aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore70
-rw-r--r--AUTHORS26
-rw-r--r--COPYRIGHT4
-rw-r--r--Makefile8
-rw-r--r--Makefile.common2
-rw-r--r--NEWS81
-rw-r--r--README24
-rw-r--r--audio/mididrv.h106
-rw-r--r--audio/midiparser.cpp2
-rw-r--r--audio/midiparser.h6
-rw-r--r--audio/midiplayer.cpp198
-rw-r--r--audio/midiplayer.h191
-rw-r--r--audio/mixer.cpp26
-rw-r--r--audio/mixer_intern.h4
-rw-r--r--audio/mods/module.cpp2
-rw-r--r--audio/mods/rjp1.cpp4
-rw-r--r--audio/module.mk2
-rw-r--r--audio/mpu401.cpp14
-rw-r--r--audio/mpu401.h29
-rw-r--r--audio/null.h1
-rw-r--r--audio/rate_arm.cpp175
-rw-r--r--audio/softsynth/adlib.cpp2
-rw-r--r--audio/softsynth/eas.cpp483
-rw-r--r--audio/softsynth/emumidi.h45
-rw-r--r--audio/softsynth/fluidsynth.cpp5
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp2
-rw-r--r--audio/softsynth/mt32.cpp11
-rw-r--r--audio/softsynth/opl/dbopl.cpp10
-rw-r--r--audio/softsynth/opl/mame.cpp6
-rw-r--r--audio/softsynth/pcspk.cpp2
-rw-r--r--audio/softsynth/ym2612.cpp4
-rw-r--r--backends/base-backend.cpp3
-rw-r--r--backends/events/gp2xsdl/gp2xsdl-events.cpp13
-rw-r--r--backends/events/gp2xsdl/gp2xsdl-events.h5
-rw-r--r--backends/events/gph/gph-events.cpp (renamed from backends/platform/gph/gph-events.cpp)150
-rw-r--r--backends/events/gph/gph-events.h56
-rw-r--r--backends/events/openpandora/op-events.cpp (renamed from backends/platform/openpandora/op-events.cpp)146
-rw-r--r--backends/events/openpandora/op-events.h44
-rw-r--r--backends/events/webossdl/webossdl-events.cpp241
-rw-r--r--backends/events/webossdl/webossdl-events.h (renamed from engines/mohawk/myst_vars.h)44
-rw-r--r--backends/events/wincesdl/wincesdl-events.cpp332
-rw-r--r--backends/events/wincesdl/wincesdl-events.h73
-rw-r--r--backends/graphics/default-palette.h6
-rw-r--r--backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp5
-rw-r--r--backends/graphics/gph/gph-graphics.cpp (renamed from backends/platform/gph/gph-graphics.cpp)176
-rw-r--r--backends/graphics/gph/gph-graphics.h62
-rw-r--r--backends/graphics/opengl/gltexture.cpp2
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp461
-rw-r--r--backends/graphics/opengl/opengl-graphics.h83
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp195
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h9
-rw-r--r--backends/graphics/openpandora/op-graphics.cpp (renamed from backends/platform/openpandora/op-graphics.cpp)22
-rw-r--r--backends/graphics/openpandora/op-graphics.h62
-rw-r--r--backends/graphics/sdl/sdl-graphics.cpp154
-rw-r--r--backends/graphics/sdl/sdl-graphics.h14
-rw-r--r--backends/graphics/wincesdl/wincesdl-graphics.cpp1639
-rw-r--r--backends/graphics/wincesdl/wincesdl-graphics.h206
-rw-r--r--backends/midi/alsa.cpp53
-rw-r--r--backends/midi/camd.cpp1
-rw-r--r--backends/midi/coreaudio.cpp17
-rw-r--r--backends/midi/coremidi.cpp11
-rw-r--r--backends/midi/dmedia.cpp3
-rw-r--r--backends/midi/seq.cpp1
-rw-r--r--backends/midi/stmidi.cpp39
-rw-r--r--backends/midi/timidity.cpp52
-rw-r--r--backends/midi/windows.cpp3
-rw-r--r--backends/mixer/wincesdl/wincesdl-mixer.cpp183
-rw-r--r--backends/mixer/wincesdl/wincesdl-mixer.h53
-rw-r--r--backends/module.mk8
-rw-r--r--backends/platform/android/README.build90
-rw-r--r--backends/platform/android/android.cpp1501
-rw-r--r--backends/platform/android/android.h307
-rw-r--r--backends/platform/android/android.mk205
-rw-r--r--backends/platform/android/asset-archive.cpp204
-rw-r--r--backends/platform/android/asset-archive.h7
-rw-r--r--backends/platform/android/events.cpp805
-rw-r--r--backends/platform/android/gfx.cpp819
-rw-r--r--backends/platform/android/jni.cpp605
-rw-r--r--backends/platform/android/jni.h151
-rw-r--r--backends/platform/android/module.mk81
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java15
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Event.java330
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java18
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVM.java710
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java411
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java10
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java232
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Unpacker.java31
-rw-r--r--backends/platform/android/texture.cpp477
-rw-r--r--backends/platform/android/texture.h277
-rw-r--r--backends/platform/android/video.cpp354
-rw-r--r--backends/platform/android/video.h140
-rw-r--r--backends/platform/dc/display.cpp7
-rw-r--r--backends/platform/dc/dreamcast.mk2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp5
-rwxr-xr-xbackends/platform/ds/build-ds.sh4
-rw-r--r--backends/platform/gp2x/build/README-GP2X54
-rwxr-xr-xbackends/platform/gp2x/build/bundle.sh10
-rw-r--r--backends/platform/gp2x/gp2x-common.h15
-rw-r--r--backends/platform/gp2x/gp2x-main.cpp10
-rw-r--r--backends/platform/gp2x/gp2x.cpp8
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-build.sh (renamed from backends/platform/gph/caanoo/build.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-bundle-debug.sh (renamed from backends/platform/gph/caanoo/bundle-debug.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-bundle.sh (renamed from backends/platform/gph/caanoo/bundle.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-config-alleng.sh (renamed from backends/platform/gph/caanoo/config-alleng.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-config.sh (renamed from backends/platform/gph/caanoo/config.sh)0
-rwxr-xr-xbackends/platform/gph/build/clean.sh2
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2x-build.sh (renamed from backends/platform/gp2x/build/build.sh)0
-rw-r--r--backends/platform/gph/build/gp2x-bundle.sh19
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2x-config-alleng.sh (renamed from backends/platform/gp2x/build/config-alleng.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2x-config.sh (renamed from backends/platform/gp2x/build/config.sh)2
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-build.sh (renamed from backends/platform/gph/build/build.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-bundle-debug.sh (renamed from backends/platform/gph/build/bundle-debug.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-bundle.sh (renamed from backends/platform/gph/build/bundle.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-config-alleng.sh (renamed from backends/platform/gph/build/config-alleng.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-config.sh (renamed from backends/platform/gph/build/config.sh)0
-rw-r--r--backends/platform/gph/build/scummvm.pngbin2656 -> 0 bytes
-rwxr-xr-xbackends/platform/gph/caanoo-bundle.mk20
-rwxr-xr-xbackends/platform/gph/caanoo/clean.sh8
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/caanoo/scummvm-gdb.gpe (renamed from backends/platform/gph/build/scummvm-gdb.gpe)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/caanoo/scummvm.gpe (renamed from backends/platform/gph/caanoo/scummvm.gpe)0
-rw-r--r--backends/platform/gph/devices/common/README-GPH (renamed from backends/platform/gph/build/README-GPH)4
-rw-r--r--backends/platform/gph/devices/common/scummvm.ini (renamed from backends/platform/gph/build/scummvm.ini)0
-rw-r--r--backends/platform/gph/devices/common/scummvm.png (renamed from backends/platform/gp2x/build/scummvm.png)bin2656 -> 2656 bytes
-rw-r--r--backends/platform/gph/devices/common/scummvmb.png (renamed from backends/platform/gph/build/scummvmb.png)bin34274 -> 34274 bytes
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/Makefile (renamed from backends/platform/gp2x/mmuhack/Makefile)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h (renamed from backends/platform/gp2x/mmuhack/flush_uppermem_cache.h)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s (renamed from backends/platform/gp2x/mmuhack/flush_uppermem_cache.s)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c (renamed from backends/platform/gp2x/mmuhack/mmuhack.c)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o (renamed from backends/platform/gp2x/build/mmuhack.o)bin1720 -> 1720 bytes
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/readme.txt (renamed from backends/platform/gp2x/mmuhack/readme.txt)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/gp2x/scummvm.gpe (renamed from backends/platform/gp2x/build/scummvm.gpe)4
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe (renamed from backends/platform/gph/caanoo/scummvm-gdb.gpe)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/gp2xwiz/scummvm.gpe (renamed from backends/platform/gph/build/scummvm.gpe)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/gp2x-bundle.mk (renamed from backends/platform/gp2x/gp2x-bundle.mk)23
-rwxr-xr-xbackends/platform/gph/gp2xwiz-bundle.mk21
-rw-r--r--backends/platform/gph/gph-backend.cpp211
-rw-r--r--backends/platform/gph/gph-main.cpp191
-rw-r--r--backends/platform/gph/gph-sdl.h53
-rw-r--r--backends/platform/gph/module.mk7
-rw-r--r--backends/platform/iphone/osys_video.cpp5
-rw-r--r--backends/platform/n64/osys_n64.h7
-rw-r--r--backends/platform/n64/osys_n64_base.cpp18
-rw-r--r--backends/platform/n64/osys_n64_events.cpp4
-rwxr-xr-xbackends/platform/openpandora/module.mk3
-rw-r--r--backends/platform/openpandora/op-backend.cpp273
-rw-r--r--backends/platform/openpandora/op-main.cpp234
-rw-r--r--backends/platform/openpandora/op-sdl.h22
-rw-r--r--backends/platform/ps2/Gs2dScreen.cpp20
-rw-r--r--backends/platform/ps2/Gs2dScreen.h4
-rw-r--r--backends/platform/ps2/systemps2.cpp4
-rw-r--r--backends/platform/psp/README.PSP2
-rw-r--r--backends/platform/psp/display_client.cpp6
-rw-r--r--backends/platform/sdl/posix/posix-main.cpp2
-rw-r--r--backends/platform/sdl/sdl.cpp26
-rw-r--r--backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in2
-rw-r--r--backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_agi.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_agos.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_base.mmp.in10
-rw-r--r--backends/platform/symbian/mmp/scummvm_cine.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_cruise.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_draci.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_drascula.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_gob.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_groovie.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_hugo.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_kyra.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_lure.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_m4.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_made.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_mohawk.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_parallaction.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_queen.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_saga.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sci.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_scumm.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sky.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sword1.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sword2.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_teenagent.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_tinsel.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_toon.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_touche.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_tucker.mmp.in2
-rw-r--r--backends/platform/webos/main.cpp53
-rw-r--r--backends/platform/webos/module.mk10
-rw-r--r--backends/platform/webos/webos.cpp73
-rw-r--r--backends/platform/webos/webos.h40
-rw-r--r--backends/platform/webos/webos.mk23
-rw-r--r--backends/platform/wii/osystem_gfx.cpp28
-rw-r--r--backends/platform/wince/CEActionsPocket.cpp58
-rw-r--r--backends/platform/wince/CEActionsSmartphone.cpp169
-rw-r--r--backends/platform/wince/CEDevice.cpp31
-rw-r--r--backends/platform/wince/CEDevice.h2
-rw-r--r--backends/platform/wince/CEException.cpp22
-rw-r--r--backends/platform/wince/CELauncherDialog.cpp9
-rw-r--r--backends/platform/wince/CEgui/GUIElement.cpp9
-rw-r--r--backends/platform/wince/CEgui/ItemAction.cpp2
-rw-r--r--backends/platform/wince/CEgui/ItemSwitch.cpp6
-rw-r--r--backends/platform/wince/CEgui/Panel.cpp11
-rw-r--r--backends/platform/wince/CEgui/Panel.h2
-rw-r--r--backends/platform/wince/CEgui/PanelItem.h2
-rw-r--r--backends/platform/wince/CEgui/PanelKeyboard.cpp21
-rw-r--r--backends/platform/wince/CEgui/SDL_ImageResource.cpp4
-rw-r--r--backends/platform/wince/CEgui/SDL_ImageResource.h4
-rw-r--r--backends/platform/wince/CEgui/ToolbarHandler.cpp13
-rw-r--r--backends/platform/wince/CEgui/ToolbarHandler.h2
-rw-r--r--backends/platform/wince/CEkeys/EventsBuffer.cpp98
-rw-r--r--backends/platform/wince/CEkeys/EventsBuffer.h16
-rw-r--r--backends/platform/wince/Makefile2
-rw-r--r--backends/platform/wince/missing/io.h6
-rw-r--r--backends/platform/wince/missing/missing.cpp60
-rw-r--r--backends/platform/wince/missing/time.h7
-rw-r--r--backends/platform/wince/portdefs.h38
-rw-r--r--backends/platform/wince/wince-sdl.cpp2113
-rw-r--r--backends/platform/wince/wince-sdl.h186
-rw-r--r--backends/saves/savefile.cpp15
-rw-r--r--backends/timer/default/default-timer.cpp2
-rw-r--r--backends/timer/default/default-timer.h6
-rw-r--r--base/commandLine.cpp3
-rw-r--r--base/plugins.cpp3
-rw-r--r--common/EventRecorder.cpp4
-rw-r--r--common/config-manager.cpp6
-rw-r--r--common/endian.h20
-rw-r--r--common/events.h24
-rw-r--r--common/hashmap.h8
-rw-r--r--common/iff_container.h96
-rw-r--r--common/list.h2
-rw-r--r--common/macresman.cpp140
-rw-r--r--common/macresman.h11
-rw-r--r--common/module.mk4
-rw-r--r--common/ne_exe.cpp612
-rw-r--r--common/savefile.h8
-rw-r--r--common/scummsys.h14
-rw-r--r--common/winexe.cpp84
-rw-r--r--common/winexe.h74
-rw-r--r--common/winexe_ne.cpp291
-rw-r--r--common/winexe_ne.h (renamed from common/ne_exe.h)100
-rw-r--r--common/winexe_pe.cpp255
-rw-r--r--common/winexe_pe.h122
-rwxr-xr-xconfigure211
-rw-r--r--devtools/README (renamed from tools/README)0
-rw-r--r--devtools/agi-palex.py (renamed from tools/agi-palex.py)0
-rwxr-xr-xdevtools/construct-pred-dict.pl (renamed from tools/construct-pred-dict.pl)0
-rw-r--r--devtools/convbdf.c (renamed from tools/convbdf.c)0
-rw-r--r--devtools/create_drascula/Makefile (renamed from tools/create_drascula/Makefile)0
-rw-r--r--devtools/create_drascula/create_drascula.cpp (renamed from tools/create_drascula/create_drascula.cpp)0
-rw-r--r--devtools/create_drascula/create_drascula.h (renamed from tools/create_drascula/create_drascula.h)0
-rw-r--r--devtools/create_drascula/dists/msvc8/create_drascula.sln (renamed from tools/create_drascula/dists/msvc8/create_drascula.sln)0
-rw-r--r--devtools/create_drascula/dists/msvc8/create_drascula.vcproj (renamed from tools/create_drascula/dists/msvc8/create_drascula.vcproj)0
-rw-r--r--devtools/create_drascula/dists/msvc8_to_msvc9.bat (renamed from tools/create_drascula/dists/msvc8_to_msvc9.bat)0
-rw-r--r--devtools/create_drascula/dists/msvc9/create_drascula.sln (renamed from tools/create_drascula/dists/msvc9/create_drascula.sln)0
-rw-r--r--devtools/create_drascula/dists/msvc9/create_drascula.vcproj (renamed from tools/create_drascula/dists/msvc9/create_drascula.vcproj)0
-rw-r--r--devtools/create_drascula/dists/msvc9_to_msvc8.bat (renamed from tools/create_drascula/dists/msvc9_to_msvc8.bat)0
-rw-r--r--devtools/create_drascula/module.mk (renamed from tools/create_drascula/module.mk)2
-rw-r--r--devtools/create_drascula/staticdata.h (renamed from tools/create_drascula/staticdata.h)0
-rw-r--r--devtools/create_hugo/Data/Btn_1.bmp (renamed from tools/create_hugo/Data/Btn_1.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_1_off.bmp (renamed from tools/create_hugo/Data/Btn_1_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_2.bmp (renamed from tools/create_hugo/Data/Btn_2.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_2_off.bmp (renamed from tools/create_hugo/Data/Btn_2_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_3.bmp (renamed from tools/create_hugo/Data/Btn_3.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_3_off.bmp (renamed from tools/create_hugo/Data/Btn_3_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_4.bmp (renamed from tools/create_hugo/Data/Btn_4.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_4_off.bmp (renamed from tools/create_hugo/Data/Btn_4_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_5.bmp (renamed from tools/create_hugo/Data/Btn_5.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_5_off.bmp (renamed from tools/create_hugo/Data/Btn_5_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_6.bmp (renamed from tools/create_hugo/Data/Btn_6.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_6_off.bmp (renamed from tools/create_hugo/Data/Btn_6_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_7.bmp (renamed from tools/create_hugo/Data/Btn_7.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_7_off.bmp (renamed from tools/create_hugo/Data/Btn_7_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_8.bmp (renamed from tools/create_hugo/Data/Btn_8.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_8_off.bmp (renamed from tools/create_hugo/Data/Btn_8_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_9.bmp (renamed from tools/create_hugo/Data/Btn_9.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/Data/Btn_9_off.bmp (renamed from tools/create_hugo/Data/Btn_9_off.bmp)bin774 -> 774 bytes
-rw-r--r--devtools/create_hugo/README (renamed from tools/create_hugo/README)0
-rw-r--r--devtools/create_hugo/create_hugo.cpp (renamed from tools/create_hugo/create_hugo.cpp)328
-rw-r--r--devtools/create_hugo/create_hugo.h (renamed from tools/create_hugo/create_hugo.h)2
-rw-r--r--devtools/create_hugo/dists/msvc10/create_hugo.sln (renamed from tools/create_hugo/dists/msvc10/create_hugo.sln)0
-rw-r--r--devtools/create_hugo/dists/msvc10/create_hugo.vcxproj (renamed from tools/create_hugo/dists/msvc10/create_hugo.vcxproj)0
-rw-r--r--devtools/create_hugo/dists/msvc9/create_hugo.sln (renamed from tools/create_hugo/dists/msvc9/create_hugo.sln)0
-rw-r--r--devtools/create_hugo/dists/msvc9/create_hugo.vcproj (renamed from tools/create_hugo/dists/msvc9/create_hugo.vcproj)0
-rw-r--r--devtools/create_hugo/enums.h (renamed from tools/create_hugo/enums.h)0
-rw-r--r--devtools/create_hugo/module.mk (renamed from tools/create_hugo/module.mk)2
-rw-r--r--devtools/create_hugo/staticdata.h (renamed from tools/create_hugo/staticdata.h)0
-rw-r--r--devtools/create_hugo/staticdisplay.h (renamed from tools/create_hugo/staticdisplay.h)66
-rw-r--r--devtools/create_hugo/staticengine.h (renamed from tools/create_hugo/staticengine.h)0
-rw-r--r--devtools/create_hugo/staticfont.h (renamed from tools/create_hugo/staticfont.h)0
-rw-r--r--devtools/create_hugo/staticintro.h (renamed from tools/create_hugo/staticintro.h)0
-rw-r--r--devtools/create_hugo/staticmouse.h (renamed from tools/create_hugo/staticmouse.h)0
-rw-r--r--devtools/create_hugo/staticparser.h (renamed from tools/create_hugo/staticparser.h)0
-rw-r--r--devtools/create_hugo/staticutil.h (renamed from tools/create_hugo/staticutil.h)0
-rw-r--r--devtools/create_kyradat/create_kyradat.cpp (renamed from tools/create_kyradat/create_kyradat.cpp)0
-rw-r--r--devtools/create_kyradat/create_kyradat.h (renamed from tools/create_kyradat/create_kyradat.h)0
-rw-r--r--devtools/create_kyradat/extract.cpp (renamed from tools/create_kyradat/extract.cpp)0
-rw-r--r--devtools/create_kyradat/extract.h (renamed from tools/create_kyradat/extract.h)0
-rw-r--r--devtools/create_kyradat/games.cpp (renamed from tools/create_kyradat/games.cpp)0
-rw-r--r--devtools/create_kyradat/md5.cpp (renamed from tools/create_kyradat/md5.cpp)0
-rw-r--r--devtools/create_kyradat/md5.h (renamed from tools/create_kyradat/md5.h)0
-rw-r--r--devtools/create_kyradat/module.mk (renamed from tools/create_kyradat/module.mk)2
-rw-r--r--devtools/create_kyradat/pak.cpp (renamed from tools/create_kyradat/pak.cpp)0
-rw-r--r--devtools/create_kyradat/pak.h (renamed from tools/create_kyradat/pak.h)0
-rw-r--r--devtools/create_kyradat/search.cpp (renamed from tools/create_kyradat/search.cpp)0
-rw-r--r--devtools/create_kyradat/search.h (renamed from tools/create_kyradat/search.h)0
-rw-r--r--devtools/create_kyradat/tables.cpp (renamed from tools/create_kyradat/tables.cpp)0
-rw-r--r--devtools/create_kyradat/tables.h (renamed from tools/create_kyradat/tables.h)0
-rw-r--r--devtools/create_kyradat/util.cpp (renamed from tools/create_kyradat/util.cpp)0
-rw-r--r--devtools/create_kyradat/util.h (renamed from tools/create_kyradat/util.h)0
-rw-r--r--devtools/create_lure/Makefile (renamed from tools/create_lure/Makefile)0
-rw-r--r--devtools/create_lure/create_lure_dat.cpp (renamed from tools/create_lure/create_lure_dat.cpp)0
-rw-r--r--devtools/create_lure/create_lure_dat.h (renamed from tools/create_lure/create_lure_dat.h)0
-rw-r--r--devtools/create_lure/dists/msvc8/create_lure.sln (renamed from tools/create_lure/dists/msvc8/create_lure.sln)0
-rw-r--r--devtools/create_lure/dists/msvc8/create_lure.vcproj (renamed from tools/create_lure/dists/msvc8/create_lure.vcproj)0
-rw-r--r--devtools/create_lure/dists/msvc8_to_msvc9.bat (renamed from tools/create_lure/dists/msvc8_to_msvc9.bat)0
-rw-r--r--devtools/create_lure/dists/msvc9/create_lure.sln (renamed from tools/create_lure/dists/msvc9/create_lure.sln)0
-rw-r--r--devtools/create_lure/dists/msvc9/create_lure.vcproj (renamed from tools/create_lure/dists/msvc9/create_lure.vcproj)0
-rw-r--r--devtools/create_lure/dists/msvc9_to_msvc8.bat (renamed from tools/create_lure/dists/msvc9_to_msvc8.bat)0
-rw-r--r--devtools/create_lure/module.mk (renamed from tools/create_lure/module.mk)2
-rw-r--r--devtools/create_lure/process_actions.cpp (renamed from tools/create_lure/process_actions.cpp)0
-rw-r--r--devtools/create_mads/Makefile (renamed from tools/create_mads/Makefile)0
-rw-r--r--devtools/create_mads/dists/msvc9/create_mads.sln (renamed from tools/create_mads/dists/msvc9/create_mads.sln)0
-rw-r--r--devtools/create_mads/dists/msvc9/create_mads.vcproj (renamed from tools/create_mads/dists/msvc9/create_mads.vcproj)0
-rw-r--r--devtools/create_mads/main.cpp (renamed from tools/create_mads/main.cpp)0
-rw-r--r--devtools/create_mads/module.mk (renamed from tools/create_mads/module.mk)2
-rw-r--r--devtools/create_mads/parser.cpp (renamed from tools/create_mads/parser.cpp)0
-rw-r--r--devtools/create_mads/parser.h (renamed from tools/create_mads/parser.h)0
-rw-r--r--devtools/create_mads/scripts/rex_nebular.txt (renamed from tools/create_mads/scripts/rex_nebular.txt)0
-rw-r--r--devtools/create_project/codeblocks.cpp (renamed from tools/create_project/codeblocks.cpp)9
-rw-r--r--devtools/create_project/codeblocks.h (renamed from tools/create_project/codeblocks.h)0
-rw-r--r--devtools/create_project/codeblocks/create_project.cbp (renamed from tools/create_project/codeblocks/create_project.cbp)0
-rw-r--r--devtools/create_project/create_project.cpp (renamed from tools/create_project/create_project.cpp)18
-rw-r--r--devtools/create_project/create_project.h (renamed from tools/create_project/create_project.h)0
-rw-r--r--devtools/create_project/module.mk (renamed from tools/create_project/module.mk)2
-rw-r--r--devtools/create_project/msbuild.cpp (renamed from tools/create_project/msbuild.cpp)0
-rw-r--r--devtools/create_project/msbuild.h (renamed from tools/create_project/msbuild.h)0
-rw-r--r--devtools/create_project/msvc.cpp (renamed from tools/create_project/msvc.cpp)4
-rw-r--r--devtools/create_project/msvc.h (renamed from tools/create_project/msvc.h)0
-rw-r--r--devtools/create_project/msvc10/create_project.sln (renamed from tools/create_project/msvc10/create_project.sln)0
-rw-r--r--devtools/create_project/msvc10/create_project.vcxproj (renamed from tools/create_project/msvc10/create_project.vcxproj)0
-rw-r--r--devtools/create_project/msvc10/create_project.vcxproj.filters (renamed from tools/create_project/msvc10/create_project.vcxproj.filters)0
-rw-r--r--devtools/create_project/msvc8/create_project.sln (renamed from tools/create_project/msvc8/create_project.sln)0
-rw-r--r--devtools/create_project/msvc8/create_project.vcproj (renamed from tools/create_project/msvc8/create_project.vcproj)0
-rw-r--r--devtools/create_project/msvc9/create_project.sln (renamed from tools/create_project/msvc9/create_project.sln)0
-rw-r--r--devtools/create_project/msvc9/create_project.vcproj (renamed from tools/create_project/msvc9/create_project.vcproj)0
-rw-r--r--devtools/create_project/scripts/postbuild.cmd (renamed from tools/create_project/scripts/postbuild.cmd)0
-rw-r--r--devtools/create_project/scripts/prebuild.cmd (renamed from tools/create_project/scripts/prebuild.cmd)2
-rw-r--r--devtools/create_project/scripts/revision.vbs (renamed from tools/create_project/scripts/revision.vbs)2
-rw-r--r--devtools/create_project/visualstudio.cpp (renamed from tools/create_project/visualstudio.cpp)3
-rw-r--r--devtools/create_project/visualstudio.h (renamed from tools/create_project/visualstudio.h)0
-rw-r--r--devtools/create_teenagent/create_teenagent.cpp (renamed from tools/create_teenagent/create_teenagent.cpp)6
-rw-r--r--devtools/create_teenagent/md5.cpp (renamed from tools/create_teenagent/md5.cpp)0
-rw-r--r--devtools/create_teenagent/md5.h (renamed from tools/create_teenagent/md5.h)0
-rw-r--r--devtools/create_teenagent/module.mk (renamed from tools/create_teenagent/module.mk)2
-rw-r--r--devtools/create_teenagent/util.h (renamed from tools/create_teenagent/util.h)0
-rw-r--r--devtools/create_toon/create_toon.cpp (renamed from tools/create_toon/create_toon.cpp)0
-rw-r--r--devtools/create_toon/create_toon.h (renamed from tools/create_toon/create_toon.h)0
-rw-r--r--devtools/create_toon/dists/msvc9/create_toon.sln (renamed from tools/create_toon/dists/msvc9/create_toon.sln)0
-rw-r--r--devtools/create_toon/dists/msvc9/create_toon.vcproj (renamed from tools/create_toon/dists/msvc9/create_toon.vcproj)0
-rw-r--r--devtools/create_toon/module.mk (renamed from tools/create_toon/module.mk)2
-rw-r--r--devtools/create_toon/staticdata.h (renamed from tools/create_toon/staticdata.h)0
-rw-r--r--devtools/create_translations/create_translations.cpp (renamed from tools/create_translations/create_translations.cpp)0
-rw-r--r--devtools/create_translations/create_translations.h (renamed from tools/create_translations/create_translations.h)0
-rw-r--r--devtools/create_translations/module.mk (renamed from tools/create_translations/module.mk)2
-rw-r--r--devtools/create_translations/po_parser.cpp (renamed from tools/create_translations/po_parser.cpp)0
-rw-r--r--devtools/create_translations/po_parser.h (renamed from tools/create_translations/po_parser.h)0
-rwxr-xr-xdevtools/credits.pl (renamed from tools/credits.pl)28
-rwxr-xr-xdevtools/dist-scummvm.sh (renamed from tools/dist-scummvm.sh)0
-rwxr-xr-xdevtools/extract-words-tok.pl (renamed from tools/extract-words-tok.pl)4
-rw-r--r--devtools/make-scumm-fontdata.c (renamed from tools/make-scumm-fontdata.c)0
-rw-r--r--devtools/md5table.c (renamed from tools/md5table.c)0
-rw-r--r--devtools/module.mk86
-rw-r--r--devtools/qtable/fat_amiga_demo.h (renamed from tools/qtable/fat_amiga_demo.h)0
-rw-r--r--devtools/qtable/fat_amiga_eng_floppy.h (renamed from tools/qtable/fat_amiga_eng_floppy.h)0
-rw-r--r--devtools/qtable/fat_amiga_interview.h (renamed from tools/qtable/fat_amiga_interview.h)0
-rw-r--r--devtools/qtable/fat_eng_cdrom.h (renamed from tools/qtable/fat_eng_cdrom.h)0
-rw-r--r--devtools/qtable/fat_eng_floppy.h (renamed from tools/qtable/fat_eng_floppy.h)0
-rw-r--r--devtools/qtable/fat_fre_cdrom.h (renamed from tools/qtable/fat_fre_cdrom.h)0
-rw-r--r--devtools/qtable/fat_fre_floppy.h (renamed from tools/qtable/fat_fre_floppy.h)0
-rw-r--r--devtools/qtable/fat_ger_cdrom.h (renamed from tools/qtable/fat_ger_cdrom.h)0
-rw-r--r--devtools/qtable/fat_ger_floppy.h (renamed from tools/qtable/fat_ger_floppy.h)0
-rw-r--r--devtools/qtable/fat_heb_cdrom.h (renamed from tools/qtable/fat_heb_cdrom.h)0
-rw-r--r--devtools/qtable/fat_ita_cdrom.h (renamed from tools/qtable/fat_ita_cdrom.h)0
-rw-r--r--devtools/qtable/fat_ita_floppy.h (renamed from tools/qtable/fat_ita_floppy.h)0
-rw-r--r--devtools/qtable/fat_pc_demo.h (renamed from tools/qtable/fat_pc_demo.h)0
-rw-r--r--devtools/qtable/fat_pc_demo_pcgames.h (renamed from tools/qtable/fat_pc_demo_pcgames.h)0
-rw-r--r--devtools/qtable/fat_pc_interview.h (renamed from tools/qtable/fat_pc_interview.h)0
-rw-r--r--devtools/qtable/fat_spa_cdrom.h (renamed from tools/qtable/fat_spa_cdrom.h)0
-rw-r--r--devtools/qtable/module.mk (renamed from tools/qtable/module.mk)2
-rw-r--r--devtools/qtable/qtable.cpp (renamed from tools/qtable/qtable.cpp)0
-rw-r--r--devtools/sci/musicplayer.cpp (renamed from tools/sci/musicplayer.cpp)0
-rw-r--r--devtools/sci/scidisasm.cpp (renamed from tools/sci/scidisasm.cpp)0
-rw-r--r--devtools/sci/scipack.cpp (renamed from tools/sci/scipack.cpp)0
-rw-r--r--devtools/sci/scitrace.asm (renamed from tools/sci/scitrace.asm)0
-rw-r--r--devtools/scumm-md5.txt (renamed from tools/scumm-md5.txt)0
-rw-r--r--devtools/skycpt/288diff.txt (renamed from tools/skycpt/288diff.txt)0
-rw-r--r--devtools/skycpt/AsciiCptCompile.cpp (renamed from tools/skycpt/AsciiCptCompile.cpp)0
-rw-r--r--devtools/skycpt/AsciiCptCompile.sln (renamed from tools/skycpt/AsciiCptCompile.sln)0
-rw-r--r--devtools/skycpt/AsciiCptCompile.vcproj (renamed from tools/skycpt/AsciiCptCompile.vcproj)0
-rw-r--r--devtools/skycpt/COMPACT.TXT (renamed from tools/skycpt/COMPACT.TXT)0
-rw-r--r--devtools/skycpt/KmpSearch.cpp (renamed from tools/skycpt/KmpSearch.cpp)0
-rw-r--r--devtools/skycpt/KmpSearch.h (renamed from tools/skycpt/KmpSearch.h)0
-rw-r--r--devtools/skycpt/README (renamed from tools/skycpt/README)0
-rw-r--r--devtools/skycpt/TextFile.cpp (renamed from tools/skycpt/TextFile.cpp)0
-rw-r--r--devtools/skycpt/TextFile.h (renamed from tools/skycpt/TextFile.h)0
-rw-r--r--devtools/skycpt/cptcompiler.cpp (renamed from tools/skycpt/cptcompiler.cpp)6
-rw-r--r--devtools/skycpt/cpthelp.cpp (renamed from tools/skycpt/cpthelp.cpp)0
-rw-r--r--devtools/skycpt/cpthelp.h (renamed from tools/skycpt/cpthelp.h)0
-rw-r--r--devtools/skycpt/idFinder.cpp (renamed from tools/skycpt/idFinder.cpp)0
-rw-r--r--devtools/skycpt/module.mk (renamed from tools/skycpt/module.mk)2
-rw-r--r--devtools/skycpt/savedata.txt (renamed from tools/skycpt/savedata.txt)0
-rw-r--r--devtools/skycpt/skycpt-engine.patch (renamed from tools/skycpt/skycpt-engine.patch)0
-rw-r--r--devtools/skycpt/stdafx.cpp (renamed from tools/skycpt/stdafx.cpp)0
-rw-r--r--devtools/skycpt/stdafx.h (renamed from tools/skycpt/stdafx.h)0
-rw-r--r--devtools/themeparser.py (renamed from tools/themeparser.py)0
-rwxr-xr-xdevtools/update-version.pl (renamed from tools/update-version.pl)1
-rw-r--r--dists/android/AndroidManifest.xml113
-rw-r--r--dists/android/AndroidManifest.xml.in113
-rw-r--r--dists/android/README.Android56
-rwxr-xr-xdists/android/mkmanifest.pl170
-rwxr-xr-xdists/android/mkplugin.sh17
-rw-r--r--dists/android/plugin-manifest.xml35
-rw-r--r--dists/android/plugin-manifest.xml.in35
-rw-r--r--dists/android/plugin-strings.xml7
-rw-r--r--dists/android/res/layout/main.xml17
-rw-r--r--dists/engine-data/hugo.datbin189600 -> 189584 bytes
-rw-r--r--dists/iphone/Info.plist4
-rw-r--r--dists/irix/scummvm.spec2
-rw-r--r--dists/macosx/Info.plist6
-rw-r--r--dists/msvc10/readme.txt2
-rw-r--r--dists/msvc8/readme.txt2
-rw-r--r--dists/msvc9/readme.txt2
-rw-r--r--dists/redhat/scummvm-tools.spec2
-rw-r--r--dists/redhat/scummvm.spec2
-rw-r--r--dists/scummvm.rc27
-rw-r--r--dists/scummvm.rc.in21
-rwxr-xr-xdists/slackware/scummvm.SlackBuild2
-rw-r--r--dists/webos/README.WebOS37
-rw-r--r--dists/webos/mojo/appinfo.json10
-rw-r--r--dists/webos/mojo/icon.pngbin0 -> 3290 bytes
-rw-r--r--dists/webos/mojo/package.properties1
-rw-r--r--dists/webos/mojo/scummvmrc-default36
-rwxr-xr-xdists/webos/mojo/start32
-rw-r--r--dists/wii/meta.xml2
-rw-r--r--engines/agi/agi.cpp27
-rw-r--r--engines/agi/agi.h5
-rw-r--r--engines/agi/detection.cpp4
-rw-r--r--engines/agi/detection_tables.h5
-rw-r--r--engines/agi/graphics.cpp27
-rw-r--r--engines/agi/graphics.h2
-rw-r--r--engines/agi/preagi.cpp6
-rw-r--r--engines/agi/preagi_mickey.cpp4
-rw-r--r--engines/agi/preagi_winnie.cpp4
-rw-r--r--engines/agi/saveload.cpp2
-rw-r--r--engines/agi/sound_2gs.cpp52
-rw-r--r--engines/agi/sound_2gs.h4
-rw-r--r--engines/agi/sound_midi.cpp182
-rw-r--r--engines/agi/sound_midi.h65
-rw-r--r--engines/agos/agos.cpp38
-rw-r--r--engines/agos/agos.h8
-rw-r--r--engines/agos/animation.cpp8
-rw-r--r--engines/agos/cursor.cpp6
-rw-r--r--engines/agos/debug.cpp22
-rw-r--r--engines/agos/draw.cpp12
-rw-r--r--engines/agos/gfx.cpp2
-rw-r--r--engines/agos/icons.cpp4
-rw-r--r--engines/agos/midi.cpp66
-rw-r--r--engines/agos/midi.h28
-rw-r--r--engines/agos/oracle.cpp6
-rw-r--r--engines/agos/pn.cpp7
-rw-r--r--engines/agos/script_ff.cpp5
-rw-r--r--engines/agos/script_s1.cpp6
-rw-r--r--engines/agos/string.cpp3
-rw-r--r--engines/agos/vga.cpp29
-rw-r--r--engines/agos/vga_e2.cpp7
-rw-r--r--engines/agos/vga_s1.cpp10
-rw-r--r--engines/agos/window.cpp12
-rw-r--r--engines/cine/bg.cpp7
-rw-r--r--engines/cine/cine.cpp25
-rw-r--r--engines/cine/cine.h2
-rw-r--r--engines/cine/pal.cpp8
-rw-r--r--engines/cine/saveload.cpp13
-rw-r--r--engines/cine/saveload.h4
-rw-r--r--engines/cine/script_os.cpp2
-rw-r--r--engines/cruise/backgroundIncrust.cpp6
-rw-r--r--engines/cruise/cruise.cpp11
-rw-r--r--engines/cruise/cruise_main.cpp16
-rw-r--r--engines/cruise/dataLoader.cpp4
-rw-r--r--engines/cruise/gfxModule.cpp11
-rw-r--r--engines/cruise/linker.cpp4
-rw-r--r--engines/cruise/mainDraw.cpp4
-rw-r--r--engines/cruise/mouse.cpp4
-rw-r--r--engines/cruise/script.cpp4
-rw-r--r--engines/cruise/sound.cpp16
-rw-r--r--engines/draci/draci.cpp15
-rw-r--r--engines/draci/draci.h1
-rw-r--r--engines/draci/music.cpp184
-rw-r--r--engines/draci/music.h57
-rw-r--r--engines/draci/screen.cpp20
-rw-r--r--engines/draci/sound.cpp11
-rw-r--r--engines/drascula/drascula.cpp8
-rw-r--r--engines/drascula/palette.cpp13
-rw-r--r--engines/drascula/rooms.cpp4
-rw-r--r--engines/engine.cpp15
-rw-r--r--engines/engine.h11
-rw-r--r--engines/engines.mk12
-rw-r--r--engines/gob/detection_tables.h30
-rw-r--r--engines/gob/gob.cpp3
-rw-r--r--engines/gob/inter_v2.cpp5
-rw-r--r--engines/gob/save/savefile.h14
-rw-r--r--engines/gob/save/saveload.h4
-rw-r--r--engines/gob/save/saveload_inca2.cpp4
-rw-r--r--engines/gob/save/saveload_v3.cpp6
-rw-r--r--engines/gob/sound/bgatmosphere.cpp4
-rw-r--r--engines/gob/sound/bgatmosphere.h4
-rw-r--r--engines/gob/sound/sound.cpp10
-rw-r--r--engines/gob/surface.cpp10
-rw-r--r--engines/gob/util.cpp4
-rw-r--r--engines/gob/video.cpp10
-rw-r--r--engines/gob/video.h1
-rw-r--r--engines/groovie/cursor.cpp11
-rw-r--r--engines/groovie/debug.cpp4
-rw-r--r--engines/groovie/graphics.cpp14
-rw-r--r--engines/groovie/graphics.h2
-rw-r--r--engines/groovie/groovie.cpp2
-rw-r--r--engines/groovie/music.cpp61
-rw-r--r--engines/groovie/music.h16
-rw-r--r--engines/groovie/roq.cpp27
-rw-r--r--engines/groovie/vdx.cpp9
-rw-r--r--engines/hugo/detection.cpp5
-rw-r--r--engines/hugo/dialogs.cpp (renamed from engines/hugo/menu.cpp)37
-rw-r--r--engines/hugo/dialogs.h (renamed from engines/hugo/menu.h)29
-rw-r--r--engines/hugo/display.cpp131
-rw-r--r--engines/hugo/display.h48
-rw-r--r--engines/hugo/file.cpp176
-rw-r--r--engines/hugo/file.h22
-rw-r--r--engines/hugo/file_v1d.cpp5
-rw-r--r--engines/hugo/file_v1w.cpp3
-rw-r--r--engines/hugo/file_v2d.cpp3
-rw-r--r--engines/hugo/file_v2w.cpp2
-rw-r--r--engines/hugo/file_v3d.cpp8
-rw-r--r--engines/hugo/game.h117
-rw-r--r--engines/hugo/hugo.cpp431
-rw-r--r--engines/hugo/hugo.h92
-rw-r--r--engines/hugo/intro.cpp82
-rw-r--r--engines/hugo/intro.h11
-rw-r--r--engines/hugo/inventory.cpp60
-rw-r--r--engines/hugo/inventory.h16
-rw-r--r--engines/hugo/module.mk2
-rw-r--r--engines/hugo/mouse.cpp96
-rw-r--r--engines/hugo/mouse.h31
-rw-r--r--engines/hugo/object.cpp305
-rw-r--r--engines/hugo/object.h48
-rw-r--r--engines/hugo/object_v1d.cpp2
-rw-r--r--engines/hugo/object_v1w.cpp2
-rw-r--r--engines/hugo/object_v2d.cpp2
-rw-r--r--engines/hugo/object_v3d.cpp2
-rw-r--r--engines/hugo/parser.cpp156
-rw-r--r--engines/hugo/parser.h50
-rw-r--r--engines/hugo/parser_v1d.cpp63
-rw-r--r--engines/hugo/parser_v1w.cpp30
-rw-r--r--engines/hugo/parser_v2d.cpp33
-rw-r--r--engines/hugo/parser_v3d.cpp70
-rw-r--r--engines/hugo/route.cpp8
-rw-r--r--engines/hugo/route.h4
-rw-r--r--engines/hugo/schedule.cpp1421
-rw-r--r--engines/hugo/schedule.h98
-rw-r--r--engines/hugo/sound.cpp195
-rw-r--r--engines/hugo/sound.h47
-rw-r--r--engines/hugo/text.cpp52
-rw-r--r--engines/hugo/text.h24
-rw-r--r--engines/hugo/util.cpp78
-rw-r--r--engines/hugo/util.h27
-rw-r--r--engines/kyra/animator_mr.cpp1
-rw-r--r--engines/kyra/gui_lok.cpp7
-rw-r--r--engines/kyra/gui_lok.h1
-rw-r--r--engines/kyra/gui_mr.cpp14
-rw-r--r--engines/kyra/gui_mr.h2
-rw-r--r--engines/kyra/kyra_hof.cpp89
-rw-r--r--engines/kyra/kyra_hof.h6
-rw-r--r--engines/kyra/kyra_lok.cpp20
-rw-r--r--engines/kyra/kyra_lok.h13
-rw-r--r--engines/kyra/kyra_mr.cpp66
-rw-r--r--engines/kyra/kyra_mr.h3
-rw-r--r--engines/kyra/kyra_v1.cpp6
-rw-r--r--engines/kyra/kyra_v1.h3
-rw-r--r--engines/kyra/kyra_v2.cpp5
-rw-r--r--engines/kyra/kyra_v2.h3
-rw-r--r--engines/kyra/lol.cpp12
-rw-r--r--engines/kyra/resource.h2
-rw-r--r--engines/kyra/resource_intern.cpp2
-rw-r--r--engines/kyra/saveload.cpp14
-rw-r--r--engines/kyra/saveload_hof.cpp2
-rw-r--r--engines/kyra/saveload_lok.cpp2
-rw-r--r--engines/kyra/saveload_lol.cpp2
-rw-r--r--engines/kyra/saveload_mr.cpp2
-rw-r--r--engines/kyra/scene_lok.cpp17
-rw-r--r--engines/kyra/scene_mr.cpp50
-rw-r--r--engines/kyra/scene_v2.cpp11
-rw-r--r--engines/kyra/screen.cpp43
-rw-r--r--engines/kyra/screen_lok.cpp9
-rw-r--r--engines/kyra/screen_lol.cpp3
-rw-r--r--engines/kyra/script.cpp6
-rw-r--r--engines/kyra/script.h4
-rw-r--r--engines/kyra/script_mr.cpp6
-rw-r--r--engines/kyra/script_tim.cpp4
-rw-r--r--engines/kyra/sequences_hof.cpp10
-rw-r--r--engines/kyra/sequences_lok.cpp255
-rw-r--r--engines/kyra/sound_intern.h8
-rw-r--r--engines/kyra/sound_midi.cpp17
-rw-r--r--engines/kyra/text_mr.cpp4
-rw-r--r--engines/kyra/timer_lok.cpp9
-rw-r--r--engines/kyra/vqa.cpp42
-rw-r--r--engines/lastexpress/lastexpress.cpp4
-rw-r--r--engines/lure/lure.cpp6
-rw-r--r--engines/lure/screen.cpp24
-rw-r--r--engines/lure/screen.h2
-rw-r--r--engines/lure/sound.cpp27
-rw-r--r--engines/lure/sound.h32
-rw-r--r--engines/m4/assets.h16
-rw-r--r--engines/m4/converse.cpp48
-rw-r--r--engines/m4/dialogs.cpp4
-rw-r--r--engines/m4/font.cpp8
-rw-r--r--engines/m4/graphics.cpp7
-rw-r--r--engines/m4/graphics.h6
-rw-r--r--engines/m4/m4.cpp15
-rw-r--r--engines/m4/m4.h1
-rw-r--r--engines/m4/m4_views.h2
-rw-r--r--engines/m4/mads_scene.cpp10
-rw-r--r--engines/m4/midi.cpp136
-rw-r--r--engines/m4/midi.h46
-rw-r--r--engines/m4/rails.cpp5
-rw-r--r--engines/m4/resource.cpp5
-rw-r--r--engines/m4/scene.cpp8
-rw-r--r--engines/m4/woodscript.cpp10
-rw-r--r--engines/made/database.cpp6
-rw-r--r--engines/made/made.cpp27
-rw-r--r--engines/made/music.cpp146
-rw-r--r--engines/made/music.h52
-rw-r--r--engines/made/pmvplayer.cpp10
-rw-r--r--engines/made/resource.cpp12
-rw-r--r--engines/made/resource.h20
-rw-r--r--engines/made/screen.cpp11
-rw-r--r--engines/made/screen.h1
-rw-r--r--engines/mohawk/bitmap.cpp29
-rw-r--r--engines/mohawk/bitmap.h10
-rw-r--r--engines/mohawk/console.cpp69
-rw-r--r--engines/mohawk/console.h22
-rw-r--r--engines/mohawk/cstime_game.cpp8
-rw-r--r--engines/mohawk/cstime_ui.cpp40
-rw-r--r--engines/mohawk/cstime_ui.h6
-rw-r--r--engines/mohawk/cstime_view.cpp4
-rw-r--r--engines/mohawk/cursors.cpp239
-rw-r--r--engines/mohawk/cursors.h86
-rw-r--r--engines/mohawk/detection.cpp50
-rw-r--r--engines/mohawk/detection_tables.h286
-rw-r--r--engines/mohawk/dialogs.cpp30
-rw-r--r--engines/mohawk/dialogs.h14
-rw-r--r--engines/mohawk/graphics.cpp138
-rw-r--r--engines/mohawk/graphics.h69
-rw-r--r--engines/mohawk/installer_archive.cpp86
-rw-r--r--engines/mohawk/livingbooks.cpp679
-rw-r--r--engines/mohawk/livingbooks.h119
-rw-r--r--engines/mohawk/livingbooks_code.cpp1110
-rw-r--r--engines/mohawk/livingbooks_code.h191
-rw-r--r--engines/mohawk/module.mk40
-rw-r--r--engines/mohawk/mohawk.cpp4
-rw-r--r--engines/mohawk/myst.cpp38
-rw-r--r--engines/mohawk/myst.h2
-rw-r--r--engines/mohawk/myst_areas.h1
-rw-r--r--engines/mohawk/myst_scripts.cpp4
-rw-r--r--engines/mohawk/myst_stacks/channelwood.cpp86
-rw-r--r--engines/mohawk/myst_stacks/channelwood.h14
-rw-r--r--engines/mohawk/myst_stacks/credits.cpp18
-rw-r--r--engines/mohawk/myst_stacks/credits.h14
-rw-r--r--engines/mohawk/myst_stacks/demo.cpp30
-rw-r--r--engines/mohawk/myst_stacks/demo.h14
-rw-r--r--engines/mohawk/myst_stacks/dni.cpp26
-rw-r--r--engines/mohawk/myst_stacks/dni.h14
-rw-r--r--engines/mohawk/myst_stacks/intro.cpp26
-rw-r--r--engines/mohawk/myst_stacks/intro.h14
-rw-r--r--engines/mohawk/myst_stacks/makingof.cpp14
-rw-r--r--engines/mohawk/myst_stacks/makingof.h14
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp465
-rw-r--r--engines/mohawk/myst_stacks/mechanical.h62
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp350
-rw-r--r--engines/mohawk/myst_stacks/myst.h14
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp24
-rw-r--r--engines/mohawk/myst_stacks/preview.h14
-rw-r--r--engines/mohawk/myst_stacks/selenitic.cpp98
-rw-r--r--engines/mohawk/myst_stacks/selenitic.h14
-rw-r--r--engines/mohawk/myst_stacks/slides.cpp20
-rw-r--r--engines/mohawk/myst_stacks/slides.h14
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp106
-rw-r--r--engines/mohawk/myst_stacks/stoneship.h14
-rw-r--r--engines/mohawk/myst_vars.cpp578
-rw-r--r--engines/mohawk/resource.h148
-rw-r--r--engines/mohawk/riven.cpp152
-rw-r--r--engines/mohawk/riven.h29
-rw-r--r--engines/mohawk/riven_cursors.h670
-rw-r--r--engines/mohawk/riven_external.cpp793
-rw-r--r--engines/mohawk/riven_external.h5
-rw-r--r--engines/mohawk/riven_saveload.cpp46
-rw-r--r--engines/mohawk/riven_scripts.cpp99
-rw-r--r--engines/mohawk/riven_scripts.h19
-rw-r--r--engines/mohawk/riven_vars.cpp95
-rw-r--r--engines/mohawk/sound.cpp15
-rw-r--r--engines/mohawk/sound.h3
-rw-r--r--engines/mohawk/video.cpp5
-rw-r--r--engines/mohawk/video.h1
-rw-r--r--engines/mohawk/view.cpp10
-rw-r--r--engines/parallaction/disk_ns.cpp4
-rw-r--r--engines/parallaction/graphics.cpp26
-rw-r--r--engines/parallaction/graphics.h2
-rw-r--r--engines/parallaction/parallaction.cpp2
-rw-r--r--engines/parallaction/parallaction_br.cpp4
-rw-r--r--engines/parallaction/parallaction_ns.cpp4
-rw-r--r--engines/parallaction/sound.h4
-rw-r--r--engines/parallaction/sound_br.cpp172
-rw-r--r--engines/parallaction/sound_ns.cpp184
-rw-r--r--engines/queen/command.cpp11
-rw-r--r--engines/queen/display.cpp16
-rw-r--r--engines/queen/midiadlib.cpp2
-rw-r--r--engines/queen/music.cpp41
-rw-r--r--engines/queen/music.h26
-rw-r--r--engines/queen/queen.cpp19
-rw-r--r--engines/queen/resource.cpp4
-rw-r--r--engines/queen/sound.cpp8
-rw-r--r--engines/saga/detection.cpp7
-rw-r--r--engines/saga/font.cpp3
-rw-r--r--engines/saga/gfx.cpp50
-rw-r--r--engines/saga/gfx.h2
-rw-r--r--engines/saga/image.cpp2
-rw-r--r--engines/saga/music.cpp183
-rw-r--r--engines/saga/music.h49
-rw-r--r--engines/saga/resource_hrs.cpp2
-rw-r--r--engines/saga/resource_rsc.cpp2
-rw-r--r--engines/saga/saga.cpp2
-rw-r--r--engines/saga/saveload.cpp6
-rw-r--r--engines/saga/script.cpp4
-rw-r--r--engines/saga/sound.cpp8
-rw-r--r--engines/sci/console.cpp129
-rw-r--r--engines/sci/console.h3
-rw-r--r--engines/sci/debug.h12
-rw-r--r--engines/sci/detection_tables.h70
-rw-r--r--engines/sci/engine/features.cpp20
-rw-r--r--engines/sci/engine/gc.cpp61
-rw-r--r--engines/sci/engine/gc.h9
-rw-r--r--engines/sci/engine/kernel.cpp1
-rw-r--r--engines/sci/engine/kernel.h5
-rw-r--r--engines/sci/engine/kernel_tables.h18
-rw-r--r--engines/sci/engine/kevent.cpp109
-rw-r--r--engines/sci/engine/kfile.cpp12
-rw-r--r--engines/sci/engine/kgraphics.cpp192
-rw-r--r--engines/sci/engine/kmath.cpp14
-rw-r--r--engines/sci/engine/kmenu.cpp3
-rw-r--r--engines/sci/engine/kmisc.cpp89
-rw-r--r--engines/sci/engine/kmovement.cpp62
-rw-r--r--engines/sci/engine/kparse.cpp4
-rw-r--r--engines/sci/engine/kpathing.cpp12
-rw-r--r--engines/sci/engine/kscripts.cpp38
-rw-r--r--engines/sci/engine/kstring.cpp24
-rw-r--r--engines/sci/engine/kvideo.cpp4
-rw-r--r--engines/sci/engine/object.cpp64
-rw-r--r--engines/sci/engine/savegame.cpp51
-rw-r--r--engines/sci/engine/script.cpp34
-rw-r--r--engines/sci/engine/script_patches.cpp416
-rw-r--r--engines/sci/engine/scriptdebug.cpp217
-rw-r--r--engines/sci/engine/seg_manager.cpp45
-rw-r--r--engines/sci/engine/seg_manager.h11
-rw-r--r--engines/sci/engine/segment.cpp190
-rw-r--r--engines/sci/engine/segment.h104
-rw-r--r--engines/sci/engine/selector.cpp1
-rw-r--r--engines/sci/engine/selector.h1
-rw-r--r--engines/sci/engine/state.cpp3
-rw-r--r--engines/sci/engine/state.h9
-rw-r--r--engines/sci/engine/static_selectors.cpp214
-rw-r--r--engines/sci/engine/vm.cpp1253
-rw-r--r--engines/sci/engine/vm.h28
-rw-r--r--engines/sci/engine/vm_types.cpp227
-rw-r--r--engines/sci/engine/vm_types.h96
-rw-r--r--engines/sci/engine/workarounds.cpp126
-rw-r--r--engines/sci/engine/workarounds.h12
-rw-r--r--engines/sci/event.cpp360
-rw-r--r--engines/sci/event.h15
-rw-r--r--engines/sci/graphics/animate.cpp363
-rw-r--r--engines/sci/graphics/animate.h6
-rw-r--r--engines/sci/graphics/compare.cpp25
-rw-r--r--engines/sci/graphics/cursor.cpp29
-rw-r--r--engines/sci/graphics/frameout.cpp32
-rw-r--r--engines/sci/graphics/frameout.h3
-rw-r--r--engines/sci/graphics/helpers.h18
-rw-r--r--engines/sci/graphics/maciconbar.cpp259
-rw-r--r--engines/sci/graphics/maciconbar.h30
-rw-r--r--engines/sci/graphics/menu.cpp34
-rw-r--r--engines/sci/graphics/paint.cpp3
-rw-r--r--engines/sci/graphics/paint.h1
-rw-r--r--engines/sci/graphics/paint16.cpp36
-rw-r--r--engines/sci/graphics/paint16.h1
-rw-r--r--engines/sci/graphics/paint32.cpp11
-rw-r--r--engines/sci/graphics/paint32.h1
-rw-r--r--engines/sci/graphics/palette.cpp201
-rw-r--r--engines/sci/graphics/palette.h9
-rw-r--r--engines/sci/graphics/picture.cpp202
-rw-r--r--engines/sci/graphics/ports.cpp102
-rw-r--r--engines/sci/graphics/ports.h22
-rw-r--r--engines/sci/graphics/screen.cpp128
-rw-r--r--engines/sci/graphics/screen.h29
-rw-r--r--engines/sci/graphics/text16.cpp11
-rw-r--r--engines/sci/graphics/transitions.cpp30
-rw-r--r--engines/sci/graphics/transitions.h3
-rw-r--r--engines/sci/graphics/view.cpp337
-rw-r--r--engines/sci/graphics/view.h14
-rw-r--r--engines/sci/module.mk1
-rw-r--r--engines/sci/parser/grammar.cpp3
-rw-r--r--engines/sci/parser/said.cpp2
-rw-r--r--engines/sci/parser/vocabulary.cpp2
-rw-r--r--engines/sci/parser/vocabulary.h3
-rw-r--r--engines/sci/resource.cpp130
-rw-r--r--engines/sci/resource.h3
-rw-r--r--engines/sci/resource_audio.cpp8
-rw-r--r--engines/sci/sci.cpp176
-rw-r--r--engines/sci/sci.h40
-rw-r--r--engines/sci/sound/audio.cpp12
-rw-r--r--engines/sci/sound/drivers/adlib.cpp14
-rw-r--r--engines/sci/sound/drivers/amigamac.cpp72
-rw-r--r--engines/sci/sound/drivers/cms.cpp2
-rw-r--r--engines/sci/sound/drivers/fb01.cpp2
-rw-r--r--engines/sci/sound/drivers/midi.cpp94
-rw-r--r--engines/sci/sound/drivers/mididriver.h6
-rw-r--r--engines/sci/sound/music.cpp89
-rw-r--r--engines/sci/sound/soundcmd.cpp20
-rw-r--r--engines/sci/util.cpp26
-rw-r--r--engines/sci/util.h5
-rw-r--r--engines/sci/video/robot_decoder.cpp5
-rw-r--r--engines/scumm/actor.cpp27
-rw-r--r--engines/scumm/actor.h41
-rw-r--r--engines/scumm/actor_he.h92
-rw-r--r--engines/scumm/akos.cpp32
-rw-r--r--engines/scumm/charset.cpp41
-rw-r--r--engines/scumm/cursor.cpp10
-rw-r--r--engines/scumm/debugger.cpp2
-rw-r--r--engines/scumm/detection.cpp160
-rw-r--r--engines/scumm/gfx.cpp42
-rw-r--r--engines/scumm/he/animation_he.cpp2
-rw-r--r--engines/scumm/he/cup_player_he.cpp44
-rw-r--r--engines/scumm/he/cup_player_he.h2
-rw-r--r--engines/scumm/he/floodfill_he.cpp4
-rw-r--r--engines/scumm/he/intern_he.h13
-rw-r--r--engines/scumm/he/logic_he.cpp6
-rw-r--r--engines/scumm/he/palette_he.cpp21
-rw-r--r--engines/scumm/he/resource_he.cpp1114
-rw-r--r--engines/scumm/he/resource_he.h381
-rw-r--r--engines/scumm/he/script_v100he.cpp2
-rw-r--r--engines/scumm/he/script_v60he.cpp10
-rw-r--r--engines/scumm/he/script_v71he.cpp8
-rw-r--r--engines/scumm/he/script_v72he.cpp37
-rw-r--r--engines/scumm/he/script_v90he.cpp12
-rw-r--r--engines/scumm/he/sound_he.cpp38
-rw-r--r--engines/scumm/he/sprite_he.cpp2
-rw-r--r--engines/scumm/he/wiz_he.cpp76
-rw-r--r--engines/scumm/help.cpp24
-rw-r--r--engines/scumm/imuse/imuse.cpp39
-rw-r--r--engines/scumm/imuse/imuse.h1
-rw-r--r--engines/scumm/imuse/imuse_internal.h13
-rw-r--r--engines/scumm/imuse/imuse_player.cpp18
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp1
-rw-r--r--engines/scumm/imuse_digi/dimuse_bndmgr.cpp7
-rw-r--r--engines/scumm/imuse_digi/dimuse_bndmgr.h8
-rw-r--r--engines/scumm/imuse_digi/dimuse_codecs.cpp297
-rw-r--r--engines/scumm/imuse_digi/dimuse_codecs.h44
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.cpp42
-rw-r--r--engines/scumm/insane/insane.cpp2
-rw-r--r--engines/scumm/insane/insane_iact.cpp20
-rw-r--r--engines/scumm/nut_renderer.cpp8
-rw-r--r--engines/scumm/object.cpp88
-rw-r--r--engines/scumm/palette.cpp12
-rw-r--r--engines/scumm/player_pce.cpp4
-rw-r--r--engines/scumm/player_sid.cpp18
-rw-r--r--engines/scumm/player_towns.cpp8
-rw-r--r--engines/scumm/resource.cpp186
-rw-r--r--engines/scumm/resource_v3.cpp4
-rw-r--r--engines/scumm/resource_v4.cpp4
-rw-r--r--engines/scumm/room.cpp49
-rw-r--r--engines/scumm/saveload.cpp16
-rw-r--r--engines/scumm/script.cpp44
-rw-r--r--engines/scumm/script.h21
-rw-r--r--engines/scumm/script_v5.cpp24
-rw-r--r--engines/scumm/script_v6.cpp8
-rw-r--r--engines/scumm/scumm.cpp37
-rw-r--r--engines/scumm/scumm.h34
-rw-r--r--engines/scumm/scumm_v3.h2
-rw-r--r--engines/scumm/scumm_v4.h2
-rw-r--r--engines/scumm/smush/imuse_channel.cpp37
-rw-r--r--engines/scumm/smush/saud_channel.cpp10
-rw-r--r--engines/scumm/smush/smush_player.cpp46
-rw-r--r--engines/scumm/sound.cpp87
-rw-r--r--engines/scumm/verbs.cpp2
-rw-r--r--engines/sky/control.cpp2
-rw-r--r--engines/sky/debug.cpp4
-rw-r--r--engines/sky/intro.cpp17
-rw-r--r--engines/sky/music/gmmusic.cpp4
-rw-r--r--engines/sky/music/musicbase.cpp9
-rw-r--r--engines/sky/screen.cpp246
-rw-r--r--engines/sky/screen.h14
-rw-r--r--engines/sky/sky.cpp43
-rw-r--r--engines/sky/sky.h4
-rw-r--r--engines/sword1/animation.cpp2
-rw-r--r--engines/sword1/control.cpp20
-rw-r--r--engines/sword1/control.h2
-rw-r--r--engines/sword1/mouse.cpp11
-rw-r--r--engines/sword1/mouse.h3
-rw-r--r--engines/sword1/screen.cpp18
-rw-r--r--engines/sword1/screen.h4
-rw-r--r--engines/sword1/sword1.cpp5
-rw-r--r--engines/sword2/animation.cpp40
-rw-r--r--engines/sword2/animation.h6
-rw-r--r--engines/sword2/console.cpp2
-rw-r--r--engines/sword2/function.cpp12
-rw-r--r--engines/sword2/mouse.cpp4
-rw-r--r--engines/sword2/palette.cpp41
-rw-r--r--engines/sword2/protocol.cpp15
-rw-r--r--engines/sword2/render.cpp24
-rw-r--r--engines/sword2/screen.cpp29
-rw-r--r--engines/sword2/screen.h2
-rw-r--r--engines/sword2/sprite.cpp18
-rw-r--r--engines/sword2/sword2.cpp5
-rw-r--r--engines/sword2/sword2.h2
-rw-r--r--engines/sword25/gfx/graphicengine_script.cpp51
-rw-r--r--engines/sword25/gfx/image/art.cpp60
-rw-r--r--engines/sword25/gfx/image/art.h145
-rw-r--r--engines/sword25/gfx/image/image.h144
-rw-r--r--engines/sword25/gfx/image/pngloader.cpp32
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp18
-rw-r--r--engines/sword25/gfx/image/renderedimage.h24
-rw-r--r--engines/sword25/gfx/image/swimage.cpp8
-rw-r--r--engines/sword25/gfx/image/vectorimage.cpp102
-rw-r--r--engines/sword25/gfx/image/vectorimagerenderer.cpp24
-rw-r--r--engines/sword25/math/geometry_script.cpp29
-rw-r--r--engines/sword25/script/luabindhelper.cpp21
-rw-r--r--engines/sword25/script/luabindhelper.h2
-rw-r--r--engines/sword25/sword25.cpp2
-rw-r--r--engines/sword25/util/lua/lmathlib.cpp14
-rw-r--r--engines/teenagent/scene.cpp8
-rw-r--r--engines/teenagent/teenagent.cpp38
-rw-r--r--engines/testbed/graphics.cpp32
-rw-r--r--engines/testbed/graphics.h4
-rw-r--r--engines/testbed/midi.cpp2
-rw-r--r--engines/tinsel/background.cpp8
-rw-r--r--engines/tinsel/background.h2
-rw-r--r--engines/tinsel/bmv.cpp18
-rw-r--r--engines/tinsel/bmv.h1
-rw-r--r--engines/tinsel/detection.cpp7
-rw-r--r--engines/tinsel/drives.cpp3
-rw-r--r--engines/tinsel/dw.h2
-rw-r--r--engines/tinsel/handle.cpp8
-rw-r--r--engines/tinsel/music.cpp175
-rw-r--r--engines/tinsel/music.h52
-rw-r--r--engines/tinsel/palette.cpp9
-rw-r--r--engines/tinsel/saveload.cpp63
-rw-r--r--engines/tinsel/scene.cpp18
-rw-r--r--engines/tinsel/sound.cpp6
-rw-r--r--engines/tinsel/tinsel.cpp23
-rw-r--r--engines/tinsel/tinsel.h3
-rw-r--r--engines/toon/anim.cpp26
-rw-r--r--engines/toon/anim.h2
-rw-r--r--engines/toon/audio.cpp67
-rw-r--r--engines/toon/audio.h9
-rw-r--r--engines/toon/character.cpp46
-rw-r--r--engines/toon/character.h2
-rw-r--r--engines/toon/conversation.cpp1
-rw-r--r--engines/toon/conversation.h4
-rw-r--r--engines/toon/detection.cpp9
-rw-r--r--engines/toon/drew.cpp3
-rw-r--r--engines/toon/drew.h2
-rw-r--r--engines/toon/flux.cpp2
-rw-r--r--engines/toon/flux.h1
-rw-r--r--engines/toon/font.cpp8
-rw-r--r--engines/toon/hotspot.cpp8
-rw-r--r--engines/toon/movie.cpp16
-rw-r--r--engines/toon/movie.h2
-rw-r--r--engines/toon/path.cpp9
-rw-r--r--engines/toon/path.h1
-rw-r--r--engines/toon/picture.cpp81
-rw-r--r--engines/toon/picture.h1
-rw-r--r--engines/toon/resource.cpp156
-rw-r--r--engines/toon/resource.h29
-rw-r--r--engines/toon/script.cpp9
-rw-r--r--engines/toon/script.h5
-rw-r--r--engines/toon/script_func.cpp17
-rw-r--r--engines/toon/state.cpp4
-rw-r--r--engines/toon/state.h3
-rw-r--r--engines/toon/text.cpp8
-rw-r--r--engines/toon/tools.cpp40
-rw-r--r--engines/toon/tools.h8
-rw-r--r--engines/toon/toon.cpp391
-rw-r--r--engines/toon/toon.h16
-rw-r--r--engines/touche/midi.cpp156
-rw-r--r--engines/touche/midi.h42
-rw-r--r--engines/touche/opcodes.cpp12
-rw-r--r--engines/touche/resource.cpp5
-rw-r--r--engines/touche/staticres.cpp11
-rw-r--r--engines/touche/touche.cpp29
-rw-r--r--engines/touche/touche.h6
-rw-r--r--engines/tucker/detection.cpp5
-rw-r--r--engines/tucker/graphics.cpp4
-rw-r--r--engines/tucker/graphics.h2
-rw-r--r--engines/tucker/locations.cpp22
-rw-r--r--engines/tucker/resource.cpp44
-rw-r--r--engines/tucker/sequences.cpp36
-rw-r--r--engines/tucker/tucker.cpp107
-rw-r--r--engines/tucker/tucker.h7
-rw-r--r--graphics/cursorman.cpp6
-rw-r--r--graphics/cursorman.h2
-rw-r--r--graphics/dither.cpp4
-rw-r--r--graphics/fonts/winfont.cpp89
-rw-r--r--graphics/fonts/winfont.h4
-rw-r--r--graphics/jpeg.cpp4
-rw-r--r--graphics/module.mk3
-rw-r--r--graphics/palette.h17
-rw-r--r--graphics/pict.cpp17
-rw-r--r--graphics/pict.h4
-rw-r--r--graphics/png.cpp10
-rw-r--r--graphics/png.h6
-rw-r--r--graphics/scaler/2xsai.cpp3
-rw-r--r--graphics/scaler/thumbnail_intern.cpp8
-rw-r--r--graphics/sjis.cpp2
-rw-r--r--graphics/thumbnail.cpp4
-rw-r--r--graphics/wincursor.cpp317
-rw-r--r--graphics/wincursor.h105
-rw-r--r--gui/ThemeEngine.cpp164
-rw-r--r--gui/ThemeEngine.h260
-rw-r--r--gui/ThemeParser.cpp48
-rw-r--r--gui/credits.h32
-rw-r--r--gui/gui-manager.cpp28
-rw-r--r--gui/themes/default.inc10
-rw-r--r--gui/themes/scummclassic.zipbin91252 -> 91156 bytes
-rw-r--r--gui/themes/scummclassic/THEMERC2
-rw-r--r--gui/themes/scummclassic/classic_gfx.stx6
-rw-r--r--gui/themes/scummclassic/classic_layout.stx2
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx2
-rw-r--r--gui/themes/scummmodern.zipbin198584 -> 198479 bytes
-rw-r--r--gui/themes/scummmodern/THEMERC2
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx8
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx2
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx2
-rw-r--r--gui/themes/translations.datbin174729 -> 189132 bytes
-rw-r--r--icons/scummvm.icnsbin232638 -> 232610 bytes
-rw-r--r--po/ca_ES.po153
-rw-r--r--po/cs_CZ.po159
-rw-r--r--po/da_DA.po157
-rw-r--r--po/de_DE.po183
-rw-r--r--po/es_ES.po153
-rw-r--r--po/fr_FR.po218
-rw-r--r--po/hu_HU.po197
-rw-r--r--po/it_IT.po153
-rw-r--r--po/module.mk7
-rw-r--r--po/nb_NO.po157
-rw-r--r--po/nn_NO.po157
-rw-r--r--po/pl_PL.po157
-rw-r--r--po/pt_BR.po159
-rw-r--r--po/ru_RU.po153
-rw-r--r--po/scummvm.pot152
-rw-r--r--po/se_SE.po2208
-rw-r--r--po/uk_UA.po493
-rw-r--r--ports.mk4
-rw-r--r--rules.mk8
-rw-r--r--test/audio/helper.h2
-rw-r--r--test/common/endian.h36
-rw-r--r--tools/module.mk86
-rwxr-xr-xtools/svnpropset.sh20
-rw-r--r--video/avi_decoder.h54
-rw-r--r--video/codecs/cdtoons.cpp14
-rw-r--r--video/codecs/indeo3.cpp2
-rw-r--r--video/codecs/qdm2.cpp28
-rw-r--r--video/coktel_decoder.cpp27
-rw-r--r--video/dxa_decoder.cpp12
-rw-r--r--video/qt_decoder.cpp159
-rw-r--r--video/qt_decoder.h11
-rw-r--r--video/smk_decoder.cpp6
-rw-r--r--video/video_decoder.cpp13
-rw-r--r--video/video_decoder.h5
1082 files changed, 31753 insertions, 25970 deletions
diff --git a/.gitignore b/.gitignore
index 9983c212d8..bff5ead245 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,11 +19,10 @@ lib*.a
/MT32_CONTROL.ROM
/MT32_PCM.ROM
/ScummVM.app
+/*.ipk
/.project
/.cproject
-
-/backends/platform/android/org/inodes/gus/scummvm/R.java
-/backends/platform/android/org/inodes/gus/scummvm/Manifest.java
+/.settings
/backends/platform/dc/gui
/backends/platform/dc/graphics
@@ -65,21 +64,21 @@ lib*.a
/dists/rpl.exe
+/dists/codeblocks/*.cbp
+/dists/codeblocks/*.depend
+/dists/codeblocks/*.layout
+/dists/codeblocks/scummvm*
+
/dists/iphone/build
/dists/iphone/scummvm.xcodeproj/*.mode1v3
/dists/iphone/scummvm.xcodeproj/*.pbxuser
-/dists/msvc8/[Dd]ebug*/
-/dists/msvc8/[Rr]elease*/
-/dists/msvc8/*.lib
-
-/dists/msvc9/[Dd]ebug*/
-/dists/msvc9/[Rr]elease*/
-/dists/msvc9/*.lib
-
-/dists/msvc10/[Dd]ebug*/
-/dists/msvc10/[Rr]elease*/
-/dists/msvc10/*.lib
+/dists/msvc*/[Dd]ebug*/
+/dists/msvc*/[Rr]elease*/
+/dists/msvc*/*.lib
+/dists/msvc*/*.SAV
+/dists/msvc*/*.dat
+/dists/msvc*/*.dll
/doc/*.aux
/doc/*.dvi
@@ -89,24 +88,26 @@ lib*.a
/doc/*.ps
/doc/*.toc
+/plugins
+
/test/runner
/test/runner.cpp
/test/*.dSYM
-/tools/convbdf
-/tools/md5table
-/tools/make-scumm-fontdata
-/tools/create_drascula/create_drascula
-/tools/create_hugo/create_hugo
-/tools/create_kyradat/create_kyradat
-/tools/create_lure/create_lure
-/tools/create_mads/create_mads
-/tools/create_project/create_project
-/tools/create_teenagent/create_teenagent
-/tools/create_toon/create_toon
-/tools/create_translations/create_translations
-/tools/qtable/qtable
-/tools/skycpt/skycpt
+/devtools/convbdf
+/devtools/md5table
+/devtools/make-scumm-fontdata
+/devtools/create_drascula/create_drascula
+/devtools/create_hugo/create_hugo
+/devtools/create_kyradat/create_kyradat
+/devtools/create_lure/create_lure
+/devtools/create_mads/create_mads
+/devtools/create_project/create_project
+/devtools/create_teenagent/create_teenagent
+/devtools/create_toon/create_toon
+/devtools/create_translations/create_translations
+/devtools/qtable/qtable
+/devtools/skycpt/skycpt
#ignore thumbnails created by windows
Thumbs.db
@@ -127,9 +128,20 @@ Thumbs.db
*.ilk
*.log
*.sbr
+*.sdf
+*.opensdf
obj/
_ReSharper*/
+ipch/
[Tt]est[Rr]esult*
*.vcproj
*.sln
-*.vsprops \ No newline at end of file
+*.vsprops
+*.props
+*.vcxproj*
+*.bat
+*.tss
+
+#Ignore default Visual Studio build folders
+[Dd]ebug/
+[Rr]elease/
diff --git a/AUTHORS b/AUTHORS
index 758d1934cf..adc23e50ad 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -137,8 +137,10 @@ ScummVM Team
Filippos Karapetis
Mohawk:
+ Bastien Bouclet
Matthew Hoops
Filippos Karapetis
+ Alyssa Milburn
Eugene Sandulenko
David Turner
@@ -187,6 +189,7 @@ ScummVM Team
Backend Teams
-------------
Android:
+ Andre Heider
Angus Lees
Dreamcast:
@@ -233,6 +236,9 @@ ScummVM Team
Jurgen Braam
Lars Persson
+ WebOS:
+ Klaus Reimer
+
Wii:
Andre Heider
@@ -252,7 +258,7 @@ ScummVM Team
Miscellaneous:
David Corrales-Lopez - Filesystem access improvements (GSoC 2007
task) (retired)
- Jerome Fisher - MT-32 emulator (retired)
+ Jerome Fisher - MT-32 emulator
Benjamin Haisch - Heavily improved de-/encoder for DXA videos
Jochen Hoenicke - Speaker & PCjr sound support, AdLib work
(retired)
@@ -265,6 +271,18 @@ ScummVM Team
--------------
Fredrik Wendel - (retired)
+ Website (maintenance)
+ ---------------------
+ James Brown - IRC Logs maintainer
+ Thierry Crozat - Wiki maintainer
+ Andre Heider - Buildbot maintainer
+ Max Horn - Forum, IRC channel and Mailing list maintainer
+ Joost Peters - Doxygen Project Documentation maintainer
+ Jordi Vilalta Prat - Wiki maintainer
+ Eugene Sandulenko - Forum, IRC channel, Screen Shots and Mailing
+ list maintainer
+ John Willis
+
Website (content)
-----------------
All active team members
@@ -386,6 +404,9 @@ Other contributions
Spanish:
Tomas Maidagan
+ Swedish:
+ Hampus Flink
+
Ukrainian:
Lubomyr Lisen
@@ -396,6 +417,7 @@ Other contributions
David Jensen - SVG logo conversion
Jean Marc Gimenez - ScummVM logo
Raina - ScummVM forum buttons
+ William Claydon - Skins for doxygen and wiki
Code contributions
------------------
@@ -405,7 +427,7 @@ Other contributions
engine)
Paolo Costabel - PSP port contributions
Martin Doucha - CinE engine objectification
- Thomas Fach-Pedersen - ProTracker module player
+ Thomas Fach-Pedersen - ProTracker module player, Smacker video decoder
Tobias Gunkel - Sound support for C64 version of MM/Zak, Loom
PCE support
Janne Huttunen - V3 actor mask support, Dig/FT SMUSH audio
diff --git a/COPYRIGHT b/COPYRIGHT
index 5b00ca218e..fca190596f 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -10,6 +10,7 @@ Chris Apers
Ori Avtalion
Nicolas Bacca
Fabio Battaglia
+Bastien Bouclet
Arnaud Boutonne
Jurgen Braam
Ralph Brorsen
@@ -51,6 +52,7 @@ Andrew Kurushin
Angus Lees
Claudio Matsuoka
Thomas Mayer
+Alyssa Milburn
Neil Millstone
Gregory Montoir
Kostas Nakos
@@ -86,7 +88,6 @@ Bodo Bellut "bellut"
Bramvandijk "bramvandijk"
Andreas Bierfert "awjb"
Elio Blanca "eblanca76"
-Bastien Bouclet "bgk"
David Breakey "dbreakey"
Robert Buchholz "prendi"
Rainer Canavan "canavan"
@@ -154,7 +155,6 @@ Vladimir Menshakov "megath"
Adam Metcalf "gamblore"
Frank Meyering "frank_m24"
Gael Le Migno "kilobug"
-Alyssa Anne Milburn "fuzzie"
Andy Molloy "maloi"
Sean Murrau "lightcast"
Armin Mueller "arm_in"
diff --git a/Makefile b/Makefile
index 844a063f8f..4a6a157259 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ ifeq "$(HAVE_GCC)" "1"
CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
# Enable even more warnings...
CXXFLAGS+= -Wpointer-arith -Wcast-qual
- CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
+ CXXFLAGS+= -Wshadow -Wnon-virtual-dtor -Wwrite-strings
# Currently we disable this gcc flag, since it will also warn in cases,
# where using GCC_PRINTF (means: __attribute__((format(printf, x, y))))
@@ -55,10 +55,6 @@ ifeq "$(HAVE_ICC)" "1"
CXXFLAGS+= -diag-disable 161,1899
endif
-# Warn if global constructors are used. Only available in GCC with LLVM backend
-# (and maybe clang?), hence off by default.
-#CXXFLAGS+= -Wglobal-constructors
-
#######################################################################
# Default commands - put the necessary replacements in config.mk #
#######################################################################
@@ -76,7 +72,7 @@ ZIP ?= zip -q
# Misc stuff - you should never have to edit this #
#######################################################################
-EXECUTABLE := scummvm$(EXEEXT)
+EXECUTABLE := $(EXEPRE)scummvm$(EXEEXT)
include $(srcdir)/Makefile.common
diff --git a/Makefile.common b/Makefile.common
index 2413fa572b..6646af8e8d 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -16,7 +16,7 @@ all: $(EXECUTABLE) plugins
######################################################################
PLUGINS :=
-MODULES := test tools base $(MODULES)
+MODULES := test devtools base $(MODULES)
-include $(srcdir)/engines/engines.mk
diff --git a/NEWS b/NEWS
index 1973490e54..d2ab41c29d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,6 @@
-For a more comprehensive changelog for the latest experimental SVN code, see:
- http://scummvm.svn.sourceforge.net/viewvc/scummvm/?view=log
+For a more comprehensive changelog of the latest experimental code, see:
+ https://github.com/scummvm/scummvm/commits/
+
1.3.0 (????-??-??)
New Games:
- Added support for Backyard Baseball.
@@ -7,12 +8,16 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
- Added support for Urban Runner.
- Added support for Playtoons: Bambou le Sauveur de la Jungle.
- Added support for Toonstruck.
+ - Added support for Living Books v1 and v2 games.
General
+ - Added support for loadable modules on platforms without a dynamic loader.
+ (GSoC Task)
- Added Danish translation.
- Added Norwegian Bokmaal translation.
- Added Norwegian Nynorsk translation.
- - Added Debug Console to Cine, Draci, Gob, MADE, Sword1, Touche and
+ - Added Swedish translation.
+ - Added Debug Console to Cine, Draci, Gob, MADE, Sword1, Touche and
Tucker Engines.
- Closed significant memory leaks. RTL should now be more usable.
@@ -22,14 +27,14 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
Cine:
- Corrected memory leaks and invalid memory accesses.
Future Wars should be more stable.
- - Operation Stealth is now completable, though significant
- graphical glitches remain so not official supported.
+ - Made Operation Stealth completable, though significant graphical
+ glitches remain so not official supported.
Drascula:
- Added German and French subtitles in the Von Braun cutscene (#3069981:
no subtitles in scene with "von Braun").
- Improved French translation of the game.
- - Return To Launcher now supported.
+ - Added support for "Return To Launcher".
Gob:
- Fixed "Goblin Stuck On Reload" bugs affecting Gobliiins.
@@ -39,7 +44,7 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
Parallaction:
- Corrected issue which could cause crash at engine exit.
- - Leak fixes in Nippon Safes Amiga.
+ - Closed memory leaks in Nippon Safes Amiga.
SCI:
- Added a CMS music driver for SCI1 - SCI1.1 games.
@@ -47,7 +52,7 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
- Added several previously missing parts of the game state in saved games,
such as game played time, script created windows, the script string heap
and information related to the text parser in old EGA games.
- - Added support for magnifier cursors.
+ - Added support for SCI1.1 magnifier cursors.
- Added support for the keypad +/- keys.
- Added support for the alternative General MIDI tracks in the Windows CD
versions of Eco Quest, Jones in the Fast Lane, King's Quest 5 and Space
@@ -60,13 +65,23 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
- Corrected several problems and issues in the Skate-O-Rama rooms in Space
Quest 4.
- Corrected several issues in Hoyle Classic Card Games.
- - Fixed several graphical glitches.
+ - Fixed several graphical glitches (like, for example, parts of the screen
+ that weren't erased correctly under some rare circumstances).
- Fixed several script bugs.
- - Fixed several pathfinding related issues and lockups.
- - Fixed several music related glitches and possible lockups.
+ - Fixed several pathfinding related issues and lockups (like, for example,
+ a lockup in the shower scene of Laura bow 1 and pathfinding in some
+ screens during the chase sequence in Laura Bow 2).
+ - Fixed several music related glitches and possible lockups (like, for
+ example, a rare music lockup that occurred when loading a saved game
+ outside the palace in Quest for Glory 3).
- Fixed possible problems and lockups in the character import screens of
Quest for Glory 2 and 3.
- - Function keys now work correctly when the numlock key is on.
+ - Fixed a bug that caused a lockup in the SCI1 CD version of Mixed Up Mother
+ Goose, after Tommy Tucker's song.
+ - Fixed a script bug in the CD version of King's Quest 5, which caused a
+ lockup under certain circumstances when going outside the witch's house
+ in the dark forest.
+ - Function keys now work correctly when the num lock key is on.
- Improved support for fanmade game scripts.
- Improved support for non-English versions of games.
- Made several enhancements and fixes related to MT-32 music (e.g. reverb).
@@ -75,25 +90,59 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
SCUMM:
- Improved support for FM-TOWNS versions of games.
+ Sky:
+ - Fixed crashes on sequences for several ports (Android, OpenGL, ...)
+
Teenagent:
- Closed memory leaks.
Tinsel:
- Closed memory leaks in Coroutines.
+ - Added enhanced music support for the German CD "Neon Edition" re-release
+ of Discworld 1.
Touche:
- Corrected memory leaks and minor issues.
- SDL:
+ Tucker:
+ - Added workarounds for several issues present in the original game.
+
+ SDL ports:
+ - Added support for OpenGL. (GSoC Task)
- Closed memory leaks in Mouse Surfaces.
- PSP:
+ Android port:
+ - Switched to the official NDK toolchain for building.
+ - Fixed GFX output for various devices.
+ - Fixed various crashes.
+ - Switched to the native screen resolution to improve text readability.
+ - Added support for pause/resume.
+ - Added support for games using 16bit graphics.
+ - Increased the performance significantly.
+ - Added support for the "Fullscreen mode" option. Unchecking this keeps the
+ game's aspect ratio.
+ - Added a new graphics mode for linear filtering.
+ - Overhauled the input system (see README.Android).
+ - Added a MIDI driver based on SONiVOX's Embedded Audio Synthesis (EAS).
+
+ Nintendo DS port:
+ - Added support for loadable modules.
+
+ PSP port:
+ - Added support for loadable modules.
- Added image viewer.
+ PS2 port:
+ - Added support for loadable modules.
+
+ Wii/GameCube port:
+ - Added support for loadable modules.
+ - Fixed 16bit mouse cursors on HE games.
+
1.2.1 (2010-12-19)
General
- - Add Hungarian translation.
- - Add Brazilian Portuguese translation.
+ - Added Hungarian translation.
+ - Added Brazilian Portuguese translation.
Cruise:
- Fixed a problem with Raoul appearing when examining the Book.
diff --git a/README b/README
index d6482e0392..efb9a2a502 100644
--- a/README
+++ b/README
@@ -137,7 +137,7 @@ Hint: If you want to add multiple games in one go, try pressing and
holding the shift key before clicking 'Add game' -- its label will
change to 'Mass Add' and if you press it, you are again asked to select
a directory, only this time ScummVM will search through all
-subdirectoriess for supported games.
+subdirectories for supported games.
2.0) Contact:
@@ -216,7 +216,7 @@ AGI Games by Sierra:
Space Quest II: Vohaul's Revenge [sq2]
Fanmade Games [agi-fanmade]
-AGOS Games by Adventuresoft / Horrorsoft:
+AGOS Games by Adventuresoft/Horrorsoft:
Elvira - Mistress of the Dark [elvira1]
Elvira II - The Jaws of Cerberus [elvira2]
Waxworks [waxworks]
@@ -318,6 +318,22 @@ SCUMM Games by Humongous Entertainment:
SPY Fox in Cheese Chase [chase]
SPY Fox in Hold the Mustard [mustard]
+Living Books Games:
+ Aesop's Fables: The Tortoise and the Hare [tortoise]
+ Arthur's Birthday [arthurbday]
+ Arthur's Teacher Trouble [arthur]
+ Dr. Seuss's ABC [seussabc]
+ Green Eggs and Ham [greeneggs]
+ Harry and the Haunted House [harryhh]
+ Just Grandma and Me [grandma]
+ Little Monster at School [lilmonster]
+ Ruff's Bone [ruff]
+ Sheila Rae, the Brave [sheila]
+ Stellaluna [stellaluna]
+ The Berenstain Bears Get in a Fight [bearfight]
+ The Berenstain Bears in the Dark [beardark]
+ The New Kid on the Block [newkid]
+
The following games should load, but are not yet fully playable. Play
these at your own risk, and please do not file bug reports about them.
If you want the latest updates on game compatibility, visit our web site
@@ -528,7 +544,7 @@ playing the video itself. This remained a fallback until ScummVM 1.0.0,
but was never the only solution for any stable release.
In ScummVM 0.6.0 we used MPEG, which provided a reasonable trade-off
-between size and quality. In ScummVM 0.10.0 this was superceeded by DXA
+between size and quality. In ScummVM 0.10.0 this was superseded by DXA
(originally added for AdventureSoft's "The Feeble Files"). This gave us
a way of providing the cutscenes in the exact same quality as the
originals, at the cost of being larger.
@@ -1663,7 +1679,7 @@ First, you need to start a daemon:
timidity -ir 7777
-Now you can start scummvm and try selection TiMidity music output. By
+Now you can start ScummVM and try selection TiMidity music output. By
default, it will connect to localhost:7777, but you can change host/port
via the "TIMIDITY_HOST" environment variable. You can also specify
a "device number" using the "SCUMMVM_MIDIPORT" environment variable.
diff --git a/audio/mididrv.h b/audio/mididrv.h
index 9e649cba3d..8d6f942455 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -38,15 +38,6 @@ namespace Audio {
namespace Common { class String; }
/**
- * Music Driver Types, used to uniquely identify each music driver.
- *
- * The pseudo drivers are listed first, then all native drivers,
- * then all other MIDI drivers, and finally the non-MIDI drivers.
- *
- * @todo Rename MidiDriverType to MusicDriverType
- */
-
-/**
* Music types that music drivers can implement and engines can rely on.
*/
enum MusicType {
@@ -71,16 +62,21 @@ enum MusicType {
* A set of flags to be passed to detectDevice() which can be used to
* specify what kind of music driver is preferred / accepted.
*
- * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a given driver
- * type is acceptable. E.g. the TOWNS music driver could be returned by
- * detectDevice if and only if MDT_TOWNS is specified.
+ * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a
+ * given driver type is acceptable. E.g. the TOWNS music driver could be
+ * returned by detectDevice if and only if MDT_TOWNS is specified.
+ *
+ * MDT_PREFER_MT32 and MDT_PREFER_GM indicate the MIDI device type to use when
+ * no device is selected in the music options, or when the MIDI device selected
+ * does not match the requirements of a game engine. With these flags, more
+ * priority is given to an MT-32 device, or a GM device respectively.
*
* @todo Rename MidiDriverFlags to MusicDriverFlags
*/
enum MidiDriverFlags {
MDT_NONE = 0,
- MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR
- MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS
+ MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MT_PCSPK and MT_PCJR
+ MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MT_CMS
MDT_PCJR = 1 << 2, // Tandy/PC Junior driver
MDT_ADLIB = 1 << 3, // AdLib: Maps to MT_ADLIB
MDT_C64 = 1 << 4,
@@ -94,19 +90,53 @@ enum MidiDriverFlags {
};
/**
- * Abstract description of a MIDI driver. Used by the config file and command
- * line parsing code, and also to be able to give the user a list of available
- * drivers.
- *
- * @todo Rename MidiDriverType to MusicDriverType
+ * TODO: Document this, give it a better name.
*/
+class MidiDriver_BASE {
+public:
+ virtual ~MidiDriver_BASE() { }
+
+ /**
+ * Output a packed midi command to the midi stream.
+ * The 'lowest' byte (i.e. b & 0xFF) is the status
+ * code, then come (if used) the first and second
+ * opcode.
+ */
+ virtual void send(uint32 b) = 0;
+
+ /**
+ * Output a midi command to the midi stream. Convenience wrapper
+ * around the usual 'packed' send method.
+ *
+ * Do NOT use this for sysEx transmission; instead, use the sysEx()
+ * method below.
+ */
+ void send(byte status, byte firstOp, byte secondOp) {
+ send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+ }
+
+ /**
+ * Transmit a sysEx to the midi device.
+ *
+ * The given msg MUST NOT contain the usual SysEx frame, i.e.
+ * do NOT include the leading 0xF0 and the trailing 0xF7.
+ *
+ * Furthermore, the maximal supported length of a SysEx
+ * is 264 bytes. Passing longer buffers can lead to
+ * undefined behavior (most likely, a crash).
+ */
+ virtual void sysEx(const byte *msg, uint16 length) { }
+
+ // TODO: Document this.
+ virtual void metaEvent(byte type, byte *data, uint16 length) { }
+};
/**
* Abstract MIDI Driver Class
*
* @todo Rename MidiDriver to MusicDriver
*/
-class MidiDriver {
+class MidiDriver : public MidiDriver_BASE {
public:
/**
* The device handle.
@@ -177,27 +207,13 @@ public:
*/
virtual int open() = 0;
- /** Close the midi driver. */
- virtual void close() = 0;
-
/**
- * Output a packed midi command to the midi stream.
- * The 'lowest' byte (i.e. b & 0xFF) is the status
- * code, then come (if used) the first and second
- * opcode.
+ * Check whether the midi driver has already been opened.
*/
- virtual void send(uint32 b) = 0;
+ virtual bool isOpen() const = 0;
- /**
- * Output a midi command to the midi stream. Convenience wrapper
- * around the usual 'packed' send method.
- *
- * Do NOT use this for sysEx transmission; instead, use the sysEx()
- * method below.
- */
- void send(byte status, byte firstOp, byte secondOp) {
- send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
- }
+ /** Close the midi driver. */
+ virtual void close() = 0;
/** Get or set a property. */
virtual uint32 property(int prop, uint32 param) { return 0; }
@@ -225,22 +241,8 @@ public:
*/
void sendGMReset();
- /**
- * Transmit a sysEx to the midi device.
- *
- * The given msg MUST NOT contain the usual SysEx frame, i.e.
- * do NOT include the leading 0xF0 and the trailing 0xF7.
- *
- * Furthermore, the maximal supported length of a SysEx
- * is 264 bytes. Passing longer buffers can lead to
- * undefined behavior (most likely, a crash).
- */
- virtual void sysEx(const byte *msg, uint16 length) { }
-
virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
- virtual void metaEvent(byte type, byte *data, uint16 length) { }
-
// Timing functions - MidiDriver now operates timers
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) = 0;
diff --git a/audio/midiparser.cpp b/audio/midiparser.cpp
index e01b8a7fc6..a6df6024cd 100644
--- a/audio/midiparser.cpp
+++ b/audio/midiparser.cpp
@@ -350,7 +350,7 @@ void MidiParser::hangAllActiveNotes() {
if (_next_event.command() == 0x8) {
if (temp_active[_next_event.basic.param1] & (1 << _next_event.channel())) {
hangingNote(_next_event.channel(), _next_event.basic.param1, (advance_tick - _position._last_event_tick) * _psec_per_tick, false);
- temp_active[_next_event.basic.param1] &= ~ (1 << _next_event.channel());
+ temp_active[_next_event.basic.param1] &= ~(1 << _next_event.channel());
}
} else if (_next_event.event == 0xFF && _next_event.ext.type == 0x2F) {
// warning("MidiParser::hangAllActiveNotes(): Hit End of Track with active notes left");
diff --git a/audio/midiparser.h b/audio/midiparser.h
index 0b18a19a5b..eeeee981e4 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -32,7 +32,7 @@
#include "common/endian.h"
class MidiParser;
-class MidiDriver;
+class MidiDriver_BASE;
@@ -273,7 +273,7 @@ protected:
///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
byte _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration.
- MidiDriver *_driver; ///< The device to which all events will be transmitted.
+ MidiDriver_BASE *_driver; ///< The device to which all events will be transmitted.
uint32 _timer_rate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
uint32 _ppqn; ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
uint32 _tempo; ///< Microseconds per quarter note.
@@ -380,7 +380,7 @@ public:
virtual void unloadMusic();
virtual void property(int prop, int value);
- void setMidiDriver(MidiDriver *driver) { _driver = driver; }
+ void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
void setTimerRate(uint32 rate) { _timer_rate = rate; }
void setTempo(uint32 tempo);
void onTimer();
diff --git a/audio/midiplayer.cpp b/audio/midiplayer.cpp
new file mode 100644
index 0000000000..f4a13a0438
--- /dev/null
+++ b/audio/midiplayer.cpp
@@ -0,0 +1,198 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "audio/midiplayer.h"
+#include "audio/midiparser.h"
+
+#include "common/config-manager.h"
+
+namespace Audio {
+
+MidiPlayer::MidiPlayer() :
+ _driver(0),
+ _parser(0),
+ _midiData(0),
+ _isLooping(false),
+ _isPlaying(false),
+ _masterVolume(0),
+ _nativeMT32(false) {
+
+ memset(_channelsTable, 0, sizeof(_channelsTable));
+ memset(_channelsVolume, 127, sizeof(_channelsVolume));
+
+// TODO
+}
+
+MidiPlayer::~MidiPlayer() {
+ // FIXME/TODO: In some engines, stop() was called first;
+ // in others, _driver->setTimerCallback(NULL, NULL) came first.
+ // Hopefully, this make no real difference, but we should
+ // watch out for regressions.
+ stop();
+
+ // Unhook & unload the driver
+ if (_driver) {
+ _driver->setTimerCallback(0, 0);
+ _driver->close();
+ delete _driver;
+ _driver = 0;
+ }
+}
+
+void MidiPlayer::createDriver(int flags) {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(flags);
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
+ if (_nativeMT32)
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+}
+
+
+void MidiPlayer::setVolume(int volume) {
+ volume = CLIP(volume, 0, 255);
+ if (_masterVolume == volume)
+ return;
+
+ Common::StackLock lock(_mutex);
+
+ _masterVolume = volume;
+ for (int i = 0; i < kNumChannels; ++i) {
+ if (_channelsTable[i]) {
+ _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
+ }
+ }
+}
+
+void MidiPlayer::syncVolume() {
+ int volume = ConfMan.getInt("music_volume");
+ if (ConfMan.getBool("mute")) {
+ volume = -1;
+ }
+ setVolume(volume);
+}
+
+
+void MidiPlayer::send(uint32 b) {
+ byte ch = (byte)(b & 0x0F);
+ if ((b & 0xFFF0) == 0x07B0) {
+ // Adjust volume changes by master volume
+ byte volume = (byte)((b >> 16) & 0x7F);
+ _channelsVolume[ch] = volume;
+ volume = volume * _masterVolume / 255;
+ b = (b & 0xFF00FFFF) | (volume << 16);
+ } else if ((b & 0xFFF0) == 0x007BB0) {
+ // Only respond to All Notes Off if this channel
+ // has currently been allocated
+ if (!_channelsTable[ch])
+ return;
+ }
+
+ sendToChannel(ch, b);
+}
+
+void MidiPlayer::sendToChannel(byte ch, uint32 b) {
+ if (!_channelsTable[ch]) {
+ _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // TODO: Some engines overload this method to insert code at this
+ // point which calls the channel's volume() method.
+ // Does this make sense, and should we maybe do it in general?
+ }
+ if (_channelsTable[ch]) {
+ _channelsTable[ch]->send(b);
+ }
+}
+
+void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
+ switch (type) {
+ case 0x2F: // End of Track
+ endOfTrack();
+ break;
+ default:
+ //warning("Unhandled meta event: %02x", type);
+ break;
+ }
+}
+
+void MidiPlayer::endOfTrack() {
+ if (_isLooping) {
+ assert(_parser);
+ _parser->jumpToTick(0);
+ } else
+ stop();
+}
+
+void MidiPlayer::timerCallback(void *data) {
+ assert(data);
+ ((MidiPlayer *)data)->onTimer();
+}
+
+void MidiPlayer::onTimer() {
+ Common::StackLock lock(_mutex);
+
+ // TODO: Maybe we can replace _isPlaying
+ // by a simple check for "_parser != 0" ?
+
+ if (_isPlaying && _parser) {
+ _parser->onTimer();
+ }
+}
+
+
+void MidiPlayer::stop() {
+ Common::StackLock lock(_mutex);
+
+ _isPlaying = false;
+ if (_parser) {
+ _parser->unloadMusic();
+
+ // FIXME/TODO: The MidiParser destructor calls allNotesOff()
+ // but unloadMusic also does. To suppress double notes-off,
+ // we reset the midi driver of _parser before deleting it.
+ // This smells very fishy, in any case.
+ _parser->setMidiDriver(0);
+
+ delete _parser;
+ _parser = NULL;
+ }
+
+ free(_midiData);
+ _midiData = 0;
+}
+
+void MidiPlayer::pause() {
+// debugC(2, kDraciSoundDebugLevel, "Pausing track %d", _track);
+ _isPlaying = false;
+ setVolume(-1); // FIXME: This should be 0, shouldn't it?
+}
+
+void MidiPlayer::resume() {
+// debugC(2, kDraciSoundDebugLevel, "Resuming track %d", _track);
+ syncVolume();
+ _isPlaying = true;
+}
+
+} // End of namespace Audio
diff --git a/audio/midiplayer.h b/audio/midiplayer.h
new file mode 100644
index 0000000000..0cf373d646
--- /dev/null
+++ b/audio/midiplayer.h
@@ -0,0 +1,191 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SOUND_MIDIPLAYER_H
+#define SOUND_MIDIPLAYER_H
+
+#include "common/scummsys.h"
+#include "common/mutex.h"
+#include "audio/mididrv.h"
+
+class MidiParser;
+
+namespace Audio {
+
+/**
+ * Simple MIDI playback class.
+ *
+ * @note Currently incomplete, as it lacks play() methods. This is just a
+ * start of the real thing, which tries to include code replicated between
+ * several of our engines.
+ *
+ * Eventually, this should offer ways to start playback of SMF and XMIDI
+ * data (and possibly make it easy to add further playback methods),
+ * should be able to automatically instantiate _driver as needed,
+ * should perform memory management on the MidiParser object(s) being
+ * used, and possibly more.
+ *
+ * Also, pause/resume handling should be unified (we provide an implementation,
+ * but several subclasses use different ones).
+ *
+ * Also, care should be taken to ensure that mutex locking is done right.
+ *
+ * @todo Document origin of this class. It is based on code shared by
+ * several engines (e.g. DRACI says it copied it from MADE, which took
+ * it from SAGE).
+ */
+class MidiPlayer : public MidiDriver_BASE {
+public:
+ MidiPlayer();
+ ~MidiPlayer();
+
+ // TODO: Implement ways to actually play stuff
+ //virtual void play(TODO);
+
+ // TODO: Document these
+ virtual void stop();
+ virtual void pause();
+ virtual void resume();
+
+ /**
+ * Return whether there is currently any MIDI music playing.
+ *
+ * @todo There is a subtle difference between the semantics of this in
+ * various subclasses, related to paused music: Namely, should this
+ * function return true or false if a MIDI song is currently loaded,
+ * but paused? In the base implementation of pause/resume, "false"
+ * will be returned (that is, it is not possible to distinguish between
+ * nothing being played, and an active but paused MIDI tune).
+ * But in several subclasses (e.g. in HUGO), there is a separate _paused
+ * variable, which is used to pause playback, and for these, "true"
+ * will be returned.
+ * And in SAGA, isPlaying is overwritten to return the value
+ * of _parser->isPlaying() (which should amount to "true" in the
+ * described situation).
+ * We really should unify this and clearly define the desired
+ * semantics of this method.
+ */
+ bool isPlaying() const { return _isPlaying; }
+
+ /**
+ * Return the currently active master volume, in the range 0-255.
+ */
+ int getVolume() const { return _masterVolume; }
+
+ /**
+ * Set the master volume to the specified value in the range 0-255.
+ * (values outside this range are automatically clipped).
+ * This may cause suitable MIDI events to be sent to active channels.
+ *
+ * @todo This method currently does not do anything if the new volume
+ * matches the old volume. But some engines always update the
+ * volume (Parallaction, Tinsel, Touche, ...). This is why
+ * this method is currently virtual. We really should figure
+ * which way to do it, and then make this the default, and make
+ * this method non-virtual again.
+ */
+ virtual void setVolume(int volume);
+
+ /**
+ * Update the volume according to the ConfMan's 'music_volume'
+ * setting. also respects the 'mute' setting.
+ */
+ void syncVolume();
+
+ // TODO: Document this
+ bool hasNativeMT32() const { return _nativeMT32; }
+
+ // MidiDriver_BASE implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
+
+protected:
+ /**
+ * This method is invoked by the default send() implementation,
+ * after suitably filtering the message b.
+ */
+ virtual void sendToChannel(byte ch, uint32 b);
+
+ /**
+ * This method is invoked by metaEvent when an end-of-track
+ * event arrives. By default, this tells the parser
+ * to jump to the start (if looping is enabled) resp.
+ * invokes stope():
+ * Overload this to customize behavior.
+ */
+ virtual void endOfTrack();
+
+ // TODO: Document this
+ virtual void onTimer();
+
+ static void timerCallback(void *data);
+
+ void createDriver(int flags = MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+
+protected:
+ enum {
+ /**
+ * The number of MIDI channels supported.
+ */
+ kNumChannels = 16
+ };
+
+ Common::Mutex _mutex;
+ MidiDriver *_driver;
+
+ /**
+ * A MidiParser instances, to be created by methods of a MidiPlayer
+ * subclass.
+ * @note The stop() method (and hence the destructor) invoke the
+ * unloadMusic() method of _parser and then delete it.
+ */
+ MidiParser *_parser;
+
+ /**
+ * This is an (optional) pointer to a malloc'ed buffer containing
+ * MIDI data used by _parser. The stop() method (and hence the
+ * destructor) will free this if set.
+ * Subclasses of this class may use _midiData, but don't have to
+ */
+ byte *_midiData;
+
+ MidiChannel *_channelsTable[kNumChannels];
+ uint8 _channelsVolume[kNumChannels];
+
+ bool _isLooping;
+ bool _isPlaying;
+
+ /**
+ * The master volume, in the range 0-255.
+ */
+ int _masterVolume; // FIXME: byte or int ?
+
+ bool _nativeMT32;
+};
+
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index c2271b1059..dc0287e3fb 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -54,8 +54,9 @@ public:
* @param len number of sample *pairs*. So a value of
* 10 means that the buffer contains twice 10 sample, each
* 16 bits, for a total of 40 bytes.
+ * @return number of sample pairs processed (which can still be silence!)
*/
- void mix(int16 *data, uint len);
+ int mix(int16 *data, uint len);
/**
* Queries whether the channel is still playing or not.
@@ -257,7 +258,7 @@ void MixerImpl::playStream(
insertChannel(handle, chan);
}
-void MixerImpl::mixCallback(byte *samples, uint len) {
+int MixerImpl::mixCallback(byte *samples, uint len) {
assert(samples);
Common::StackLock lock(_mutex);
@@ -272,14 +273,21 @@ void MixerImpl::mixCallback(byte *samples, uint len) {
memset(buf, 0, 2 * len * sizeof(int16));
// mix all channels
+ int res = 0, tmp;
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i]) {
if (_channels[i]->isFinished()) {
delete _channels[i];
_channels[i] = 0;
- } else if (!_channels[i]->isPaused())
- _channels[i]->mix(buf, len);
+ } else if (!_channels[i]->isPaused()) {
+ tmp = _channels[i]->mix(buf, len);
+
+ if (tmp > res)
+ res = tmp;
+ }
}
+
+ return res;
}
void MixerImpl::stopAll() {
@@ -538,19 +546,23 @@ Timestamp Channel::getElapsedTime() {
return ts;
}
-void Channel::mix(int16 *data, uint len) {
+int Channel::mix(int16 *data, uint len) {
assert(_stream);
+ int res = 0;
+
if (_stream->endOfData()) {
// TODO: call drain method
} else {
assert(_converter);
-
_samplesConsumed = _samplesDecoded;
_mixerTimeStamp = g_system->getMillis();
_pauseTime = 0;
- _samplesDecoded += _converter->flow(*_stream, data, len, _volL, _volR);
+ res = _converter->flow(*_stream, data, len, _volL, _volR);
+ _samplesDecoded += res;
}
+
+ return res;
}
} // End of namespace Audio
diff --git a/audio/mixer_intern.h b/audio/mixer_intern.h
index c8df9a594d..dd2746e9ea 100644
--- a/audio/mixer_intern.h
+++ b/audio/mixer_intern.h
@@ -118,8 +118,10 @@ public:
* The mixer callback function, to be called at regular intervals by
* the backend (e.g. from an audio mixing thread). All the actual mixing
* work is done from here.
+ *
+ * @return number of sample pairs processed (which can still be silence!)
*/
- void mixCallback(byte *samples, uint len);
+ int mixCallback(byte *samples, uint len);
/**
* Set the internal 'is ready' flag of the mixer.
diff --git a/audio/mods/module.cpp b/audio/mods/module.cpp
index 0da6923b5d..3dad3794f9 100644
--- a/audio/mods/module.cpp
+++ b/audio/mods/module.cpp
@@ -113,7 +113,7 @@ const int16 Module::periods[16][60] = {
108 , 101 , 96 , 90 , 85 , 80 , 76 , 72 , 68 , 64 , 60 , 57 }};
const uint32 Module::signatures[] = {
- MKID_BE('M.K.'), MKID_BE('M!K!'), MKID_BE('FLT4')
+ MKTAG('M','.','K','.'), MKTAG('M','!','K','!'), MKTAG('F','L','T','4')
};
bool Module::load(Common::SeekableReadStream &st, int offs) {
diff --git a/audio/mods/rjp1.cpp b/audio/mods/rjp1.cpp
index 7423abb668..957bbb933a 100644
--- a/audio/mods/rjp1.cpp
+++ b/audio/mods/rjp1.cpp
@@ -138,7 +138,7 @@ Rjp1::~Rjp1() {
}
bool Rjp1::load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData) {
- if (songData->readUint32BE() == MKID_BE('RJP1') && songData->readUint32BE() == MKID_BE('SMOD')) {
+ if (songData->readUint32BE() == MKTAG('R','J','P','1') && songData->readUint32BE() == MKTAG('S','M','O','D')) {
for (int i = 0; i < 7; ++i) {
uint32 size = songData->readUint32BE();
_vars.songData[i] = (uint8 *)malloc(size);
@@ -167,7 +167,7 @@ bool Rjp1::load(Common::SeekableReadStream *songData, Common::SeekableReadStream
}
}
- if (instrumentsData->readUint32BE() == MKID_BE('RJP1')) {
+ if (instrumentsData->readUint32BE() == MKTAG('R','J','P','1')) {
uint32 size = instrumentsData->size() - 4;
_vars.instData = (int8 *)malloc(size);
if (!_vars.instData)
diff --git a/audio/module.mk b/audio/module.mk
index 5b93c80d57..a9d9bfc869 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
midiparser_smf.o \
midiparser_xmidi.o \
midiparser.o \
+ midiplayer.o \
mixer.o \
mpu401.o \
musicplugin.o \
@@ -44,6 +45,7 @@ MODULE_OBJS := \
softsynth/ym2612.o \
softsynth/fluidsynth.o \
softsynth/mt32.o \
+ softsynth/eas.o \
softsynth/pcspk.o \
softsynth/sid.o \
softsynth/wave6581.o
diff --git a/audio/mpu401.cpp b/audio/mpu401.cpp
index 4f62de930c..4834772c07 100644
--- a/audio/mpu401.cpp
+++ b/audio/mpu401.cpp
@@ -101,12 +101,18 @@ MidiDriver_MPU401::MidiDriver_MPU401() :
}
}
+MidiDriver_MPU401::~MidiDriver_MPU401() {
+}
+
void MidiDriver_MPU401::close() {
- if (_timer_proc)
+ if (_timer_proc) {
g_system->getTimerManager()->removeTimerProc(_timer_proc);
- _timer_proc = 0;
- for (int i = 0; i < 16; ++i)
- send(0x7B << 8 | 0xB0 | i);
+ _timer_proc = 0;
+ }
+ if (isOpen()) {
+ for (int i = 0; i < 16; ++i)
+ send(0x7B << 8 | 0xB0 | i);
+ }
}
uint32 MidiDriver_MPU401::property(int prop, uint32 param) {
diff --git a/audio/mpu401.h b/audio/mpu401.h
index 070eaf636a..07e2817381 100644
--- a/audio/mpu401.h
+++ b/audio/mpu401.h
@@ -46,22 +46,22 @@ private:
public:
MidiDriver *device();
byte getNumber() { return _channel; }
- void release() { _allocated = false; }
+ virtual void release() { _allocated = false; }
- void send(uint32 b);
+ virtual void send(uint32 b);
// Regular messages
- void noteOff(byte note);
- void noteOn(byte note, byte velocity);
- void programChange(byte program);
- void pitchBend(int16 bend);
+ virtual void noteOff(byte note);
+ virtual void noteOn(byte note, byte velocity);
+ virtual void programChange(byte program);
+ virtual void pitchBend(int16 bend);
// Control Change messages
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte value);
+ virtual void controlChange(byte control, byte value);
+ virtual void pitchBendFactor(byte value);
// SysEx messages
- void sysEx_customInstrument(uint32 type, const byte *instr);
+ virtual void sysEx_customInstrument(uint32 type, const byte *instr);
// Only to be called by the owner
void init(MidiDriver *owner, byte channel);
@@ -78,14 +78,15 @@ private:
public:
MidiDriver_MPU401();
+ virtual ~MidiDriver_MPU401();
virtual void close();
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
- uint32 getBaseTempo(void) { return 10000; }
- uint32 property(int prop, uint32 param);
+ virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
+ virtual uint32 getBaseTempo(void) { return 10000; }
+ virtual uint32 property(int prop, uint32 param);
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel() { return &_midi_channels[9]; }
+ virtual MidiChannel *allocateChannel();
+ virtual MidiChannel *getPercussionChannel() { return &_midi_channels[9]; }
};
diff --git a/audio/null.h b/audio/null.h
index 5df7493a06..8570d4d293 100644
--- a/audio/null.h
+++ b/audio/null.h
@@ -33,6 +33,7 @@
class MidiDriver_NULL : public MidiDriver_MPU401 {
public:
int open() { return 0; }
+ bool isOpen() const { return true; }
void send(uint32 b) { }
};
diff --git a/audio/rate_arm.cpp b/audio/rate_arm.cpp
index 41944ef698..43172f64c8 100644
--- a/audio/rate_arm.cpp
+++ b/audio/rate_arm.cpp
@@ -60,7 +60,7 @@ namespace Audio {
* ARM routine we call doesn't respect those definitions.
*/
#define FRAC_BITS 16
-#define FRAC_ONE (1<<FRAC_BITS)
+#define FRAC_ONE (1 << FRAC_BITS)
/**
* The size of the intermediate input cache. Bigger values may increase
@@ -138,34 +138,33 @@ extern "C" {
}
extern "C" st_sample_t *ARM_SimpleRate_M(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- SimpleRateDetails *sr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ SimpleRateDetails *sr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_SimpleRate_S(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- SimpleRateDetails *sr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ SimpleRateDetails *sr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_SimpleRate_R(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- SimpleRateDetails *sr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
-
-extern "C" int SimpleRate_readFudge(Audio::AudioStream &input,
- int16 *a, int b)
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ SimpleRateDetails *sr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
+
+extern "C" int SimpleRate_readFudge(Audio::AudioStream &input, int16 *a, int b)
{
#ifdef DEBUG_RATECONV
debug("Reading ptr=%x n%d", a, b);
@@ -183,21 +182,22 @@ int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
if (!stereo) {
obuf = ARM_SimpleRate_M(input,
- &SimpleRate_readFudge,
- &sr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &sr,
+ obuf, osamp, vol_l, vol_r);
} else if (reverseStereo) {
obuf = ARM_SimpleRate_R(input,
- &SimpleRate_readFudge,
- &sr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &sr,
+ obuf, osamp, vol_l, vol_r);
} else {
obuf = ARM_SimpleRate_S(input,
- &SimpleRate_readFudge,
- &sr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &sr,
+ obuf, osamp, vol_l, vol_r);
}
- return (obuf-ostart)/2;
+
+ return (obuf - ostart) / 2;
}
/**
@@ -240,31 +240,31 @@ extern "C" {
}
extern "C" st_sample_t *ARM_LinearRate_M(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- LinearRateDetails *lr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ LinearRateDetails *lr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_LinearRate_S(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- LinearRateDetails *lr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ LinearRateDetails *lr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_LinearRate_R(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- LinearRateDetails *lr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ LinearRateDetails *lr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
template<bool stereo, bool reverseStereo>
class LinearRateConverter : public RateConverter {
@@ -320,23 +320,29 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
#endif
st_sample_t *ostart = obuf;
+ if (vol_l > 0xff)
+ vol_l = 0xff;
+
+ if (vol_r > 0xff)
+ vol_r = 0xff;
+
if (!stereo) {
obuf = ARM_LinearRate_M(input,
- &SimpleRate_readFudge,
- &lr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &lr,
+ obuf, osamp, vol_l, vol_r);
} else if (reverseStereo) {
obuf = ARM_LinearRate_R(input,
- &SimpleRate_readFudge,
- &lr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &lr,
+ obuf, osamp, vol_l, vol_r);
} else {
obuf = ARM_LinearRate_S(input,
- &SimpleRate_readFudge,
- &lr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &lr,
+ obuf, osamp, vol_l, vol_r);
}
- return (obuf-ostart)/2;
+ return (obuf - ostart) / 2;
}
@@ -355,31 +361,32 @@ extern "C" {
}
extern "C" st_sample_t *ARM_CopyRate_M(
- st_size_t len,
- st_sample_t *obuf,
- st_volume_t vol_l,
- st_volume_t vol_r,
- st_sample_t *_buffer);
+ st_size_t len,
+ st_sample_t *obuf,
+ st_volume_t vol_l,
+ st_volume_t vol_r,
+ st_sample_t *_buffer);
extern "C" st_sample_t *ARM_CopyRate_S(
- st_size_t len,
- st_sample_t *obuf,
- st_volume_t vol_l,
- st_volume_t vol_r,
- st_sample_t *_buffer);
+ st_size_t len,
+ st_sample_t *obuf,
+ st_volume_t vol_l,
+ st_volume_t vol_r,
+ st_sample_t *_buffer);
extern "C" st_sample_t *ARM_CopyRate_R(
- st_size_t len,
- st_sample_t *obuf,
- st_volume_t vol_l,
- st_volume_t vol_r,
- st_sample_t *_buffer);
+ st_size_t len,
+ st_sample_t *obuf,
+ st_volume_t vol_l,
+ st_volume_t vol_r,
+ st_sample_t *_buffer);
template<bool stereo, bool reverseStereo>
class CopyRateConverter : public RateConverter {
st_sample_t *_buffer;
st_size_t _bufferSize;
+
public:
CopyRateConverter() : _buffer(0), _bufferSize(0) {}
~CopyRateConverter() {
@@ -393,7 +400,7 @@ public:
debug("Copy st=%d rev=%d", stereo, reverseStereo);
#endif
st_size_t len;
- st_sample_t *ostart = obuf;
+ st_sample_t *ostart = obuf;
if (stereo)
osamp *= 2;
@@ -418,8 +425,9 @@ public:
else
obuf = ARM_CopyRate_M(len, obuf, vol_l, vol_r, _buffer);
- return (obuf-ostart)/2;
+ return (obuf - ostart) / 2;
}
+
virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
return (ST_SUCCESS);
}
@@ -463,3 +471,4 @@ RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stere
}
} // End of namespace Audio
+
diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp
index 4a9ce54c75..9e863471f0 100644
--- a/audio/softsynth/adlib.cpp
+++ b/audio/softsynth/adlib.cpp
@@ -118,7 +118,7 @@ public:
byte getNumber() { return _channel; }
void release() { _allocated = false; }
- void send (uint32 b);
+ void send(uint32 b);
// Regular messages
void noteOff(byte note);
diff --git a/audio/softsynth/eas.cpp b/audio/softsynth/eas.cpp
new file mode 100644
index 0000000000..0339492f5d
--- /dev/null
+++ b/audio/softsynth/eas.cpp
@@ -0,0 +1,483 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "common/scummsys.h"
+
+#if defined(__ANDROID__)
+
+#include <dlfcn.h>
+
+#include "common/debug.h"
+#include "common/endian.h"
+#include "common/file.h"
+#include "common/config-manager.h"
+#include "audio/audiostream.h"
+#include "audio/mpu401.h"
+#include "audio/musicplugin.h"
+#include "audio/mixer.h"
+
+//#define EAS_DUMPSTREAM
+
+// NOTE:
+// EAS's render function *only* accepts one mix buffer size. it's defined at
+// compile time of the library and can be retrieved via EASLibConfig.bufSize
+// (seen: 128 bytes).
+// to avoid local intermediate buffers, this implementation insists on a fixed
+// buffer size of the calling rate converter, which in return must be a
+// multiple of EAS's. that may change if there're hickups because slower
+// devices can't render fast enough
+
+// from rate_arm.cpp
+#define INTERMEDIATE_BUFFER_SIZE 512
+
+// so far all android versions have the very same library version
+#define EAS_LIBRARY "libsonivox.so"
+#define EAS_KNOWNVERSION 0x03060a0e
+
+#define EAS_REVERB 2
+#define EAS_REVERB_BYPASS 0
+#define EAS_REVERB_PRESET 1
+#define EAS_REVERB_CHAMBER 2
+
+class MidiDriver_EAS : public MidiDriver_MPU401, Audio::AudioStream {
+public:
+ MidiDriver_EAS();
+ virtual ~MidiDriver_EAS();
+
+ // MidiDriver
+ virtual int open();
+ virtual bool isOpen() const;
+ virtual void close();
+ virtual void send(uint32 b);
+ virtual void sysEx(const byte *msg, uint16 length);
+ virtual void setTimerCallback(void *timerParam,
+ Common::TimerManager::TimerProc timerProc);
+ virtual uint32 getBaseTempo();
+
+ // AudioStream
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const;
+ virtual int getRate() const;
+ virtual bool endOfData() const;
+
+private:
+ struct EASLibConfig {
+ uint32 version;
+ uint32 debug;
+ int32 voices;
+ int32 channels;
+ int32 rate;
+ int32 bufSize;
+ uint32 filter;
+ uint32 timeStamp;
+ char *GUID;
+ };
+
+ struct EASFile {
+ const char *path;
+ int fd;
+ long long offset;
+ long long length;
+ };
+
+ typedef void * EASDataHandle;
+ typedef void * EASHandle;
+
+ typedef EASLibConfig *(*ConfigFunc)();
+ typedef int32 (*InitFunc)(EASDataHandle *);
+ typedef int32 (*ShutdownFunc)(EASDataHandle);
+ typedef int32 (*LoadDLSFunc)(EASDataHandle, EASHandle, EASFile *);
+ typedef int32 (*SetParameterFunc)(EASDataHandle, int32, int32, int32);
+ typedef int32 (*SetVolumeFunc)(EASDataHandle, EASHandle, int32);
+ typedef int32 (*OpenStreamFunc)(EASDataHandle, EASHandle *, EASHandle);
+ typedef int32 (*WriteStreamFunc)(EASDataHandle, EASHandle, byte *, int32);
+ typedef int32 (*CloseStreamFunc)(EASDataHandle, EASHandle);
+ typedef int32 (*RenderFunc)(EASDataHandle, int16 *, int32, int32 *);
+
+ template<typename T>
+ void sym(T &t, const char *symbol) {
+ union {
+ void *v;
+ T t;
+ } u;
+
+ assert(sizeof(u.v) == sizeof(u.t));
+
+ u.v = dlsym(_dlHandle, symbol);
+
+ if (!u.v)
+ warning("couldn't resolve %s from " EAS_LIBRARY, symbol);
+
+ t = u.t;
+ }
+
+ void *_dlHandle;
+
+ ConfigFunc _configFunc;
+ InitFunc _initFunc;
+ ShutdownFunc _shutdownFunc;
+ LoadDLSFunc _loadDLSFunc;
+ SetParameterFunc _setParameterFunc;
+ SetVolumeFunc _setVolumeFunc;
+ OpenStreamFunc _openStreamFunc;
+ WriteStreamFunc _writeStreamFunc;
+ CloseStreamFunc _closeStreamFunc;
+ RenderFunc _renderFunc;
+
+ const EASLibConfig *_config;
+ EASDataHandle _EASHandle;
+ EASHandle _midiStream;
+
+ Common::TimerManager::TimerProc _timerProc;
+ void *_timerParam;
+ uint32 _baseTempo;
+ uint _rounds;
+ Audio::SoundHandle _soundHandle;
+
+ Common::DumpFile _dump;
+};
+
+MidiDriver_EAS::MidiDriver_EAS() :
+ MidiDriver_MPU401(),
+ _dlHandle(0),
+ _configFunc(0),
+ _initFunc(0),
+ _shutdownFunc(0),
+ _loadDLSFunc(0),
+ _setParameterFunc(0),
+ _setVolumeFunc(0),
+ _openStreamFunc(0),
+ _writeStreamFunc(0),
+ _closeStreamFunc(0),
+ _renderFunc(0),
+ _config(0),
+ _EASHandle(0),
+ _midiStream(0),
+ _timerProc(0),
+ _timerParam(0),
+ _baseTempo(0),
+ _rounds(0),
+ _soundHandle(),
+ _dump() {
+}
+
+MidiDriver_EAS::~MidiDriver_EAS() {
+}
+
+int MidiDriver_EAS::open() {
+ if (isOpen())
+ return MERR_ALREADY_OPEN;
+
+ _dlHandle = dlopen(EAS_LIBRARY, RTLD_LAZY);
+ if (!_dlHandle) {
+ warning("error opening " EAS_LIBRARY ": %s", dlerror());
+ return MERR_DEVICE_NOT_AVAILABLE;
+ }
+
+ sym(_configFunc, "EAS_Config");
+ if (!_configFunc) {
+ close();
+ return -1;
+ }
+
+ _config = _configFunc();
+ if (!_config) {
+ close();
+ warning("error retrieving EAS library configuration");
+ return -1;
+ }
+
+ if (_config->version != EAS_KNOWNVERSION) {
+ close();
+ warning("unknown EAS library version: 0x%08x", _config->version);
+ return -1;
+ }
+
+ if (_config->channels > 2) {
+ close();
+ warning("unsupported number of EAS channels: %d", _config->channels);
+ return -1;
+ }
+
+ // see note at top of this file
+ if (INTERMEDIATE_BUFFER_SIZE % (_config->bufSize * _config->channels)) {
+ close();
+ warning("unsupported EAS buffer size: %d", _config->bufSize);
+ return -1;
+ }
+
+ sym(_initFunc, "EAS_Init");
+ sym(_shutdownFunc, "EAS_Shutdown");
+ sym(_loadDLSFunc, "EAS_LoadDLSCollection");
+ sym(_setParameterFunc, "EAS_SetParameter");
+ sym(_setVolumeFunc, "EAS_SetVolume");
+ sym(_openStreamFunc, "EAS_OpenMIDIStream");
+ sym(_writeStreamFunc, "EAS_WriteMIDIStream");
+ sym(_closeStreamFunc, "EAS_CloseMIDIStream");
+ sym(_renderFunc, "EAS_Render");
+
+ if (!_initFunc || !_shutdownFunc || !_loadDLSFunc || !_setParameterFunc ||
+ !_openStreamFunc || !_writeStreamFunc || !_closeStreamFunc ||
+ !_renderFunc) {
+ close();
+ return -1;
+ }
+
+ int32 res = _initFunc(&_EASHandle);
+ if (res) {
+ close();
+ warning("error initializing the EAS library: %d", res);
+ return -1;
+ }
+
+ res = _setParameterFunc(_EASHandle, EAS_REVERB, EAS_REVERB_PRESET,
+ EAS_REVERB_CHAMBER);
+ if (res)
+ warning("error setting reverb preset: %d", res);
+
+ res = _setParameterFunc(_EASHandle, EAS_REVERB, EAS_REVERB_BYPASS, 0);
+ if (res)
+ warning("error disabling reverb bypass: %d", res);
+
+ // 90 is EAS's default, max is 100
+ // so the option slider will only work from 0.1 to 1.1
+ res = _setVolumeFunc(_EASHandle, 0, ConfMan.getInt("midi_gain") - 10);
+ if (res)
+ warning("error setting EAS master volume: %d", res);
+
+ res = _openStreamFunc(_EASHandle, &_midiStream, 0);
+ if (res) {
+ close();
+ warning("error opening EAS MIDI stream: %d", res);
+ return -1;
+ }
+
+ // set the timer frequency to match a single buffer size
+ _baseTempo = (1000000 * _config->bufSize) / _config->rate;
+
+ // number of buffer fills per readBuffer()
+ _rounds = INTERMEDIATE_BUFFER_SIZE / (_config->bufSize * _config->channels);
+
+ debug("EAS initialized (voices:%d channels:%d rate:%d buffer:%d) "
+ "tempo:%u rounds:%u", _config->voices, _config->channels,
+ _config->rate, _config->bufSize, _baseTempo, _rounds);
+
+ // TODO doesn't seem to work with midi streams?
+ if (ConfMan.hasKey("soundfont")) {
+ const Common::String dls = ConfMan.get("soundfont");
+
+ debug("loading DLS file '%s'", dls.c_str());
+
+ EASFile f;
+ memset(&f, 0, sizeof(EASFile));
+ f.path = dls.c_str();
+
+ res = _loadDLSFunc(_EASHandle, 0, &f);
+ if (res)
+ warning("error loading DLS file '%s': %d", dls.c_str(), res);
+ else
+ debug("DLS file loaded");
+ }
+
+#ifdef EAS_DUMPSTREAM
+ if (!_dump.open("/sdcard/eas.dump"))
+ warning("error opening EAS dump file");
+#endif
+
+ g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType,
+ &_soundHandle, this, -1,
+ Audio::Mixer::kMaxChannelVolume, 0,
+ DisposeAfterUse::NO, true);
+
+ return 0;
+}
+
+bool MidiDriver_EAS::isOpen() const {
+ return _dlHandle != 0;
+}
+
+void MidiDriver_EAS::close() {
+ MidiDriver_MPU401::close();
+
+ if (!isOpen())
+ return;
+
+ g_system->getMixer()->stopHandle(_soundHandle);
+
+#ifdef EAS_DUMPSTREAM
+ if (_dump.isOpen())
+ _dump.close();
+#endif
+
+ // not pretty, but better than a mutex
+ g_system->delayMillis((_baseTempo * _rounds) / 1000);
+
+ if (_midiStream) {
+ int32 res = _closeStreamFunc(_EASHandle, _midiStream);
+ if (res)
+ warning("error closing EAS MIDI stream: %d", res);
+
+ _midiStream = 0;
+ }
+
+ if (_EASHandle) {
+ int32 res = _shutdownFunc(_EASHandle);
+ if (res)
+ warning("error shutting down the EAS library: %d", res);
+
+ _EASHandle = 0;
+ }
+
+ if (dlclose(_dlHandle))
+ warning("error closing " EAS_LIBRARY ": %s", dlerror());
+
+ _dlHandle = 0;
+}
+
+void MidiDriver_EAS::send(uint32 b) {
+ byte buf[4];
+
+ WRITE_LE_UINT32(buf, b);
+
+ int32 len = 3;
+ if ((buf[0] >> 4) == 0xC || (buf[0] >> 4) == 0xD)
+ len = 2;
+
+ int32 res = _writeStreamFunc(_EASHandle, _midiStream, buf, len);
+ if (res)
+ warning("error writing to EAS MIDI stream: %d", res);
+}
+
+void MidiDriver_EAS::sysEx(const byte *msg, uint16 length) {
+ byte buf[266];
+
+ assert(length + 2 <= ARRAYSIZE(buf));
+
+ buf[0] = 0xF0;
+ memcpy(buf + 1, msg, length);
+ buf[length + 1] = 0xF7;
+
+ int32 res = _writeStreamFunc(_EASHandle, _midiStream, buf, length + 2);
+ if (res)
+ warning("error writing to EAS MIDI stream: %d", res);
+}
+
+void MidiDriver_EAS::setTimerCallback(void *timerParam,
+ Common::TimerManager::TimerProc timerProc) {
+ _timerParam = timerParam;
+ _timerProc = timerProc;
+}
+
+uint32 MidiDriver_EAS::getBaseTempo() {
+ return _baseTempo;
+}
+
+int MidiDriver_EAS::readBuffer(int16 *buffer, const int numSamples) {
+ // see note at top of this file
+ assert(numSamples == INTERMEDIATE_BUFFER_SIZE);
+
+ int32 res, c;
+
+ for (uint i = 0; i < _rounds; ++i) {
+ // pull in MIDI events for exactly one buffer size
+ if (_timerProc)
+ (*_timerProc)(_timerParam);
+
+ // if there are no MIDI events, this just renders silence
+ res = _renderFunc(_EASHandle, buffer, _config->bufSize, &c);
+ if (res) {
+ warning("error rendering EAS samples: %d", res);
+ return -1;
+ }
+
+#ifdef EAS_DUMPSTREAM
+ if (_dump.isOpen())
+ _dump.write(buffer, c * _config->channels * 2);
+#endif
+
+ buffer += c * _config->channels;
+ }
+
+ return numSamples;
+}
+
+bool MidiDriver_EAS::isStereo() const {
+ return _config->channels == 2;
+}
+
+int MidiDriver_EAS::getRate() const {
+ return _config->rate;
+}
+
+bool MidiDriver_EAS::endOfData() const {
+ return false;
+}
+
+class EASMusicPlugin : public MusicPluginObject {
+public:
+ EASMusicPlugin();
+ virtual ~EASMusicPlugin();
+
+ const char *getName() const;
+ const char *getId() const;
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver,
+ MidiDriver::DeviceHandle = 0) const;
+};
+
+EASMusicPlugin::EASMusicPlugin() {
+}
+
+EASMusicPlugin::~EASMusicPlugin() {
+}
+
+const char *EASMusicPlugin::getName() const {
+ return "Embedded Audio Synthesis";
+}
+
+const char *EASMusicPlugin::getId() const {
+ return "eas";
+}
+
+MusicDevices EASMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_GM));
+
+ return devices;
+}
+
+Common::Error EASMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ *mididriver = new MidiDriver_EAS();
+
+ return Common::kNoError;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(EAS)
+ //REGISTER_PLUGIN_DYNAMIC(EAS, PLUGIN_TYPE_MUSIC, EASMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(EAS, PLUGIN_TYPE_MUSIC, EASMusicPlugin);
+//#endif
+
+#endif
+
diff --git a/audio/softsynth/emumidi.h b/audio/softsynth/emumidi.h
index 35c81490e4..190b70c392 100644
--- a/audio/softsynth/emumidi.h
+++ b/audio/softsynth/emumidi.h
@@ -45,25 +45,24 @@ private:
int _samplesPerTick;
protected:
+ int _baseFreq;
+
virtual void generateSamples(int16 *buf, int len) = 0;
virtual void onTimer() {}
- int _baseFreq;
-
public:
- MidiDriver_Emulated(Audio::Mixer *mixer) : _mixer(mixer) {
- _isOpen = false;
-
- _timerProc = 0;
- _timerParam = 0;
-
- _nextTick = 0;
- _samplesPerTick = 0;
-
- _baseFreq = 250;
+ MidiDriver_Emulated(Audio::Mixer *mixer) :
+ _mixer(mixer),
+ _isOpen(false),
+ _timerProc(0),
+ _timerParam(0),
+ _nextTick(0),
+ _samplesPerTick(0),
+ _baseFreq(250) {
}
- int open() {
+ // MidiDriver API
+ virtual int open() {
_isOpen = true;
int d = getRate() / _baseFreq;
@@ -73,19 +72,23 @@ public:
// but less prone to arithmetic overflow.
_samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
+
return 0;
}
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
+ bool isOpen() const { return _isOpen; }
+
+ virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
_timerProc = timer_proc;
_timerParam = timer_param;
}
- uint32 getBaseTempo() { return 1000000 / _baseFreq; }
-
+ virtual uint32 getBaseTempo() {
+ return 1000000 / _baseFreq;
+ }
// AudioStream API
- int readBuffer(int16 *data, const int numSamples) {
+ virtual int readBuffer(int16 *data, const int numSamples) {
const int stereoFactor = isStereo() ? 2 : 1;
int len = numSamples / stereoFactor;
int step;
@@ -101,16 +104,22 @@ public:
if (!(_nextTick >> FIXP_SHIFT)) {
if (_timerProc)
(*_timerProc)(_timerParam);
+
onTimer();
+
_nextTick += _samplesPerTick;
}
+
data += step * stereoFactor;
len -= step;
} while (len);
return numSamples;
}
- bool endOfData() const { return false; }
+
+ virtual bool endOfData() const {
+ return false;
+ }
};
#endif
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index bd016548ec..f6f66ce5e8 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -40,7 +40,6 @@ private:
fluid_synth_t *_synth;
int _soundFont;
int _outputRate;
- Audio::SoundHandle _handle;
protected:
// Because GCC complains about casting from const to non-const...
@@ -144,7 +143,7 @@ int MidiDriver_FluidSynth::open() {
MidiDriver_Emulated::open();
// The MT-32 emulator uses kSFXSoundType here. I don't know why.
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -153,7 +152,7 @@ void MidiDriver_FluidSynth::close() {
return;
_isOpen = false;
- _mixer->stopHandle(_handle);
+ _mixer->stopHandle(_mixerSoundHandle);
if (_soundFont != -1)
fluid_synth_sfunload(_synth, _soundFont, 1);
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index f84fd841a6..67de8fa026 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -1253,7 +1253,7 @@ void TownsPC98_FmSynth::generateTables() {
delete[] _oprSinTbl;
_oprSinTbl = new uint32[1024];
for (int i = 0; i < 1024; i++) {
- double val = sin((double)(((i << 1) + 1) * PI / 1024.0));
+ double val = sin((double)(((i << 1) + 1) * M_PI / 1024.0));
double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
int32 i_dcb = (int32)(2.0 * d_dcb);
i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp
index 3a3958d494..dd2c7e2121 100644
--- a/audio/softsynth/mt32.cpp
+++ b/audio/softsynth/mt32.cpp
@@ -51,7 +51,6 @@ class MidiChannel_MT32 : public MidiChannel_MPU401 {
class MidiDriver_MT32 : public MidiDriver_Emulated {
private:
- Audio::SoundHandle _handle;
MidiChannel_MT32 _midiChannels[16];
uint16 _channelMask;
MT32Emu::Synth *_synth;
@@ -315,9 +314,9 @@ int MidiDriver_MT32::open() {
if (screenFormat.bytesPerPixel == 1) {
const byte dummy_palette[] = {
- 0, 0, 0, 0, // background
- 0, 171, 0, 0, // border, font
- 171, 0, 0, 0 // fill
+ 0, 0, 0, // background
+ 0, 171, 0, // border, font
+ 171, 0, 0 // fill
};
g_system->getPaletteManager()->setPalette(dummy_palette, 0, 3);
@@ -336,7 +335,7 @@ int MidiDriver_MT32::open() {
g_system->updateScreen();
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -378,7 +377,7 @@ void MidiDriver_MT32::close() {
// Detach the player callback handler
setTimerCallback(NULL, NULL);
// Detach the mixer callback handler
- _mixer->stopHandle(_handle);
+ _mixer->stopHandle(_mixerSoundHandle);
_synth->close();
delete _synth;
diff --git a/audio/softsynth/opl/dbopl.cpp b/audio/softsynth/opl/dbopl.cpp
index 47e263b6b9..2c46cfee75 100644
--- a/audio/softsynth/opl/dbopl.cpp
+++ b/audio/softsynth/opl/dbopl.cpp
@@ -41,10 +41,6 @@
namespace OPL {
namespace DOSBox {
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
namespace DBOPL {
#define OPLRATE ((double)(14318180.0 / 288.0))
@@ -1392,7 +1388,7 @@ void InitTables( void ) {
//Add 0.5 for the trunc rounding of the integer cast
//Do a PI sinetable instead of the original 0.5 PI
for ( int i = 0; i < 512; i++ ) {
- SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
+ SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
}
#endif
#if ( DBOPL_WAVE == WAVE_TABLEMUL )
@@ -1406,7 +1402,7 @@ void InitTables( void ) {
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
- WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
+ WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (M_PI / 512.0) ) * 4084);
WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
}
//Exponential wave
@@ -1418,7 +1414,7 @@ void InitTables( void ) {
#if ( DBOPL_WAVE == WAVE_TABLELOG )
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
- WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
+ WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
}
//Exponential wave
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index c875080e8f..b4bbcb5ab3 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -708,7 +708,7 @@ static int OPLOpenTable(void) {
/* degree 0 = degree 180 = off */
SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
for (s = 1;s <= SIN_ENT / 4; s++) {
- pom = sin(2 * PI * s / SIN_ENT); /* sin */
+ pom = sin(2 * M_PI * s / SIN_ENT); /* sin */
pom = 20 * log10(1 / pom); /* decibel */
j = int(pom / EG_STEP); /* TL_TABLE steps */
@@ -739,14 +739,14 @@ static int OPLOpenTable(void) {
ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
/* make LFO ams table */
for (i=0; i < AMS_ENT; i++) {
- pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
+ pom = (1.0 + sin(2 * M_PI * i / AMS_ENT)) / 2; /* sin */
AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
}
/* make LFO vibrate table */
for (i=0; i < VIB_ENT; i++) {
/* 100cent = 1seminote = 6% ?? */
- pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
+ pom = (double)VIB_RATE * 0.06 * sin(2 * M_PI * i / VIB_ENT); /* +-100sect step */
VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
}
diff --git a/audio/softsynth/pcspk.cpp b/audio/softsynth/pcspk.cpp
index 69ba113c8b..947c142b73 100644
--- a/audio/softsynth/pcspk.cpp
+++ b/audio/softsynth/pcspk.cpp
@@ -109,7 +109,7 @@ int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) {
return 0;
// TODO: Maybe using a look-up-table would be better?
- return CLIP<int16>((int16) (128 * sin(2.0 * PI * x / oscLength)), -128, 127);
+ return CLIP<int16>((int16) (128 * sin(2.0 * M_PI * x / oscLength)), -128, 127);
}
int8 PCSpeaker::generateSaw(uint32 x, uint32 oscLength) {
diff --git a/audio/softsynth/ym2612.cpp b/audio/softsynth/ym2612.cpp
index 94fcfb97db..6b3c2aab73 100644
--- a/audio/softsynth/ym2612.cpp
+++ b/audio/softsynth/ym2612.cpp
@@ -677,14 +677,14 @@ void MidiDriver_YM2612::createLookupTables() {
int i;
sintbl = new int [2048];
for (i = 0; i < 2048; i++)
- sintbl[i] = (int)(0xffff * sin(i/2048.0*2.0*PI));
+ sintbl[i] = (int)(0xffff * sin(i/2048.0 * 2.0 * M_PI));
}
{
int i;
powtbl = new int [1025];
for (i = 0; i <= 1024; i++)
- powtbl[i] = (int)(0x10000 * pow(2.0, (i-512)/512.0));
+ powtbl[i] = (int)(0x10000 * pow(2.0, (i - 512) / 512.0));
}
{
diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp
index 42ab7b887a..f349cc8005 100644
--- a/backends/base-backend.cpp
+++ b/backends/base-backend.cpp
@@ -101,7 +101,4 @@ AudioCDManager *BaseBackend::getAudioCDManager() {
}
void BaseBackend::resetGraphicsScale() {
- // As a hack, we use 0 here. Backends should override this method
- // and provide their own.
- setGraphicsMode(0);
}
diff --git a/backends/events/gp2xsdl/gp2xsdl-events.cpp b/backends/events/gp2xsdl/gp2xsdl-events.cpp
index 184f1d9b64..86d4de384f 100644
--- a/backends/events/gp2xsdl/gp2xsdl-events.cpp
+++ b/backends/events/gp2xsdl/gp2xsdl-events.cpp
@@ -18,22 +18,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
#include "common/scummsys.h"
-#if defined(GP2X) || defined(GP2XWIZ)
+#if defined(GP2X_OLD)
#include "backends/events/gp2xsdl/gp2xsdl-events.h"
-#if defined(GP2X)
#include "backends/platform/gp2x/gp2x-hw.h"
#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
-#else
-#include "backends/platform/gp2xwiz/gp2xwiz-hw.h"
-#endif
#include "backends/platform/sdl/sdl.h"
@@ -88,7 +81,6 @@ enum {
GP2XSdlEventSource::GP2XSdlEventSource()
: _buttonStateL(false){
-
}
void GP2XSdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
@@ -441,7 +433,7 @@ bool GP2XSdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event
_km.x_down_count = 0;
}
#endif
-
+
} else if (ev.jaxis.axis == JOY_YAXIS) {
#ifndef JOY_INVERT_Y
axis = -axis;
@@ -468,5 +460,4 @@ bool GP2XSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
return false;
}
-
#endif
diff --git a/backends/events/gp2xsdl/gp2xsdl-events.h b/backends/events/gp2xsdl/gp2xsdl-events.h
index 8ea533d052..0d74c1bcac 100644
--- a/backends/events/gp2xsdl/gp2xsdl-events.h
+++ b/backends/events/gp2xsdl/gp2xsdl-events.h
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
#if !defined(BACKEND_EVENTS_SDL_GP2X_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
@@ -29,7 +26,7 @@
#include "backends/events/sdl/sdl-events.h"
/**
- * SDL events manager for GP2X and GP2XWIZ
+ * SDL events manager for GP2X
*/
class GP2XSdlEventSource : public SdlEventSource {
public:
diff --git a/backends/platform/gph/gph-events.cpp b/backends/events/gph/gph-events.cpp
index 2a6237c794..d2b3483f84 100644
--- a/backends/platform/gph/gph-events.cpp
+++ b/backends/events/gph/gph-events.cpp
@@ -18,19 +18,19 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
+#include "common/scummsys.h"
+
/*
* GPH: Device Specific Event Handling.
- *
*/
-#include "backends/platform/gph/gph-sdl.h"
+#if defined(GPH_DEVICE)
+
+#include "backends/events/gph/gph-events.h"
+#include "backends/graphics/gph/gph-graphics.h"
#include "backends/platform/gph/gph-hw.h"
-#include "graphics/scaler/aspect.h"
#include "common/util.h"
#include "common/events.h"
@@ -78,7 +78,9 @@ int BUTTON_STATE_L = false;
BUTTON_SELECT = 62
};
-#else
+#endif
+
+#if defined(GP2XWIZ)
/* Wiz: Main Joystick Mappings */
enum {
@@ -115,6 +117,42 @@ int BUTTON_STATE_L = false;
#endif
+#if defined(GP2X)
+
+enum {
+ /* DPAD/Stick */
+ BUTTON_UP = 0,
+ BUTTON_UPLEFT = 1,
+ BUTTON_LEFT = 2,
+ BUTTON_DOWNLEFT = 3,
+ BUTTON_DOWN = 4,
+ BUTTON_DOWNRIGHT = 5,
+ BUTTON_RIGHT = 6,
+ BUTTON_UPRIGHT = 7,
+ /* Joystick Buttons */
+ BUTTON_MENU = 8, // Start on F100 GP2X
+ BUTTON_SELECT = 9,
+ BUTTON_L = 10,
+ BUTTON_R = 11,
+ BUTTON_A = 12,
+ BUTTON_B = 13,
+ BUTTON_X = 14,
+ BUTTON_Y = 15,
+ BUTTON_VOLUP = 16,
+ BUTTON_VOLDOWN = 17,
+ BUTTON_CLICK = 18
+};
+
+enum {
+ /* Unused Joystick Buttons on the GP2X */
+ BUTTON_HOME = 51,
+ BUTTON_HOLD = 52,
+ BUTTON_HELP = 53,
+ BUTTON_HELP2 = 54
+};
+
+#endif
+
enum {
/* Touchscreen TapMode */
TAPMODE_LEFT = 0,
@@ -122,48 +160,34 @@ enum {
TAPMODE_HOVER = 2
};
-static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
- if (key >= SDLK_F1 && key <= SDLK_F9) {
- return key - SDLK_F1 + Common::ASCII_F1;
- } else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
- return key - SDLK_KP0 + '0';
- } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
- return key;
- } else if (unicode) {
- return unicode;
- } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {
- return key & ~0x20;
- } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
- return 0;
- }
- return key;
-}
-
-
-void OSystem_GPH::fillMouseEvent(Common::Event &event, int x, int y) {
- if (_videoMode.mode == GFX_HALF && !_overlayVisible){
- event.mouse.x = x*2;
- event.mouse.y = y*2;
- } else {
- event.mouse.x = x;
- event.mouse.y = y;
- }
-
- // Update the "keyboard mouse" coords
- _km.x = x;
- _km.y = y;
-
- // Adjust for the screen scaling
- if (!_overlayVisible) {
- event.mouse.x /= _videoMode.scaleFactor;
- event.mouse.y /= _videoMode.scaleFactor;
- if (_videoMode.aspectRatioCorrection)
- event.mouse.y = aspect2Real(event.mouse.y);
- }
+GPHEventSource::GPHEventSource()
+ : _buttonStateL(false){
}
-
-void OSystem_GPH::moveStick() {
+//void GPHEventSource::fillMouseEvent(Common::Event &event, int x, int y) {
+// if (GPHGraphicsManager::_videoMode.mode == GFX_HALF && !GPHGraphicsManager::_overlayVisible){
+// event.mouse.x = x*2;
+// event.mouse.y = y*2;
+// } else {
+// event.mouse.x = x;
+// event.mouse.y = y;
+// }
+//
+// // Update the "keyboard mouse" coords
+// _km.x = x;
+// _km.y = y;
+//
+// // Adjust for the screen scaling
+// if (!_overlayVisible) {
+// event.mouse.x /= _videoMode.scaleFactor;
+// event.mouse.y /= _videoMode.scaleFactor;
+// if (_videoMode.aspectRatioCorrection)
+// event.mouse.y = aspect2Real(event.mouse.y);
+// }
+//}
+
+
+void GPHEventSource::moveStick() {
bool stickBtn[32];
memcpy(stickBtn, _stickBtn, sizeof(stickBtn));
@@ -208,7 +232,7 @@ void OSystem_GPH::moveStick() {
/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */
-bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONDOWN;
@@ -241,7 +265,7 @@ bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
return true;
}
-bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONUP;
@@ -270,7 +294,7 @@ bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
/* Custom handleJoyButtonDown/handleJoyButtonUp to deal with the joystick buttons on GPH devices */
-bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
_stickBtn[ev.jbutton.button] = 1;
event.kbd.flags = 0;
@@ -339,11 +363,11 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
if (BUTTON_STATE_L == true) {
GPH::ToggleTapMode();
if (GPH::tapmodeLevel == TAPMODE_LEFT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
} else if (GPH::tapmodeLevel == TAPMODE_RIGHT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
} else if (GPH::tapmodeLevel == TAPMODE_HOVER) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
}
} else {
event.kbd.keycode = Common::KEYCODE_SPACE;
@@ -363,17 +387,17 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
case BUTTON_VOLUP:
WIZ_HW::mixerMoveVolume(2);
if (WIZ_HW::volumeLevel == 100) {
- displayMessageOnOSD("Maximum Volume");
+ g_system->displayMessageOnOSD("Maximum Volume");
} else {
- displayMessageOnOSD("Increasing Volume");
+ g_system->displayMessageOnOSD("Increasing Volume");
}
break;
case BUTTON_VOLDOWN:
WIZ_HW::mixerMoveVolume(1);
if (WIZ_HW::volumeLevel == 0) {
- displayMessageOnOSD("Minimal Volume");
+ g_system->displayMessageOnOSD("Minimal Volume");
} else {
- displayMessageOnOSD("Decreasing Volume");
+ g_system->displayMessageOnOSD("Decreasing Volume");
}
break;
case BUTTON_HOLD:
@@ -382,18 +406,18 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
case BUTTON_HELP2:
GPH::ToggleTapMode();
if (GPH::tapmodeLevel == TAPMODE_LEFT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click");
} else if (GPH::tapmodeLevel == TAPMODE_RIGHT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click");
} else if (GPH::tapmodeLevel == TAPMODE_HOVER) {
- displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)");
}
break;
}
return true;
}
-bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
_stickBtn[ev.jbutton.button] = 0;
event.kbd.flags = 0;
@@ -476,6 +500,8 @@ bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
return true;
}
-bool OSystem_GPH::remapKey(SDL_Event &ev,Common::Event &event) {
+bool GPHEventSource::remapKey(SDL_Event &ev,Common::Event &event) {
return false;
}
+
+#endif
diff --git a/backends/events/gph/gph-events.h b/backends/events/gph/gph-events.h
new file mode 100644
index 0000000000..7672bffed2
--- /dev/null
+++ b/backends/events/gph/gph-events.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if !defined(BACKEND_EVENTS_GPH_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_GPH_H
+
+#include "backends/events/sdl/sdl-events.h"
+
+/*
+ * SDL Events manager for GPH devices.
+ */
+
+class GPHEventSource : public SdlEventSource {
+public:
+ GPHEventSource();
+
+protected:
+ bool _stickBtn[32];
+
+ /**
+ * Button state for L button modifier
+ */
+ bool _buttonStateL;
+
+ /**
+ * Handles the stick movement
+ */
+ void moveStick();
+
+ bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
+ bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
+ bool remapKey(SDL_Event &ev, Common::Event &event);
+};
+
+#endif /* BACKEND_EVENTS_GPH_H */
diff --git a/backends/platform/openpandora/op-events.cpp b/backends/events/openpandora/op-events.cpp
index 24283aa8ba..381cbf89e9 100644
--- a/backends/platform/openpandora/op-events.cpp
+++ b/backends/events/openpandora/op-events.cpp
@@ -18,16 +18,19 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
+#include "common/scummsys.h"
+
/*
* OpenPandora: Device Specific Event Handling.
*
*/
+#if defined(OPENPANDORA)
+
+#include "backends/events/openpandora/op-events.h"
+#include "backends/graphics/openpandora/op-graphics.h"
#include "backends/platform/openpandora/op-sdl.h"
#include "backends/platform/openpandora/op-options.h"
@@ -41,81 +44,87 @@ enum {
TAPMODE_HOVER = 2
};
+OPEventSource::OPEventSource()
+ : _buttonStateL(false){
+}
+
/* On the OpenPandora by default the ABXY and L/R Trigger buttons are returned by SDL as
(A): SDLK_HOME (B): SDLK_END (X): SDLK_PAGEDOWN (Y): SDLK_PAGEUP (L): SDLK_RSHIFT (R): SDLK_RCTRL
*/
-bool OSystem_OP::handleKeyDown(SDL_Event &ev, Common::Event &event) {
- switch (ev.key.keysym.sym) {
- case SDLK_HOME:
- event.type = Common::EVENT_LBUTTONDOWN;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_END:
- event.type = Common::EVENT_RBUTTONDOWN;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_PAGEDOWN:
- event.type = Common::EVENT_MAINMENU;
- return true;
- break;
- case SDLK_PAGEUP:
- OP::ToggleTapMode();
- if (OP::tapmodeLevel == TAPMODE_LEFT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
- } else if (OP::tapmodeLevel == TAPMODE_RIGHT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
- } else if (OP::tapmodeLevel == TAPMODE_HOVER) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
- }
- break;
- case SDLK_RSHIFT:
- BUTTON_STATE_L = true;
- break;
- case SDLK_RCTRL:
- break;
- default:
- return OSystem_SDL::handleKeyDown(ev, event);
- break;
- }
- return false;
-}
+bool OPEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
-bool OSystem_OP::handleKeyUp(SDL_Event &ev, Common::Event &event) {
- switch (ev.key.keysym.sym) {
- case SDLK_HOME:
- event.type = Common::EVENT_LBUTTONUP;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_END:
- event.type = Common::EVENT_RBUTTONUP;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_PAGEDOWN:
- event.type = Common::EVENT_MAINMENU;
- return true;
- break;
- case SDLK_PAGEUP:
- break;
- case SDLK_RSHIFT:
- BUTTON_STATE_L = false;
- break;
- case SDLK_RCTRL:
- break;
- default:
- return OSystem_SDL::handleKeyUp(ev, event);
- break;
+ if (ev.type == SDL_KEYDOWN) {
+ switch (ev.key.keysym.sym) {
+ case SDLK_HOME:
+ event.type = Common::EVENT_LBUTTONDOWN;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_END:
+ event.type = Common::EVENT_RBUTTONDOWN;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_PAGEDOWN:
+ event.type = Common::EVENT_MAINMENU;
+ return true;
+ break;
+ case SDLK_PAGEUP:
+ OP::ToggleTapMode();
+ if (OP::tapmodeLevel == TAPMODE_LEFT) {
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
+ } else if (OP::tapmodeLevel == TAPMODE_RIGHT) {
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
+ } else if (OP::tapmodeLevel == TAPMODE_HOVER) {
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
+ }
+ break;
+ case SDLK_RSHIFT:
+ BUTTON_STATE_L = true;
+ break;
+ case SDLK_RCTRL:
+ break;
+ default:
+ return false;
+ break;
+ }
+ return false;
+ } else {
+ switch (ev.key.keysym.sym) {
+ case SDLK_HOME:
+ event.type = Common::EVENT_LBUTTONUP;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_END:
+ event.type = Common::EVENT_RBUTTONUP;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_PAGEDOWN:
+ event.type = Common::EVENT_MAINMENU;
+ return true;
+ break;
+ case SDLK_PAGEUP:
+ break;
+ case SDLK_RSHIFT:
+ BUTTON_STATE_L = false;
+ break;
+ case SDLK_RCTRL:
+ break;
+ default:
+ return false;
+ break;
+ }
+ return false;
}
return false;
}
/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */
-bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
+bool OPEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONDOWN;
@@ -148,7 +157,7 @@ bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
return true;
}
-bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
+bool OPEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONUP;
@@ -174,3 +183,4 @@ bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
return true;
}
+#endif
diff --git a/backends/events/openpandora/op-events.h b/backends/events/openpandora/op-events.h
new file mode 100644
index 0000000000..9aa637992a
--- /dev/null
+++ b/backends/events/openpandora/op-events.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if !defined(BACKEND_EVENTS_OP_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_OP_H
+
+#include "backends/events/sdl/sdl-events.h"
+
+/**
+ * Events manager for the OpenPandora.
+ */
+class OPEventSource : public SdlEventSource {
+public:
+ OPEventSource();
+
+protected:
+ /** Button state for L button modifier */
+ bool _buttonStateL;
+
+ bool remapKey(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
+};
+
+#endif /* BACKEND_EVENTS_OP_H */
diff --git a/backends/events/webossdl/webossdl-events.cpp b/backends/events/webossdl/webossdl-events.cpp
new file mode 100644
index 0000000000..fd9628995d
--- /dev/null
+++ b/backends/events/webossdl/webossdl-events.cpp
@@ -0,0 +1,241 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifdef WEBOS
+
+#include "common/scummsys.h"
+#include "sys/time.h"
+#include "time.h"
+
+#include "backends/events/webossdl/webossdl-events.h"
+#include "gui/message.h"
+
+// Inidicates if gesture area is pressed down or not.
+static bool gestureDown = false;
+
+// The timestamp when gesture area was pressed down.
+static int gestureDownTime = 0;
+
+// The timestamp when screen was pressed down.
+static int screenDownTime = 0;
+
+// The timestamp when a possible drag operation was triggered.
+static int dragStartTime = 0;
+
+// The index of the motion pointer.
+static int motionPtrIndex = -1;
+
+// The maximum horizontal motion during dragging (For tap recognition).
+static int dragDiffX = 0;
+
+// The maximum vertical motion during dragging (For tap recognition).
+static int dragDiffY = 0;
+
+// Indicates if we are in drag mode.
+static bool dragging = false;
+
+// The current mouse position on the screen.
+static int curX = 0, curY = 0;
+
+// The time (seconds after 1/1/1970) when program started.
+static time_t programStartTime = time(0);
+
+/**
+ * Returns the number of passed milliseconds since program start.
+ *
+ * @return The number of passed milliseconds.
+ */
+static time_t getMillis()
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (time(0) - programStartTime) * 1000 + tv.tv_usec / 1000;
+}
+
+/**
+ * WebOS devices only have a Shift key and a CTRL key. There is also an Alt
+ * key (the orange key) but this is already processed by WebOS to change the
+ * mode of the keys so ScummVM must not use this key as a modifier. Instead
+ * pressing down the gesture area is used as Alt key.
+ *
+ * @param mod The pressed key modifier as detected by SDL.
+ * @param event The ScummVM event to setup.
+ */
+void WebOSSdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod,
+ Common::Event &event) {
+ event.kbd.flags = 0;
+
+ if (mod & KMOD_SHIFT)
+ event.kbd.flags |= Common::KBD_SHIFT;
+ if (mod & KMOD_CTRL)
+ event.kbd.flags |= Common::KBD_CTRL;
+ if (gestureDown)
+ event.kbd.flags |= Common::KBD_ALT;
+}
+
+/**
+ * Before calling the original SDL implementation this method checks if the
+ * gesture area is pressed down.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
+ // Handle gesture area tap.
+ if (ev.key.keysym.sym == SDLK_WORLD_71) {
+ gestureDown = true;
+ gestureDownTime = getMillis();
+ return true;
+ }
+
+ // Call original SDL key handler.
+ return SdlEventSource::handleKeyDown(ev, event);
+}
+
+/**
+ * Before calling the original SDL implementation this method checks if the
+ * gesture area has been released.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
+ // Handle gesture area tap.
+ if (ev.key.keysym.sym == SDLK_WORLD_71) {
+ gestureDown = false;
+ return true;
+ }
+
+ // Call original SDL key handler.
+ return SdlEventSource::handleKeyUp(ev, event);
+}
+
+/**
+ * Handles mouse button press.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
+ if (motionPtrIndex == -1) {
+ motionPtrIndex = ev.button.which;
+ dragDiffX = 0;
+ dragDiffY = 0;
+ screenDownTime = getMillis();
+
+ // Start dragging when pressing the screen shortly after a tap.
+ if (getMillis() - dragStartTime < 250) {
+ dragging = true;
+ event.type = Common::EVENT_LBUTTONDOWN;
+ fillMouseEvent(event, curX, curY);
+ }
+ }
+ return true;
+}
+
+/**
+ * Handles mouse button release.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
+ if (motionPtrIndex == ev.button.which) {
+ motionPtrIndex = -1;
+
+ // When drag mode was active then simply send a mouse up event
+ if (dragging)
+ {
+ event.type = Common::EVENT_LBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ dragging = false;
+ return true;
+ }
+
+ // When mouse was moved 5 pixels or less then emulate a mouse button
+ // click.
+ if (ABS(dragDiffX) < 6 && ABS(dragDiffY) < 6)
+ {
+ int duration = getMillis() - screenDownTime;
+
+ // When screen was pressed for less than 500ms then emulate a
+ // left mouse click.
+ if (duration < 500) {
+ event.type = Common::EVENT_LBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ g_system->getEventManager()->pushEvent(event);
+ event.type = Common::EVENT_LBUTTONDOWN;
+ dragStartTime = getMillis();
+ }
+
+ // When screen was pressed for less than 1000ms then emulate a
+ // right mouse click.
+ else if (duration < 1000) {
+ event.type = Common::EVENT_RBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ g_system->getEventManager()->pushEvent(event);
+ event.type = Common::EVENT_RBUTTONDOWN;
+ }
+
+ // When screen was pressed for more than 1000ms then emulate a
+ // middle mouse click.
+ else {
+ event.type = Common::EVENT_MBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ g_system->getEventManager()->pushEvent(event);
+ event.type = Common::EVENT_MBUTTONDOWN;
+ }
+
+ }
+ }
+ return true;
+}
+
+/**
+ * Handles mouse motion.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) {
+ if (ev.motion.which == motionPtrIndex) {
+ int screenX = g_system->getWidth();
+ int screenY = g_system->getHeight();
+ curX = MIN(screenX, MAX(0, curX + ev.motion.xrel));
+ curY = MIN(screenY, MAX(0, curY + ev.motion.yrel));
+ dragDiffX += ev.motion.xrel;
+ dragDiffY += ev.motion.yrel;
+ event.type = Common::EVENT_MOUSEMOVE;
+ fillMouseEvent(event, curX, curY);
+ }
+ return true;
+}
+
+#endif
diff --git a/engines/mohawk/myst_vars.h b/backends/events/webossdl/webossdl-events.h
index 065d8df2cb..3a41111cf2 100644
--- a/engines/mohawk/myst_vars.h
+++ b/backends/events/webossdl/webossdl-events.h
@@ -23,38 +23,22 @@
*
*/
-#include "mohawk/myst.h"
+#if !defined(BACKEND_EVENTS_SDL_WEBOS_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_SDL_WEBOS_H
-#ifndef MYST_VARS_H
-#define MYST_VARS_H
+#include "backends/events/sdl/sdl-events.h"
-namespace Mohawk {
-
-struct MystVarEntry {
- uint16 refNum;
- uint16 storage; // Used for Initial Value setting
- const char *description;
-};
-
-class MystVar {
-public:
- MystVar(MohawkEngine_Myst *vm);
- ~MystVar();
-
- // Only for use by Save/Load
- // All other code should use getVar() / setVar()
- void loadSetVar(uint16 stack, uint16 v, uint16 value);
- uint16 saveGetVar(uint16 stack, uint16 v);
-
- uint16 getVar(uint16 v);
- void setVar(uint16 v, uint16 value);
-
-private:
- MohawkEngine_Myst *_vm;
-
- Common::Array<MystVarEntry> _unknown;
+/**
+ * SDL events manager for WebOS
+ */
+class WebOSSdlEventSource : public SdlEventSource {
+protected:
+ virtual void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event);
+ virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event);
+ virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event);
+ virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
+ virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
+ virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event);
};
-} // End of namespace Mohawk
-
#endif
diff --git a/backends/events/wincesdl/wincesdl-events.cpp b/backends/events/wincesdl/wincesdl-events.cpp
new file mode 100644
index 0000000000..2505b0fb31
--- /dev/null
+++ b/backends/events/wincesdl/wincesdl-events.cpp
@@ -0,0 +1,332 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef _WIN32_WCE
+
+#include "common/config-manager.h"
+
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/platform/wince/CEActionsPocket.h"
+#include "backends/platform/wince/CEActionsSmartphone.h"
+#include "backends/platform/wince/CEDevice.h"
+
+#include "backends/platform/sdl/sdl.h"
+
+WINCESdlEventSource::WINCESdlEventSource()
+ : _tapTime(0), _closeClick(false), _rbutton(false),
+ _freeLook(false), _graphicsMan(0) {
+}
+
+void WINCESdlEventSource::init(WINCESdlGraphicsManager *graphicsMan) {
+ assert(graphicsMan);
+ _graphicsMan = graphicsMan;
+}
+
+void WINCESdlEventSource::fillMouseEvent(Common::Event &event, int x, int y) {
+ event.mouse.x = x;
+ event.mouse.y = y;
+
+ // Update the "keyboard mouse" coords
+ _km.x = event.mouse.x;
+ _km.y = event.mouse.y;
+
+ // Adjust for the screen scaling
+ if (_graphicsMan->_zoomDown)
+ event.mouse.y += 240;
+
+ event.mouse.x = event.mouse.x * _graphicsMan->_scaleFactorXd / _graphicsMan->_scaleFactorXm;
+ event.mouse.y = event.mouse.y * _graphicsMan->_scaleFactorYd / _graphicsMan->_scaleFactorYm;
+}
+
+bool WINCESdlEventSource::pollEvent(Common::Event &event) {
+ SDL_Event ev;
+ ev.type = SDL_NOEVENT;
+ DWORD currentTime;
+ bool keyEvent = false;
+ int deltaX, deltaY;
+
+ memset(&event, 0, sizeof(Common::Event));
+
+ handleKbdMouse();
+
+ // If the screen changed, send an Common::EVENT_SCREEN_CHANGED
+ int screenID = _graphicsMan->getScreenChangeID();
+ if (screenID != _lastScreenID) {
+ _lastScreenID = screenID;
+ event.type = Common::EVENT_SCREEN_CHANGED;
+ return true;
+ }
+
+ CEDevice::wakeUp();
+
+ currentTime = GetTickCount();
+
+ while (SDL_PollEvent(&ev)) {
+ switch (ev.type) {
+ case SDL_KEYDOWN:
+ debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
+ // KMOD_RESERVED is used if the key has been injected by an external buffer
+ if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) {
+ keyEvent = true;
+ _graphicsMan->_lastKeyPressed = ev.key.keysym.sym;
+ _graphicsMan->_keyRepeatTime = currentTime;
+ _graphicsMan->_keyRepeat = 0;
+
+ if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true))
+ return true;
+ }
+
+ if (GUI_Actions::Instance()->mappingActive())
+ event.kbd.flags = 0xFF;
+ else if (ev.key.keysym.sym == SDLK_PAUSE) {
+ _graphicsMan->_lastKeyPressed = 0;
+ event.type = Common::EVENT_PREDICTIVE_DIALOG;
+ return true;
+ }
+ event.type = Common::EVENT_KEYDOWN;
+ if (!GUI::Actions::Instance()->mappingActive())
+ event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
+ else
+ event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+ event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+
+ if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
+ event.kbd.ascii ^= 0x20;
+ event.kbd.flags = Common::KBD_SHIFT;
+ }
+
+ return true;
+
+ case SDL_KEYUP:
+ debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
+ // KMOD_RESERVED is used if the key has been injected by an external buffer
+ if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) {
+ keyEvent = true;
+ _graphicsMan->_lastKeyPressed = 0;
+
+ if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false))
+ return true;
+ }
+
+ if (GUI_Actions::Instance()->mappingActive())
+ event.kbd.flags = 0xFF;
+ else if (ev.key.keysym.sym == SDLK_PAUSE) {
+ _graphicsMan->_lastKeyPressed = 0;
+ return false; // chew up the show agi dialog key up event
+ }
+
+ event.type = Common::EVENT_KEYUP;
+ if (!GUI::Actions::Instance()->mappingActive())
+ event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
+ else
+ event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+ event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+
+ if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
+ event.kbd.ascii ^= 0x20;
+ event.kbd.flags = Common::KBD_SHIFT;
+ }
+
+ return true;
+
+ case SDL_MOUSEMOTION:
+ event.type = Common::EVENT_MOUSEMOVE;
+ fillMouseEvent(event, ev.motion.x, ev.motion.y);
+ _graphicsMan->setMousePos(event.mouse.x, event.mouse.y);
+
+ return true;
+
+ case SDL_MOUSEBUTTONDOWN:
+ if (ev.button.button == SDL_BUTTON_LEFT)
+ event.type = Common::EVENT_LBUTTONDOWN;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ event.type = Common::EVENT_RBUTTONDOWN;
+ else
+ break;
+ fillMouseEvent(event, ev.button.x, ev.button.y);
+
+
+ if (event.mouse.x > _tapX)
+ deltaX = event.mouse.x - _tapX;
+ else
+ deltaX = _tapX - event.mouse.x;
+ if (event.mouse.y > _tapY)
+ deltaY = event.mouse.y - _tapY;
+ else
+ deltaY = _tapY - event.mouse.y;
+ _closeClick = (deltaX <= 5 && deltaY <= 5);
+
+ if (!_isSmartphone) {
+ // handle double-taps
+ if (_tapTime) { // second tap
+ if (_closeClick && (GetTickCount() - _tapTime < 1000)) {
+ if (event.mouse.y <= 20 &&
+ _graphicsMan->_panelInitialized) {
+ // top of screen (show panel)
+ _graphicsMan->swap_panel_visibility();
+ } else if (!_graphicsMan->_noDoubleTapRMB) {
+ // right click
+ event.type = Common::EVENT_RBUTTONDOWN;
+ _rbutton = true;
+ }
+ }
+ _tapTime = 0;
+ } else {
+ _tapTime = GetTickCount();
+ _tapX = event.mouse.x;
+ _tapY = event.mouse.y;
+ }
+ }
+
+ if (_freeLook && !_closeClick) {
+ _rbutton = false;
+ _tapTime = 0;
+ _tapX = event.mouse.x;
+ _tapY = event.mouse.y;
+ event.type = Common::EVENT_MOUSEMOVE;
+ _graphicsMan->setMousePos(event.mouse.x, event.mouse.y);
+ }
+
+
+ if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) {
+ if (!_graphicsMan->_toolbarHandler.drawn()) {
+ _graphicsMan->_toolbarHighDrawn = false;
+ _graphicsMan->internUpdateScreen();
+ }
+ if (_graphicsMan->_newOrientation != _graphicsMan->_orientationLandscape) {
+ _graphicsMan->_orientationLandscape = _graphicsMan->_newOrientation;
+ _graphicsMan->_toolbarHighDrawn = false;
+ ConfMan.setInt("landscape", _graphicsMan->_orientationLandscape);
+ ConfMan.flushToDisk();
+ _graphicsMan->hotswapGFXMode();
+ }
+ return false;
+ }
+
+ return true;
+
+ case SDL_MOUSEBUTTONUP:
+ if (ev.button.button == SDL_BUTTON_LEFT)
+ event.type = Common::EVENT_LBUTTONUP;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ event.type = Common::EVENT_RBUTTONUP;
+ else
+ break;
+
+ if (_rbutton) {
+ event.type = Common::EVENT_RBUTTONUP;
+ _rbutton = false;
+ }
+
+ fillMouseEvent(event, ev.button.x, ev.button.y);
+
+ if (_freeLook && !_closeClick) {
+ _tapX = event.mouse.x;
+ _tapY = event.mouse.y;
+ event.type = Common::EVENT_MOUSEMOVE;
+ _graphicsMan->setMousePos(event.mouse.x, event.mouse.y);
+ }
+
+ if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) {
+ if (!_graphicsMan->_toolbarHandler.drawn()) {
+ _graphicsMan->_toolbarHighDrawn = false;
+ _graphicsMan->internUpdateScreen();
+ }
+ return false;
+
+ }
+ return true;
+
+ case SDL_VIDEOEXPOSE:
+ // HACK: Send a fake event, handled by SdlGraphicsManager
+ event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose;
+ break;
+
+ case SDL_QUIT:
+ event.type = Common::EVENT_QUIT;
+ return true;
+
+ case SDL_ACTIVEEVENT:
+ if (ev.active.state & SDL_APPMOUSEFOCUS)
+ debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost");
+ if (ev.active.state & SDL_APPINPUTFOCUS)
+ debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost");
+ if (ev.active.state & SDL_APPACTIVE)
+ debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost");
+ if (ev.active.state & SDL_APPINPUTFOCUS) {
+ _graphicsMan->_hasfocus = ev.active.gain;
+ SDL_PauseAudio(!_graphicsMan->_hasfocus);
+ if (_graphicsMan->_hasfocus) {
+ event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose;
+ }
+ }
+ break;
+ }
+ }
+
+ // Simulate repeated key for backend
+ if (!keyEvent && _graphicsMan->_lastKeyPressed && (int)currentTime > _graphicsMan->_keyRepeatTime + _graphicsMan->_keyRepeatTrigger) {
+ _graphicsMan->_keyRepeatTime = currentTime;
+ _graphicsMan->_keyRepeat++;
+ GUI_Actions::Instance()->performMapped(_graphicsMan->_lastKeyPressed, true);
+ }
+
+ return false;
+}
+
+int WINCESdlEventSource::mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) {
+ if (GUI::Actions::Instance()->mappingActive())
+ return key;
+
+ if (unfilter) {
+ switch (key) {
+ case SDLK_ESCAPE:
+ return SDLK_BACKSPACE;
+ case SDLK_F8:
+ return SDLK_ASTERISK;
+ case SDLK_F9:
+ return SDLK_HASH;
+ default:
+ return key;
+ }
+ }
+
+ if (key >= SDLK_KP0 && key <= SDLK_KP9) {
+ return key - SDLK_KP0 + '0';
+ } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
+ return key;
+ } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
+ return 0;
+ }
+ return key;
+}
+
+void WINCESdlEventSource::swap_freeLook() {
+ _freeLook = !_freeLook;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/backends/events/wincesdl/wincesdl-events.h b/backends/events/wincesdl/wincesdl-events.h
new file mode 100644
index 0000000000..f5b1026c46
--- /dev/null
+++ b/backends/events/wincesdl/wincesdl-events.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_EVENTS_SDL_WINCE_H
+#define BACKENDS_EVENTS_SDL_WINCE_H
+
+#include "common/scummsys.h"
+
+#ifdef _WIN32_WCE
+
+#include "backends/events/sdl/sdl-events.h"
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+
+extern bool _isSmartphone;
+
+class WINCESdlEventSource : public SdlEventSource {
+public:
+ WINCESdlEventSource();
+
+ void init(WINCESdlGraphicsManager *graphicsMan);
+
+ void loadDeviceConfiguration();
+
+ // Overloaded from SDL backend (toolbar handling)
+ bool pollEvent(Common::Event &event);
+ // Overloaded from SDL backend (mouse and new scaler handling)
+ void fillMouseEvent(Common::Event &event, int x, int y);
+
+ void swap_freeLook();
+
+protected:
+
+private:
+ int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter);
+
+ WINCESdlGraphicsManager *_graphicsMan;
+
+ // Keyboard tap
+ int _tapX;
+ int _tapY;
+ long _tapTime;
+
+ bool _closeClick; // flag when taps are spatially close together
+ bool _rbutton; // double tap -> right button simulation
+ bool _freeLook; // freeLook mode (do not send mouse button events)
+
+};
+
+#endif
+
+#endif /* BACKENDS_EVENTS_SDL_WINCE_H */
diff --git a/backends/graphics/default-palette.h b/backends/graphics/default-palette.h
index 6e3a75350e..12436aae51 100644
--- a/backends/graphics/default-palette.h
+++ b/backends/graphics/default-palette.h
@@ -38,7 +38,7 @@
*/
class DefaultPaletteManager : public PaletteManager {
protected:
- byte _palette[4 * 256];
+ byte _palette[3 * 256];
/**
* Subclasses should only implement this method and none of the others.
@@ -51,12 +51,12 @@ protected:
public:
void setPalette(const byte *colors, uint start, uint num) {
assert(start + num <= 256);
- memcpy(_palette + 4 * start, colors, 4 * num);
+ memcpy(_palette + 3 * start, colors, 3 * num);
setPaletteIntern(colors, start, num);
}
void grabPalette(byte *colors, uint start, uint num) {
assert(start + num <= 256);
- memcpy(colors, _palette + 4 * start, 4 * num);
+ memcpy(colors, _palette + 3 * start, 3 * num);
}
};
diff --git a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp
index 75a1f17674..6e5a35a1b1 100644
--- a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp
+++ b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp
@@ -18,14 +18,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
#include "common/scummsys.h"
-#ifdef GP2X
+#if defined(GP2X_OLD)
#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
#include "graphics/scaler/aspect.h"
diff --git a/backends/platform/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp
index 8fada7e40a..4f2185ef4b 100644
--- a/backends/platform/gph/gph-graphics.cpp
+++ b/backends/graphics/gph/gph-graphics.cpp
@@ -18,35 +18,35 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
-#include "backends/platform/gph/gph-sdl.h"
+#include "common/scummsys.h"
-#include "common/mutex.h"
-#include "graphics/font.h"
-#include "graphics/fontman.h"
-#include "graphics/scaler.h"
+#if defined(GPH_DEVICE)
+
+#include "backends/graphics/gph/gph-graphics.h"
+#include "backends/events/gph/gph-events.h"
#include "graphics/scaler/aspect.h"
-#include "graphics/scaler/downscaler.h"
-#include "graphics/surface.h"
+#include "common/mutex.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- {"1x", "Fullscreen", GFX_NORMAL},
+ {"1x", "Standard", GFX_NORMAL},
{0, 0, 0}
};
-const OSystem::GraphicsMode *OSystem_GPH::getSupportedGraphicsModes() const {
+GPHGraphicsManager::GPHGraphicsManager(SdlEventSource *boss)
+ : SdlGraphicsManager(boss) {
+}
+
+const OSystem::GraphicsMode *GPHGraphicsManager::getSupportedGraphicsModes() const {
return s_supportedGraphicsModes;
}
-int OSystem_GPH::getDefaultGraphicsMode() const {
+int GPHGraphicsManager::getDefaultGraphicsMode() const {
return GFX_NORMAL;
}
-bool OSystem_GPH::setGraphicsMode(int mode) {
+bool GPHGraphicsManager::setGraphicsMode(int mode) {
Common::StackLock lock(_graphicsMutex);
assert(_transactionMode == kTransactionActive);
@@ -80,7 +80,7 @@ bool OSystem_GPH::setGraphicsMode(int mode) {
return true;
}
-void OSystem_GPH::setGraphicsModeIntern() {
+void GPHGraphicsManager::setGraphicsModeIntern() {
Common::StackLock lock(_graphicsMutex);
ScalerProc *newScalerProc = 0;
@@ -109,7 +109,7 @@ void OSystem_GPH::setGraphicsModeIntern() {
blitCursor();
}
-void OSystem_GPH::initSize(uint w, uint h) {
+void GPHGraphicsManager::initSize(uint w, uint h) {
assert(_transactionMode == kTransactionActive);
// Avoid redundant res changes
@@ -121,41 +121,13 @@ void OSystem_GPH::initSize(uint w, uint h) {
if (w > 320 || h > 240){
setGraphicsMode(GFX_HALF);
setGraphicsModeIntern();
- toggleMouseGrab();
+ _sdlEventSource->toggleMouseGrab();
}
_transactionDetails.sizeChanged = true;
}
-bool OSystem_GPH::loadGFXMode() {
- if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) {
- _videoMode.aspectRatioCorrection = false;
- setGraphicsMode(GFX_HALF);
- printf("GFX_HALF\n");
- } else {
- setGraphicsMode(GFX_NORMAL);
- printf("GFX_NORMAL\n");
- }
-
- if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) {
- _videoMode.overlayWidth = _videoMode.screenWidth / 2;
- _videoMode.overlayHeight = _videoMode.screenHeight / 2;
- _videoMode.fullscreen = true;
- } else {
-
- _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
-
- if (_videoMode.aspectRatioCorrection)
- _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
-
- _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.hardwareHeight = effectiveScreenHeight();
- }
- return OSystem_SDL::loadGFXMode();
-}
-
-void OSystem_GPH::drawMouse() {
+void GPHGraphicsManager::drawMouse() {
if (!_mouseVisible || !_mouseSurface) {
_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
return;
@@ -226,7 +198,7 @@ void OSystem_GPH::drawMouse() {
addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);
}
-void OSystem_GPH::undrawMouse() {
+void GPHGraphicsManager::undrawMouse() {
const int x = _mouseBackup.x;
const int y = _mouseBackup.y;
@@ -244,7 +216,7 @@ void OSystem_GPH::undrawMouse() {
}
}
-void OSystem_GPH::internUpdateScreen() {
+void GPHGraphicsManager::internUpdateScreen() {
SDL_Surface *srcSurf, *origSurf;
int height, width;
ScalerProc *scalerProc;
@@ -443,28 +415,124 @@ void OSystem_GPH::internUpdateScreen() {
_mouseNeedsRedraw = false;
}
-void OSystem_GPH::showOverlay() {
+void GPHGraphicsManager::showOverlay() {
if (_videoMode.mode == GFX_HALF){
_mouseCurState.x = _mouseCurState.x / 2;
_mouseCurState.y = _mouseCurState.y / 2;
}
- OSystem_SDL::showOverlay();
+ SdlGraphicsManager::showOverlay();
}
-void OSystem_GPH::hideOverlay() {
+void GPHGraphicsManager::hideOverlay() {
if (_videoMode.mode == GFX_HALF){
_mouseCurState.x = _mouseCurState.x * 2;
_mouseCurState.y = _mouseCurState.y * 2;
}
- OSystem_SDL::hideOverlay();
+ SdlGraphicsManager::hideOverlay();
}
-void OSystem_GPH::warpMouse(int x, int y) {
+
+bool GPHGraphicsManager::loadGFXMode() {
+
+ /* Forcefully disable aspect ratio correction for games
+ that start with a native 240px height resolution
+ This corrects games with non-standard resolutions
+ such as MM Nes (256x240).
+ */
+
+ if(_videoMode.screenHeight == 240) {
+ _videoMode.aspectRatioCorrection = false;
+ }
+
+ fprintf(stdout, "Game ScreenMode = %d*%d\n", _videoMode.screenWidth, _videoMode.screenHeight);
+ if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) {
+ _videoMode.aspectRatioCorrection = false;
+ setGraphicsMode(GFX_HALF);
+ fprintf(stdout, "GraphicsMode set to HALF\n");
+ } else {
+ setGraphicsMode(GFX_NORMAL);
+ fprintf(stdout, "GraphicsMode set to NORMAL\n");
+ }
+
+ if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) {
+ _videoMode.overlayWidth = _videoMode.screenWidth / 2;
+ _videoMode.overlayHeight = _videoMode.screenHeight / 2;
+ _videoMode.fullscreen = true;
+ } else {
+
+ _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+
+ if (_videoMode.aspectRatioCorrection)
+ _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
+
+ _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ _videoMode.hardwareHeight = effectiveScreenHeight();
+ }
+ return SdlGraphicsManager::loadGFXMode();
+}
+
+bool GPHGraphicsManager::hasFeature(OSystem::Feature f) {
+ return
+ (f == OSystem::kFeatureAspectRatioCorrection) ||
+ (f == OSystem::kFeatureCursorHasPalette);
+}
+
+void GPHGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ switch (f) {
+ case OSystem::kFeatureAspectRatioCorrection:
+ setAspectRatioCorrection(enable);
+ break;
+ default:
+ break;
+ }
+}
+
+bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) {
+ assert(_transactionMode == kTransactionNone);
+
+ switch (f) {
+ case OSystem::kFeatureAspectRatioCorrection:
+ return _videoMode.aspectRatioCorrection;
+ default:
+ return false;
+ }
+}
+
+SdlGraphicsManager::MousePos* GPHGraphicsManager::getMouseCurState() {
+ return &_mouseCurState;
+}
+
+SdlGraphicsManager::VideoState* GPHGraphicsManager::getVideoMode() {
+ return &_videoMode;
+}
+
+void GPHGraphicsManager::warpMouse(int x, int y) {
if (_mouseCurState.x != x || _mouseCurState.y != y) {
if (_videoMode.mode == GFX_HALF && !_overlayVisible){
x = x / 2;
y = y / 2;
}
}
- OSystem_SDL::warpMouse(x, y);
+ SdlGraphicsManager::warpMouse(x, y);
+}
+
+void GPHGraphicsManager::adjustMouseEvent(const Common::Event &event) {
+ if (!event.synthetic) {
+ Common::Event newEvent(event);
+ newEvent.synthetic = true;
+ if (!_overlayVisible) {
+ if (_videoMode.mode == GFX_HALF) {
+ newEvent.mouse.x *= 2;
+ newEvent.mouse.y *= 2;
+ }
+ newEvent.mouse.x /= _videoMode.scaleFactor;
+ newEvent.mouse.y /= _videoMode.scaleFactor;
+ if (_videoMode.aspectRatioCorrection)
+ newEvent.mouse.y = aspect2Real(newEvent.mouse.y);
+ }
+ g_system->getEventManager()->pushEvent(newEvent);
+ }
}
+
+#endif
diff --git a/backends/graphics/gph/gph-graphics.h b/backends/graphics/gph/gph-graphics.h
new file mode 100644
index 0000000000..6ba2b344a6
--- /dev/null
+++ b/backends/graphics/gph/gph-graphics.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_GPH_H
+#define BACKENDS_GRAPHICS_GPH_H
+
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "graphics/scaler/aspect.h" // for aspect2Real
+#include "graphics/scaler/downscaler.h"
+
+enum {
+ GFX_HALF = 12
+};
+
+class GPHGraphicsManager : public SdlGraphicsManager {
+public:
+ GPHGraphicsManager(SdlEventSource *boss);
+
+ bool hasFeature(OSystem::Feature f);
+ void setFeatureState(OSystem::Feature f, bool enable);
+ bool getFeatureState(OSystem::Feature f);
+ int getDefaultGraphicsMode() const;
+
+ void initSize(uint w, uint h);
+ const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ bool setGraphicsMode(const char *name);
+ bool setGraphicsMode(int mode);
+ void setGraphicsModeIntern();
+ void internUpdateScreen();
+ void showOverlay();
+ void hideOverlay();
+ bool loadGFXMode();
+ void drawMouse();
+ void undrawMouse();
+ virtual void warpMouse(int x, int y);
+
+ SdlGraphicsManager::MousePos *getMouseCurState();
+ SdlGraphicsManager::VideoState *getVideoMode();
+
+ virtual void adjustMouseEvent(const Common::Event &event);
+};
+
+#endif /* BACKENDS_GRAPHICS_GPH_H */
diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp
index cd9e23cb71..7b7d40f174 100644
--- a/backends/graphics/opengl/gltexture.cpp
+++ b/backends/graphics/opengl/gltexture.cpp
@@ -149,7 +149,7 @@ void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLu
glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
// Check if the buffer has its data contiguously
- if (static_cast<int>(w) * _bytesPerPixel == pitch && w == _textureWidth) {
+ if (static_cast<int>(w) * _bytesPerPixel == pitch) {
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
_glFormat, _glType, buf); CHECK_GL_ERROR();
} else {
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index cee80f9dc0..4ac2747d25 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -33,6 +33,9 @@
#include "common/file.h"
#include "common/mutex.h"
#include "common/translation.h"
+#ifdef USE_OSD
+#include "common/tokenizer.h"
+#endif
#include "graphics/font.h"
#include "graphics/fontman.h"
@@ -50,8 +53,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
_cursorVisible(false), _cursorKeyColor(0),
_cursorTargetScale(1),
_formatBGR(false),
- _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0),
- _aspectRatioCorrection(false) {
+ _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0) {
memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
memset(&_videoMode, 0, sizeof(_videoMode));
@@ -62,8 +64,8 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
_videoMode.fullscreen = ConfMan.getBool("fullscreen");
_videoMode.antialiasing = false;
- _gamePalette = (byte *)calloc(sizeof(byte) * 4, 256);
- _cursorPalette = (byte *)calloc(sizeof(byte) * 4, 256);
+ _gamePalette = (byte *)calloc(sizeof(byte) * 3, 256);
+ _cursorPalette = (byte *)calloc(sizeof(byte) * 3, 256);
}
OpenGLGraphicsManager::~OpenGLGraphicsManager() {
@@ -96,17 +98,31 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ setFullscreenMode(enable);
+ break;
+
case OSystem::kFeatureAspectRatioCorrection:
- _videoMode.mode = OpenGL::GFX_4_3;
- _aspectRatioCorrection = enable;
+ _videoMode.aspectRatioCorrection = enable;
+ _transactionDetails.needRefresh = true;
break;
+
default:
break;
}
}
bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
- return false;
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return _videoMode.fullscreen;
+
+ case OSystem::kFeatureAspectRatioCorrection:
+ return _videoMode.aspectRatioCorrection;
+
+ default:
+ return false;
+ }
}
//
@@ -116,7 +132,6 @@ bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
{"gl1", _s("OpenGL Normal"), OpenGL::GFX_NORMAL},
{"gl2", _s("OpenGL Conserve"), OpenGL::GFX_CONSERVE},
- {"gl3", _s("OpenGL 4/3"), OpenGL::GFX_4_3},
{"gl4", _s("OpenGL Original"), OpenGL::GFX_ORIGINAL},
{0, 0, 0}
};
@@ -136,17 +151,18 @@ int OpenGLGraphicsManager::getDefaultGraphicsMode() const {
bool OpenGLGraphicsManager::setGraphicsMode(int mode) {
assert(_transactionMode == kTransactionActive);
+ setScale(2);
+
if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
return true;
switch (mode) {
case OpenGL::GFX_NORMAL:
case OpenGL::GFX_CONSERVE:
- case OpenGL::GFX_4_3:
case OpenGL::GFX_ORIGINAL:
break;
default:
- warning("unknown gfx mode %d", mode);
+ warning("Unknown gfx mode %d", mode);
return false;
}
@@ -166,11 +182,9 @@ void OpenGLGraphicsManager::resetGraphicsScale() {
}
#ifdef USE_RGB_COLOR
-
Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const {
return _screenFormat;
}
-
#endif
void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
@@ -308,13 +322,13 @@ int16 OpenGLGraphicsManager::getWidth() {
void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
assert(colors);
-
+
#ifdef USE_RGB_COLOR
assert(_screenFormat.bytesPerPixel == 1);
#endif
// Save the screen palette
- memcpy(_gamePalette + start * 4, colors, num * 4);
+ memcpy(_gamePalette + start * 3, colors, num * 3);
_screenNeedsRedraw = true;
@@ -324,13 +338,13 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
assert(colors);
-
+
#ifdef USE_RGB_COLOR
assert(_screenFormat.bytesPerPixel == 1);
#endif
// Copies current palette to buffer
- memcpy(colors, _gamePalette + start * 4, num * 4);
+ memcpy(colors, _gamePalette + start * 3, num * 3);
}
void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
@@ -341,9 +355,9 @@ void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x,
// Copy buffer data to game screen internal buffer
const byte *src = buf;
- byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch;
+ byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch + x * _screenData.bytesPerPixel;
for (int i = 0; i < h; i++) {
- memcpy(dst + x * _screenData.bytesPerPixel, src, w * _screenData.bytesPerPixel);
+ memcpy(dst, src, w * _screenData.bytesPerPixel);
src += pitch;
dst += _screenData.pitch;
}
@@ -367,6 +381,7 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) {
if (_gameTexture == NULL)
return;
+#ifdef USE_RGB_COLOR
if (_screenFormat.bytesPerPixel == 1) {
memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
} else if (_screenFormat.bytesPerPixel == 2) {
@@ -392,7 +407,9 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) {
pixels[i] = col;
}
}
-
+#else
+ memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
+#endif
_screenNeedsRedraw = true;
}
@@ -537,13 +554,53 @@ bool OpenGLGraphicsManager::showMouse(bool visible) {
return last;
}
-void OpenGLGraphicsManager::setMousePos(int x, int y) {
- _cursorState.x = x;
- _cursorState.y = y;
-}
-
void OpenGLGraphicsManager::warpMouse(int x, int y) {
- setMousePos(x, y);
+ int scaledX = x;
+ int scaledY = y;
+
+ int16 currentX = _cursorState.x;
+ int16 currentY = _cursorState.y;
+
+ adjustMousePosition(currentX, currentY);
+
+ // Do not adjust the real screen position, when the current game / overlay
+ // coordinates match the requested coordinates. This avoids a slight
+ // movement which might occur otherwise when the mouse is at a subpixel
+ // position.
+ if (x == currentX && y == currentY)
+ return;
+
+ if (_videoMode.mode == OpenGL::GFX_NORMAL) {
+ if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
+ scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth;
+ if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
+ scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight;
+
+ if (!_overlayVisible) {
+ scaledX *= _videoMode.scaleFactor;
+ scaledY *= _videoMode.scaleFactor;
+ }
+ } else {
+ if (_overlayVisible) {
+ if (_displayWidth != _videoMode.overlayWidth)
+ scaledX = scaledX * _displayWidth / _videoMode.overlayWidth;
+ if (_displayHeight != _videoMode.overlayHeight)
+ scaledY = scaledY * _displayHeight / _videoMode.overlayHeight;
+ } else {
+ if (_displayWidth != _videoMode.screenWidth)
+ scaledX = scaledX * _displayWidth / _videoMode.screenWidth;
+ if (_displayHeight != _videoMode.screenHeight)
+ scaledY = scaledY * _displayHeight / _videoMode.screenHeight;
+ }
+
+ scaledX += _displayX;
+ scaledY += _displayY;
+ }
+
+ setInternalMousePosition(scaledX, scaledY);
+
+ _cursorState.x = scaledX;
+ _cursorState.y = scaledY;
}
void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
@@ -558,7 +615,8 @@ void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int
#endif
// Allocate space for cursor data
- if (_cursorData.w != w || _cursorData.h != h)
+ if (_cursorData.w != w || _cursorData.h != h ||
+ _cursorData.bytesPerPixel != _cursorFormat.bytesPerPixel)
_cursorData.create(w, h, _cursorFormat.bytesPerPixel);
// Save cursor data
@@ -580,7 +638,7 @@ void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uin
assert(colors);
// Save the cursor palette
- memcpy(_cursorPalette + start * 4, colors, num * 4);
+ memcpy(_cursorPalette + start * 3, colors, num * 3);
_cursorPaletteDisabled = false;
_cursorNeedsRedraw = true;
@@ -599,61 +657,13 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
assert(_transactionMode == kTransactionNone);
assert(msg);
- // The font we are going to use:
- const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
-
- if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
- _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2);
- else
- // Clear everything
- memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
-
+#ifdef USE_OSD
// Split the message into separate lines.
- Common::Array<Common::String> lines;
- const char *ptr;
- for (ptr = msg; *ptr; ++ptr) {
- if (*ptr == '\n') {
- lines.push_back(Common::String(msg, ptr - msg));
- msg = ptr + 1;
- }
- }
- lines.push_back(Common::String(msg, ptr - msg));
+ _osdLines.clear();
- // Determine a rect which would contain the message string (clipped to the
- // screen dimensions).
- const int vOffset = 6;
- const int lineSpacing = 1;
- const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
- int width = 0;
- int height = lineHeight * lines.size() + 2 * vOffset;
- for (uint i = 0; i < lines.size(); i++) {
- width = MAX(width, font->getStringWidth(lines[i]) + 14);
- }
-
- // Clip the rect
- if (width > _osdSurface.w)
- width = _osdSurface.w;
- if (height > _osdSurface.h)
- height = _osdSurface.h;
-
- int dstX = (_osdSurface.w - width) / 2;
- int dstY = (_osdSurface.h - height) / 2;
-
- // Draw a dark gray rect
- uint16 color = 0x294B;
- uint16 *dst = (uint16 *)_osdSurface.pixels + dstY * _osdSurface.w + dstX;
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++)
- dst[j] = color;
- dst += _osdSurface.w;
- }
-
- // Render the message, centered, and in white
- for (uint i = 0; i < lines.size(); i++) {
- font->drawString(&_osdSurface, lines[i],
- dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
- 0xFFFF, Graphics::kTextAlignCenter);
- }
+ Common::StringTokenizer tokenizer(msg, "\n");
+ while (!tokenizer.empty())
+ _osdLines.push_back(tokenizer.nextToken());
// Request update of the texture
_requireOSDUpdate = true;
@@ -661,12 +671,25 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
// Init the OSD display parameters, and the fade out
_osdAlpha = kOSDInitialAlpha;
_osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay;
+#endif
}
//
// Intern
//
+void OpenGLGraphicsManager::setFullscreenMode(bool enable) {
+ assert(_transactionMode == kTransactionActive);
+
+ if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
+ return;
+
+ if (_transactionMode == kTransactionActive) {
+ _videoMode.fullscreen = enable;
+ _transactionDetails.needRefresh = true;
+ }
+}
+
void OpenGLGraphicsManager::refreshGameScreen() {
if (_screenNeedsRedraw)
_screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h);
@@ -686,9 +709,9 @@ void OpenGLGraphicsManager::refreshGameScreen() {
byte *dst = surface;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 4];
- dst[1] = _gamePalette[src[j] * 4 + 1];
- dst[2] = _gamePalette[src[j] * 4 + 2];
+ dst[0] = _gamePalette[src[j] * 3];
+ dst[1] = _gamePalette[src[j] * 3 + 1];
+ dst[2] = _gamePalette[src[j] * 3 + 2];
dst += 3;
}
src += _screenData.pitch;
@@ -728,9 +751,9 @@ void OpenGLGraphicsManager::refreshOverlay() {
byte *dst = surface;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 4];
- dst[1] = _gamePalette[src[j] * 4 + 1];
- dst[2] = _gamePalette[src[j] * 4 + 2];
+ dst[0] = _gamePalette[src[j] * 3];
+ dst[1] = _gamePalette[src[j] * 3 + 1];
+ dst[2] = _gamePalette[src[j] * 3 + 2];
dst += 3;
}
src += _screenData.pitch;
@@ -754,11 +777,17 @@ void OpenGLGraphicsManager::refreshOverlay() {
void OpenGLGraphicsManager::refreshCursor() {
_cursorNeedsRedraw = false;
- if (_cursorFormat.bytesPerPixel == 1) {
- // Create a temporary RGBA8888 surface
- byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
- memset(surface, 0, _cursorState.w * _cursorState.h * 4);
+ // Allocate a texture big enough for cursor
+ _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
+
+ // Create a temporary RGBA8888 surface
+ byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
+ memset(surface, 0, _cursorState.w * _cursorState.h * 4);
+
+ byte *dst = surface;
+ // Convert the paletted cursor to RGBA8888
+ if (_cursorFormat.bytesPerPixel == 1) {
// Select palette
byte *palette;
if (_cursorPaletteDisabled)
@@ -768,27 +797,52 @@ void OpenGLGraphicsManager::refreshCursor() {
// Convert the paletted cursor to RGBA8888
const byte *src = (byte *)_cursorData.pixels;
- byte *dst = surface;
for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
// Check for keycolor
if (src[i] != _cursorKeyColor) {
- dst[0] = palette[src[i] * 4];
- dst[1] = palette[src[i] * 4 + 1];
- dst[2] = palette[src[i] * 4 + 2];
+ dst[0] = palette[src[i] * 3];
+ dst[1] = palette[src[i] * 3 + 1];
+ dst[2] = palette[src[i] * 3 + 2];
dst[3] = 255;
}
dst += 4;
}
+ } else {
+ const bool gotNoAlpha = (_cursorFormat.aLoss == 8);
+
+ // Convert the RGB cursor to RGBA8888
+ if (_cursorFormat.bytesPerPixel == 2) {
+ const uint16 *src = (uint16 *)_cursorData.pixels;
+ for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
+ // Check for keycolor
+ if (src[i] != _cursorKeyColor) {
+ _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]);
+
+ if (gotNoAlpha)
+ dst[3] = 255;
+ }
+ dst += 4;
+ }
+ } else if (_cursorFormat.bytesPerPixel == 4) {
+ const uint32 *src = (uint32 *)_cursorData.pixels;
+ for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
+ // Check for keycolor
+ if (src[i] != _cursorKeyColor) {
+ _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]);
+
+ if (gotNoAlpha)
+ dst[3] = 255;
+ }
+ dst += 4;
+ }
+ }
+ }
- // Allocate a texture big enough for cursor
- _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
-
- // Update the texture with new cursor
- _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h);
+ // Update the texture with new cursor
+ _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h);
- // Free the temp surface
- delete[] surface;
- }
+ // Free the temp surface
+ delete[] surface;
}
void OpenGLGraphicsManager::refreshCursorScale() {
@@ -811,7 +865,8 @@ void OpenGLGraphicsManager::refreshCursorScale() {
} else {
// Otherwise, scale the cursor for the overlay
int targetScaleFactor = MIN(_cursorTargetScale, _videoMode.scaleFactor);
- int actualFactor = screenScaleFactor - (targetScaleFactor - 1) * 10000;
+ // We limit the maximum scale to 3 here to avoid too big cursors, for large overlay resolutions
+ int actualFactor = MIN<uint>(3, screenScaleFactor - (targetScaleFactor - 1)) * 10000;
_cursorState.rW = (int16)(_cursorState.w * actualFactor / 10000);
_cursorState.rH = (int16)(_cursorState.h * actualFactor / 10000);
_cursorState.rHotX = (int16)(_cursorState.hotX * actualFactor / 10000);
@@ -827,8 +882,8 @@ void OpenGLGraphicsManager::refreshCursorScale() {
void OpenGLGraphicsManager::calculateDisplaySize(int &width, int &height) {
if (_videoMode.mode == OpenGL::GFX_ORIGINAL) {
- width = _videoMode.overlayWidth;
- height = _videoMode.overlayHeight;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
} else {
width = _videoMode.hardwareWidth;
height = _videoMode.hardwareHeight;
@@ -873,6 +928,11 @@ void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat,
intFormat = GL_RGBA;
glFormat = GL_RGBA;
gltype = GL_UNSIGNED_SHORT_5_5_5_1;
+ } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555
+ bpp = 2;
+ intFormat = GL_RGB;
+ glFormat = GL_BGRA;
+ gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444
bpp = 2;
intFormat = GL_RGBA;
@@ -963,7 +1023,7 @@ void OpenGLGraphicsManager::internUpdateScreen() {
refreshOverlay();
// Draw the overlay
- _overlayTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight);
+ _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight);
}
if (_cursorVisible) {
@@ -990,9 +1050,7 @@ void OpenGLGraphicsManager::internUpdateScreen() {
#ifdef USE_OSD
if (_osdAlpha > 0) {
if (_requireOSDUpdate) {
- // Update the texture
- _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
- _osdSurface.w, _osdSurface.h);
+ updateOSD();
_requireOSDUpdate = false;
}
@@ -1059,10 +1117,14 @@ void OpenGLGraphicsManager::initGL() {
void OpenGLGraphicsManager::loadTextures() {
#ifdef USE_RGB_COLOR
- if (_transactionDetails.formatChanged && _gameTexture)
+ if (_transactionDetails.formatChanged && _gameTexture) {
delete _gameTexture;
+ _gameTexture = 0;
+ }
#endif
+ uint gameScreenBPP = 0;
+
if (!_gameTexture) {
byte bpp;
GLenum intformat;
@@ -1073,6 +1135,7 @@ void OpenGLGraphicsManager::loadTextures() {
#else
getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, intformat, format, type);
#endif
+ gameScreenBPP = bpp;
_gameTexture = new GLTexture(bpp, intformat, format, type);
} else
_gameTexture->refresh();
@@ -1093,7 +1156,7 @@ void OpenGLGraphicsManager::loadTextures() {
_cursorTexture = new GLTexture(4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
else
_cursorTexture->refresh();
-
+
GLint filter = _videoMode.antialiasing ? GL_LINEAR : GL_NEAREST;
_gameTexture->setFilter(filter);
_overlayTexture->setFilter(filter);
@@ -1104,21 +1167,43 @@ void OpenGLGraphicsManager::loadTextures() {
_overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
_cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
- if (_transactionDetails.formatChanged ||
+ if (
+#ifdef USE_RGB_COLOR
+ _transactionDetails.formatChanged ||
+#endif
_oldVideoMode.screenWidth != _videoMode.screenWidth ||
_oldVideoMode.screenHeight != _videoMode.screenHeight)
_screenData.create(_videoMode.screenWidth, _videoMode.screenHeight,
- _screenFormat.bytesPerPixel);
+#ifdef USE_RGB_COLOR
+ _screenFormat.bytesPerPixel
+#else
+ 1
+#endif
+ );
+
if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth ||
_oldVideoMode.overlayHeight != _videoMode.overlayHeight)
_overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight,
_overlayFormat.bytesPerPixel);
-
+
_screenNeedsRedraw = true;
_overlayNeedsRedraw = true;
_cursorNeedsRedraw = true;
+ // We need to setup a proper unpack alignment value here, else we will
+ // get problems with the texture updates, in case the surface data is
+ // not properly aligned.
+ // For now we use the gcd of the game screen format and 2, since 2 is
+ // the BPP value for the overlay and the OSD.
+ if (gameScreenBPP)
+ glPixelStorei(GL_UNPACK_ALIGNMENT, Common::gcd<uint>(gameScreenBPP, 2));
+
+ // We use a "pack" alignment (when reading from textures) to 4 here,
+ // since the only place where we really use it is the BMP screenshot
+ // code and that requires the same alignment too.
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
#ifdef USE_OSD
if (!_osdTexture)
_osdTexture = new GLTexture(2, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
@@ -1126,6 +1211,9 @@ void OpenGLGraphicsManager::loadTextures() {
_osdTexture->refresh();
_osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
+
+ // Update the OSD in case it is used right now
+ _requireOSDUpdate = true;
#endif
}
@@ -1149,6 +1237,8 @@ void OpenGLGraphicsManager::unloadGFXMode() {
}
void OpenGLGraphicsManager::setScale(int newScale) {
+ assert(_transactionMode == kTransactionActive);
+
if (newScale == _videoMode.scaleFactor)
return;
@@ -1156,57 +1246,48 @@ void OpenGLGraphicsManager::setScale(int newScale) {
_transactionDetails.sizeChanged = true;
}
+void OpenGLGraphicsManager::toggleAntialiasing() {
+ assert(_transactionMode == kTransactionActive);
+
+ _videoMode.antialiasing = !_videoMode.antialiasing;
+ _transactionDetails.filterChanged = true;
+}
+
uint OpenGLGraphicsManager::getAspectRatio() {
- if (_videoMode.mode == OpenGL::GFX_NORMAL)
- return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight;
- else if (_videoMode.mode == OpenGL::GFX_4_3)
+ // In case we enable aspect ratio correction we force a 4/3 ratio.
+ // TODO: This makes OpenGL Normal behave like OpenGL Conserve, when aspect
+ // ratio correction is enabled, but it's better than the previous 4/3 mode
+ // mess at least...
+ if (_videoMode.aspectRatioCorrection)
return 13333;
+ else if (_videoMode.mode == OpenGL::GFX_NORMAL)
+ return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight;
else
return _videoMode.screenWidth * 10000 / _videoMode.screenHeight;
}
-void OpenGLGraphicsManager::adjustMouseEvent(const Common::Event &event) {
- if (!event.synthetic) {
- Common::Event newEvent(event);
- newEvent.synthetic = true;
-
- if (_videoMode.mode == OpenGL::GFX_NORMAL) {
- if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
- newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _videoMode.hardwareWidth;
- if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
- newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _videoMode.hardwareHeight;
-
- if (!_overlayVisible) {
- newEvent.mouse.x /= _videoMode.scaleFactor;
- newEvent.mouse.y /= _videoMode.scaleFactor;
- }
+void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
+ if (_overlayVisible)
+ return;
- } else {
- newEvent.mouse.x -= _displayX;
- newEvent.mouse.y -= _displayY;
-
- if (_overlayVisible) {
- if (_displayWidth != _videoMode.overlayWidth)
- newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _displayWidth;
- if (_displayHeight != _videoMode.overlayHeight)
- newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _displayHeight;
- } else {
- if (_displayWidth != _videoMode.screenWidth)
- newEvent.mouse.x = newEvent.mouse.x * _videoMode.screenWidth / _displayWidth;
- if (_displayHeight != _videoMode.screenHeight)
- newEvent.mouse.y = newEvent.mouse.y * _videoMode.screenHeight / _displayHeight;
- }
- }
+ if (!_overlayVisible) {
+ x -= _displayX;
+ y -= _displayY;
- g_system->getEventManager()->pushEvent(newEvent);
+ if (_displayWidth != _videoMode.screenWidth)
+ x = x * _videoMode.screenWidth / _displayWidth;
+ if (_displayHeight != _videoMode.screenHeight)
+ y = y * _videoMode.screenHeight / _displayHeight;
}
}
bool OpenGLGraphicsManager::notifyEvent(const Common::Event &event) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
- if (!event.synthetic)
- setMousePos(event.mouse.x, event.mouse.y);
+ if (!event.synthetic) {
+ _cursorState.x = event.mouse.x;
+ _cursorState.y = event.mouse.y;
+ }
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_WHEELUP:
@@ -1215,7 +1296,12 @@ bool OpenGLGraphicsManager::notifyEvent(const Common::Event &event) {
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
case Common::EVENT_MBUTTONUP:
- adjustMouseEvent(event);
+ if (!event.synthetic) {
+ Common::Event newEvent(event);
+ newEvent.synthetic = true;
+ adjustMousePosition(newEvent.mouse.x, newEvent.mouse.y);
+ g_system->getEventManager()->pushEvent(newEvent);
+ }
return !event.synthetic;
default:
@@ -1229,8 +1315,16 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
int width = _videoMode.hardwareWidth;
int height = _videoMode.hardwareHeight;
+ // A line of a BMP image must have a size divisible by 4.
+ // We calculate the padding bytes needed here.
+ // Since we use a 3 byte per pixel mode, we can use width % 4 here, since
+ // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the
+ // usual way of computing the padding bytes required).
+ const int linePaddingSize = width % 4;
+ const int lineSize = width * 3 + linePaddingSize;
+
// Allocate memory for screenshot
- uint8 *pixels = new uint8[width * height * 3];
+ uint8 *pixels = new uint8[lineSize * height];
// Get pixel data from OpenGL buffer
#ifdef USE_GLES
@@ -1250,9 +1344,9 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
// Write BMP header
out.writeByte('B');
out.writeByte('M');
- out.writeUint32LE(height * width * 3 + 52);
+ out.writeUint32LE(height * lineSize + 54);
out.writeUint32LE(0);
- out.writeUint32LE(52);
+ out.writeUint32LE(54);
out.writeUint32LE(40);
out.writeUint32LE(width);
out.writeUint32LE(height);
@@ -1266,7 +1360,7 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
out.writeUint32LE(0);
// Write pixel data to BMP
- out.write(pixels, width * height * 3);
+ out.write(pixels, lineSize * height);
// Free allocated memory
delete[] pixels;
@@ -1287,21 +1381,52 @@ const char *OpenGLGraphicsManager::getCurrentModeName() {
return modeName;
}
-void OpenGLGraphicsManager::switchDisplayMode(int mode) {
- if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
- return;
+#ifdef USE_OSD
+void OpenGLGraphicsManager::updateOSD() {
+ // The font we are going to use:
+ const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
- if (_transactionMode == kTransactionActive) {
- if (mode == -1) // If -1, switch to next mode
- _videoMode.mode = (_videoMode.mode + 1) % 4;
- else if (mode == -2) // If -2, switch to previous mode
- _videoMode.mode = (_videoMode.mode + 3) % 4;
- else
- _videoMode.mode = mode;
+ if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
+ _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2);
+ else
+ // Clear everything
+ memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
- _transactionDetails.needRefresh = true;
- _aspectRatioCorrection = false;
+ // Determine a rect which would contain the message string (clipped to the
+ // screen dimensions).
+ const int vOffset = 6;
+ const int lineSpacing = 1;
+ const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
+ int width = 0;
+ int height = lineHeight * _osdLines.size() + 2 * vOffset;
+ for (uint i = 0; i < _osdLines.size(); i++) {
+ width = MAX(width, font->getStringWidth(_osdLines[i]) + 14);
}
+
+ // Clip the rect
+ if (width > _osdSurface.w)
+ width = _osdSurface.w;
+ if (height > _osdSurface.h)
+ height = _osdSurface.h;
+
+ int dstX = (_osdSurface.w - width) / 2;
+ int dstY = (_osdSurface.h - height) / 2;
+
+ // Draw a dark gray rect
+ const uint16 color = 0x294B;
+ _osdSurface.fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color);
+
+ // Render the message, centered, and in white
+ for (uint i = 0; i < _osdLines.size(); i++) {
+ font->drawString(&_osdSurface, _osdLines[i],
+ dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
+ 0xFFFF, Graphics::kTextAlignCenter);
+ }
+
+ // Update the texture
+ _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
+ _osdSurface.w, _osdSurface.h);
}
+#endif
#endif
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 27c850f0ab..374f1c196e 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -39,8 +39,7 @@ namespace OpenGL {
enum {
GFX_NORMAL = 0,
GFX_CONSERVE = 1,
- GFX_4_3 = 2,
- GFX_ORIGINAL = 3
+ GFX_ORIGINAL = 2
};
}
@@ -152,11 +151,11 @@ protected:
bool setup;
bool fullscreen;
- int activeFullscreenMode;
int mode;
int scaleFactor;
bool antialiasing;
+ bool aspectRatioCorrection;
int screenWidth, screenHeight;
int overlayWidth, overlayHeight;
@@ -176,7 +175,41 @@ protected:
virtual bool loadGFXMode();
virtual void unloadGFXMode();
- virtual void setScale(int newScale);
+ /**
+ * Setup the fullscreen mode state.
+ */
+ void setFullscreenMode(bool enable);
+
+ /**
+ * Query the fullscreen state.
+ */
+ inline bool getFullscreenMode() const { return _videoMode.fullscreen; }
+
+ /**
+ * Set the scale factor.
+ *
+ * This can only be used in a GFX transaction.
+ *
+ * @param newScale New scale factor.
+ */
+ void setScale(int newScale);
+
+ /**
+ * Query the scale factor.
+ */
+ inline int getScale() const { return _videoMode.scaleFactor; }
+
+ /**
+ * Toggle the antialiasing state of the current video mode.
+ *
+ * This can only be used in a GFX transaction.
+ */
+ void toggleAntialiasing();
+
+ /**
+ * Query the antialiasing state.
+ */
+ inline bool getAntialiasingState() const { return _videoMode.antialiasing; }
// Drawing coordinates for the current display mode and scale
int _displayX;
@@ -184,19 +217,11 @@ protected:
int _displayWidth;
int _displayHeight;
- /**
- * Sets the dispaly mode.
- * @mode the dispaly mode, if -1 it will switch to next mode. If -2 to previous mode.
- */
- virtual void switchDisplayMode(int mode);
-
virtual const char *getCurrentModeName();
virtual void calculateDisplaySize(int &width, int &height);
virtual void refreshDisplaySize();
- bool _aspectRatioCorrection;
-
/**
* Returns the current target aspect ratio x 10000
*/
@@ -232,15 +257,14 @@ protected:
bool _overlayVisible;
bool _overlayNeedsRedraw;
Common::Rect _overlayDirtyRect;
-
+
virtual void refreshOverlay();
//
// Mouse
//
struct MousePos {
- // The mouse position, using either virtual (game) or real
- // (overlay) coordinates.
+ // The mouse position in hardware screen coordinates.
int16 x, y;
// The size and hotspot of the original cursor image.
@@ -273,8 +297,23 @@ protected:
virtual void refreshCursor();
virtual void refreshCursorScale();
- virtual void adjustMouseEvent(const Common::Event &event);
- virtual void setMousePos(int x, int y);
+
+ /**
+ * Set up the mouse position for the (event) system.
+ *
+ * @param x X coordinate in native coordinates.
+ * @param y Y coordinate in native coordinates.
+ */
+ virtual void setInternalMousePosition(int x, int y) = 0;
+
+ /**
+ * Adjusts hardware screen coordinates to either overlay or game screen
+ * coordinates depending on whether the overlay is visible or not.
+ *
+ * @param x X coordinate of the mouse position.
+ * @param y Y coordinate of the mouse position.
+ */
+ virtual void adjustMousePosition(int16 &x, int16 &y);
//
// Misc
@@ -282,6 +321,16 @@ protected:
virtual bool saveScreenshot(const char *filename);
#ifdef USE_OSD
+ /**
+ * The OSD contents.
+ */
+ Common::Array<Common::String> _osdLines;
+
+ /**
+ * Update the OSD texture / surface.
+ */
+ void updateOSD();
+
GLTexture *_osdTexture;
Graphics::Surface _osdSurface;
uint8 _osdAlpha;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index b10c94b03f..b9022af120 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -35,6 +35,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager()
:
_hwscreen(0),
_screenResized(false),
+ _activeFullscreenMode(-2),
_lastFullscreenModeWidth(0),
_lastFullscreenModeHeight(0),
_desktopWidth(0),
@@ -78,9 +79,6 @@ bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) {
void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- setFullscreenMode(enable);
- break;
case OSystem::kFeatureIconifyWindow:
if (enable)
SDL_WM_IconifyWindow();
@@ -121,6 +119,7 @@ void OpenGLSdlGraphicsManager::detectSupportedFormats() {
#endif
Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), // RGB565
Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0), // RGB5551
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), // RGB555
Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444
#ifndef USE_GLES
Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) // ARGB4444
@@ -191,40 +190,8 @@ void OpenGLSdlGraphicsManager::detectSupportedFormats() {
#endif
-void OpenGLSdlGraphicsManager::warpMouse(int x, int y) {
- int scaledX = x;
- int scaledY = y;
-
- if (_videoMode.mode == OpenGL::GFX_NORMAL) {
- if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
- scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth;
- if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
- scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight;
-
- if (!_overlayVisible) {
- scaledX *= _videoMode.scaleFactor;
- scaledY *= _videoMode.scaleFactor;
- }
- } else {
- if (_overlayVisible) {
- if (_displayWidth != _videoMode.overlayWidth)
- scaledX = scaledX * _displayWidth / _videoMode.overlayWidth;
- if (_displayHeight != _videoMode.overlayHeight)
- scaledY = scaledY * _displayHeight / _videoMode.overlayHeight;
- } else {
- if (_displayWidth != _videoMode.screenWidth)
- scaledX = scaledX * _displayWidth / _videoMode.screenWidth;
- if (_displayHeight != _videoMode.screenHeight)
- scaledY = scaledY * _displayHeight / _videoMode.screenHeight;
- }
-
- scaledX += _displayX;
- scaledY += _displayY;
- }
-
- SDL_WarpMouse(scaledX, scaledY);
-
- setMousePos(scaledX, scaledY);
+void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) {
+ SDL_WarpMouse(x, y);
}
void OpenGLSdlGraphicsManager::updateScreen() {
@@ -246,7 +213,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
if (availableModes == (void *)-1) {
_videoMode.hardwareWidth = _desktopWidth;
_videoMode.hardwareHeight = _desktopHeight;
- _videoMode.activeFullscreenMode = -2;
+ _activeFullscreenMode = -2;
return true;
}
@@ -254,7 +221,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
// The last used fullscreen mode will be prioritized, if there is no last fullscreen
// mode, the desktop resolution will be used, and in case the desktop resolution
// is not available as a fullscreen mode, the one with smallest metric will be selected.
- if (_videoMode.activeFullscreenMode == -2) {
+ if (_activeFullscreenMode == -2) {
// Desktop resolution
int desktopModeIndex = -1;
@@ -269,7 +236,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
if (mode->w == _lastFullscreenModeWidth && mode->h == _lastFullscreenModeHeight) {
_videoMode.hardwareWidth = _lastFullscreenModeWidth;
_videoMode.hardwareHeight = _lastFullscreenModeHeight;
- _videoMode.activeFullscreenMode = i;
+ _activeFullscreenMode = i;
return true;
}
@@ -293,32 +260,32 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
_videoMode.hardwareWidth = _desktopWidth;
_videoMode.hardwareHeight = _desktopHeight;
- _videoMode.activeFullscreenMode = desktopModeIndex;
+ _activeFullscreenMode = desktopModeIndex;
return true;
} else if (bestMode) {
_videoMode.hardwareWidth = bestMode->w;
_videoMode.hardwareHeight = bestMode->h;
- _videoMode.activeFullscreenMode = bestModeIndex;
+ _activeFullscreenMode = bestModeIndex;
return true;
}
} else {
// Use last fullscreen mode if looping backwards from the first mode
- if (_videoMode.activeFullscreenMode == -1) {
+ if (_activeFullscreenMode == -1) {
do {
- _videoMode.activeFullscreenMode++;
- } while(availableModes[_videoMode.activeFullscreenMode]);
- _videoMode.activeFullscreenMode--;
+ _activeFullscreenMode++;
+ } while(availableModes[_activeFullscreenMode]);
+ _activeFullscreenMode--;
}
// Use first fullscreen mode if looping from last mode
- if (!availableModes[_videoMode.activeFullscreenMode])
- _videoMode.activeFullscreenMode = 0;
+ if (!availableModes[_activeFullscreenMode])
+ _activeFullscreenMode = 0;
// Check if the fullscreen mode is valid
- if (availableModes[_videoMode.activeFullscreenMode]) {
- _videoMode.hardwareWidth = availableModes[_videoMode.activeFullscreenMode]->w;
- _videoMode.hardwareHeight = availableModes[_videoMode.activeFullscreenMode]->h;
+ if (availableModes[_activeFullscreenMode]) {
+ _videoMode.hardwareWidth = availableModes[_activeFullscreenMode]->w;
+ _videoMode.hardwareHeight = availableModes[_activeFullscreenMode]->h;
return true;
}
}
@@ -328,17 +295,11 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
}
bool OpenGLSdlGraphicsManager::loadGFXMode() {
- // Force 4/3 if feature enabled
- if (_aspectRatioCorrection)
- _videoMode.mode = OpenGL::GFX_4_3;
-
- _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
-
// If the screen was resized, do not change its size
if (!_screenResized) {
- _videoMode.hardwareWidth = _videoMode.overlayWidth;
- _videoMode.hardwareHeight = _videoMode.overlayHeight;
+ const int scaleFactor = getScale();
+ _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * scaleFactor;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * scaleFactor;
int screenAspectRatio = _videoMode.screenWidth * 10000 / _videoMode.screenHeight;
int desiredAspectRatio = getAspectRatio();
@@ -348,11 +309,6 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
_videoMode.hardwareHeight = (_videoMode.overlayWidth * 10000 + 5000) / desiredAspectRatio;
else if (screenAspectRatio < desiredAspectRatio)
_videoMode.hardwareWidth = (_videoMode.overlayHeight * desiredAspectRatio + 5000) / 10000;
-
- // Only adjust the overlay height if it is bigger than original one. If
- // the width is modified it can break the overlay.
- if (_videoMode.hardwareHeight > _videoMode.overlayHeight)
- _videoMode.overlayHeight = _videoMode.hardwareHeight;
}
_screenResized = false;
@@ -364,14 +320,24 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- if (_videoMode.fullscreen)
+ const bool isFullscreen = getFullscreenMode();
+
+ // In case we have an fullscreen mode and we are not in a rollback, detect
+ // a proper mode to use. In case we are in a rollback, we already detected
+ // a proper mode when setting up that mode, thus there is no need to run
+ // the detection again.
+ if (isFullscreen && _transactionMode != kTransactionRollback) {
if (!setupFullscreenMode())
// Failed setuping a fullscreen mode
return false;
+ }
+
+ _videoMode.overlayWidth = _videoMode.hardwareWidth;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight;
uint32 flags = SDL_OPENGL;
- if (_videoMode.fullscreen)
+ if (isFullscreen)
flags |= SDL_FULLSCREEN;
else
flags |= SDL_RESIZABLE;
@@ -397,7 +363,7 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
// Check if the screen is BGR format
_formatBGR = _hwscreen->format->Rshift != 0;
- if (_videoMode.fullscreen) {
+ if (isFullscreen) {
_lastFullscreenModeWidth = _videoMode.hardwareWidth;
_lastFullscreenModeHeight = _videoMode.hardwareHeight;
ConfMan.setInt("last_fullscreen_mode_width", _lastFullscreenModeWidth);
@@ -427,11 +393,13 @@ void OpenGLSdlGraphicsManager::internUpdateScreen() {
void OpenGLSdlGraphicsManager::displayModeChangedMsg() {
const char *newModeName = getCurrentModeName();
if (newModeName) {
+ const int scaleFactor = getScale();
+
char buffer[128];
sprintf(buffer, "Current display mode: %s\n%d x %d -> %d x %d",
newModeName,
- _videoMode.screenWidth * _videoMode.scaleFactor,
- _videoMode.screenHeight * _videoMode.scaleFactor,
+ _videoMode.screenWidth * scaleFactor,
+ _videoMode.screenHeight * scaleFactor,
_hwscreen->w, _hwscreen->h
);
displayMessageOnOSD(buffer);
@@ -439,8 +407,9 @@ void OpenGLSdlGraphicsManager::displayModeChangedMsg() {
}
void OpenGLSdlGraphicsManager::displayScaleChangedMsg() {
char buffer[128];
+ const int scaleFactor = getScale();
sprintf(buffer, "Current scale: x%d\n%d x %d -> %d x %d",
- _videoMode.scaleFactor,
+ scaleFactor,
_videoMode.screenWidth, _videoMode.screenHeight,
_videoMode.overlayWidth, _videoMode.overlayHeight
);
@@ -448,17 +417,6 @@ void OpenGLSdlGraphicsManager::displayScaleChangedMsg() {
}
#endif
-void OpenGLSdlGraphicsManager::setFullscreenMode(bool enable) {
- if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable &&
- _oldVideoMode.activeFullscreenMode == _videoMode.activeFullscreenMode)
- return;
-
- if (_transactionMode == kTransactionActive) {
- _videoMode.fullscreen = enable;
- _transactionDetails.needRefresh = true;
- }
-}
-
bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
if (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS ||
@@ -476,12 +434,14 @@ bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) {
beginGFXTransaction();
- if (_videoMode.fullscreen && loop) {
- _videoMode.activeFullscreenMode += loop;
+ const bool isFullscreen = getFullscreenMode();
+
+ if (isFullscreen && loop) {
+ _activeFullscreenMode += loop;
setFullscreenMode(true);
} else {
- _videoMode.activeFullscreenMode = -2;
- setFullscreenMode(!_videoMode.fullscreen);
+ _activeFullscreenMode = -2;
+ setFullscreenMode(!isFullscreen);
}
endGFXTransaction();
@@ -490,7 +450,7 @@ void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) {
#ifdef USE_OSD
char buffer[128];
- if (_videoMode.fullscreen)
+ if (getFullscreenMode())
sprintf(buffer, "Fullscreen mode\n%d x %d",
_hwscreen->w, _hwscreen->h
);
@@ -545,10 +505,19 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl-Alt-a switch between display modes
if (event.kbd.keycode == 'a') {
beginGFXTransaction();
- switchDisplayMode(-1);
+ setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
endGFXTransaction();
#ifdef USE_OSD
- displayModeChangedMsg();
+ char buffer[128];
+ if (getFeatureState(OSystem::kFeatureAspectRatioCorrection))
+ sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d",
+ _videoMode.screenWidth, _videoMode.screenHeight,
+ _hwscreen->w, _hwscreen->h);
+ else
+ sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d",
+ _videoMode.screenWidth, _videoMode.screenHeight,
+ _hwscreen->w, _hwscreen->h);
+ displayMessageOnOSD(buffer);
#endif
internUpdateScreen();
return true;
@@ -557,11 +526,14 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl-Alt-f toggles antialiasing
if (event.kbd.keycode == 'f') {
beginGFXTransaction();
- _videoMode.antialiasing = !_videoMode.antialiasing;
- _transactionDetails.filterChanged = true;
+ toggleAntialiasing();
endGFXTransaction();
+
#ifdef USE_OSD
- if (_videoMode.antialiasing)
+ // TODO: This makes guesses about what internal antialiasing
+ // modes we use, we might want to consider a better way of
+ // displaying information to the user.
+ if (getAntialiasingState())
displayMessageOnOSD("Active filter mode: Linear");
else
displayMessageOnOSD("Active filter mode: Nearest");
@@ -574,7 +546,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl+Alt+Plus/Minus Increase/decrease the scale factor
if ((sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS ||
sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS)) {
- int factor = _videoMode.scaleFactor;
+ int factor = getScale();
factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1;
if (0 < factor && factor < 4) {
// Check if the desktop resolution has been detected
@@ -594,17 +566,21 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
}
- const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_4);
- const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP4);
+ const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_3);
+ const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP3);
// Ctrl-Alt-<number key> will change the GFX mode
if (isNormalNumber || isKeypadNumber) {
- if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 4) {
+ if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 3) {
+#ifdef USE_OSD
int lastMode = _videoMode.mode;
+#endif
+ // We need to query the scale and set it up, because
+ // setGraphicsMode sets the default scale to 2
+ int oldScale = getScale();
beginGFXTransaction();
- _videoMode.mode = sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1);
- _transactionDetails.needRefresh = true;
- _aspectRatioCorrection = false;
+ setGraphicsMode(sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1));
+ setScale(oldScale);
endGFXTransaction();
#ifdef USE_OSD
if (lastMode != _videoMode.mode)
@@ -622,18 +598,6 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
toggleFullScreen(-1);
return true;
}
-
- // Ctrl-Shift-a switch backwards between display modes
- if (event.kbd.keycode == 'a') {
- beginGFXTransaction();
- switchDisplayMode(-2);
- endGFXTransaction();
-#ifdef USE_OSD
- displayModeChangedMsg();
-#endif
- internUpdateScreen();
- return true;
- }
}
break;
case Common::EVENT_KEYUP:
@@ -643,7 +607,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// there is no common resize event.
case OSystem_SDL::kSdlEventResize:
// Do not resize if ignoring resize events.
- if (!_ignoreResizeFrames && !_videoMode.fullscreen) {
+ if (!_ignoreResizeFrames && !getFullscreenMode()) {
bool scaleChanged = false;
beginGFXTransaction();
_videoMode.hardwareWidth = event.mouse.x;
@@ -655,10 +619,11 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
int scale = MIN(_videoMode.hardwareWidth / _videoMode.screenWidth,
- _videoMode.hardwareHeight / _videoMode.screenHeight);
- if (_videoMode.scaleFactor != scale) {
+ _videoMode.hardwareHeight / _videoMode.screenHeight);
+
+ if (getScale() != scale) {
scaleChanged = true;
- _videoMode.scaleFactor = MAX(MIN(scale, 3), 1);
+ setScale(MAX(MIN(scale, 3), 1));
}
if (_videoMode.mode == OpenGL::GFX_ORIGINAL) {
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index d39c0814de..e9e5ed882d 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -48,8 +48,6 @@ public:
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
- virtual void warpMouse(int x, int y);
-
virtual bool notifyEvent(const Common::Event &event);
virtual void updateScreen();
@@ -59,9 +57,6 @@ protected:
virtual bool loadGFXMode();
virtual void unloadGFXMode();
-
- virtual void setFullscreenMode(bool enable);
-
virtual bool isHotkey(const Common::Event &event);
#ifdef USE_RGB_COLOR
@@ -80,12 +75,16 @@ protected:
*/
virtual void toggleFullScreen(int loop);
+ int _activeFullscreenMode;
+
/**
* Setup the fullscreen mode.
* @return false if failed finding a mode, true otherwise.
*/
virtual bool setupFullscreenMode();
+ virtual void setInternalMousePosition(int x, int y);
+
int _lastFullscreenModeWidth;
int _lastFullscreenModeHeight;
int _desktopWidth;
diff --git a/backends/platform/openpandora/op-graphics.cpp b/backends/graphics/openpandora/op-graphics.cpp
index ef95f52e99..ab6974ba5f 100644
--- a/backends/platform/openpandora/op-graphics.cpp
+++ b/backends/graphics/openpandora/op-graphics.cpp
@@ -18,11 +18,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
+#include "common/scummsys.h"
+
+#if defined(OPENPANDORA)
+
+#include "backends/graphics/openpandora/op-graphics.h"
+#include "backends/events/openpandora/op-events.h"
#include "backends/platform/openpandora/op-sdl.h"
#include "common/mutex.h"
#include "common/translation.h"
@@ -31,7 +34,11 @@
#include "graphics/scaler/aspect.h"
#include "graphics/surface.h"
-bool OSystem_OP::loadGFXMode() {
+OPGraphicsManager::OPGraphicsManager(SdlEventSource *boss)
+ : SdlGraphicsManager(boss) {
+}
+
+bool OPGraphicsManager::loadGFXMode() {
/* FIXME: For now we just cheat and set the overlay to 640*480 not 800*480 and let SDL
deal with the boarders (it saves cleaning up the overlay when the game screen is
smaller than the overlay ;)
@@ -43,8 +50,7 @@ bool OSystem_OP::loadGFXMode() {
if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
_videoMode.aspectRatioCorrection = false;
- OSystem_SDL::loadGFXMode();
-
- return true;
-
+ return SdlGraphicsManager::loadGFXMode();
}
+
+#endif
diff --git a/backends/graphics/openpandora/op-graphics.h b/backends/graphics/openpandora/op-graphics.h
new file mode 100644
index 0000000000..b0d4298620
--- /dev/null
+++ b/backends/graphics/openpandora/op-graphics.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_OP_H
+#define BACKENDS_GRAPHICS_OP_H
+
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "graphics/scaler/aspect.h" // for aspect2Real
+#include "graphics/scaler/downscaler.h"
+
+enum {
+ GFX_HALF = 12
+};
+
+class OPGraphicsManager : public SdlGraphicsManager {
+public:
+ OPGraphicsManager(SdlEventSource *boss);
+
+ bool hasFeature(OSystem::Feature f);
+ void setFeatureState(OSystem::Feature f, bool enable);
+ bool getFeatureState(OSystem::Feature f);
+ int getDefaultGraphicsMode() const;
+
+ void initSize(uint w, uint h);
+ const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ bool setGraphicsMode(const char *name);
+ bool setGraphicsMode(int mode);
+ void setGraphicsModeIntern();
+ void internUpdateScreen();
+ void showOverlay();
+ void hideOverlay();
+ bool loadGFXMode();
+ void drawMouse();
+ void undrawMouse();
+ virtual void warpMouse(int x, int y);
+
+ SdlGraphicsManager::MousePos *getMouseCurState();
+ SdlGraphicsManager::VideoState *getVideoMode();
+
+ virtual void adjustMouseEvent(const Common::Event &event);
+};
+
+#endif /* BACKENDS_GRAPHICS_OP_H */
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 480cf2e795..67b979a830 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -141,7 +141,11 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource)
_currentShakePos(0), _newShakePos(0),
_paletteDirtyStart(0), _paletteDirtyEnd(0),
_screenIsLocked(false),
- _graphicsMutex(0), _transactionMode(kTransactionNone) {
+ _graphicsMutex(0),
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ _enableFocusRectDebugCode(false), _enableFocusRect(false), _focusRect(),
+#endif
+ _transactionMode(kTransactionNone) {
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
error("Could not initialize SDL: %s", SDL_GetError());
@@ -161,11 +165,9 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource)
_graphicsMutex = g_system->createMutex();
-#ifdef _WIN32_WCE
- if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) {
- SDL_VideoInit("windib", 0);
- sdlFlags ^= SDL_INIT_VIDEO;
- }
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ if (ConfMan.hasKey("use_sdl_debug_focusrect"))
+ _enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect");
#endif
SDL_ShowCursor(SDL_DISABLE);
@@ -1103,6 +1105,79 @@ void SdlGraphicsManager::internUpdateScreen() {
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
}
#endif
+
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ // We draw the focus rectangle on top of everything, to assure it's easily visible.
+ // Of course when the overlay is visible we do not show it, since it is only for game
+ // specific focus.
+ if (_enableFocusRect && !_overlayVisible) {
+ int y = _focusRect.top + _currentShakePos;
+ int h = 0;
+ int x = _focusRect.left * scale1;
+ int w = _focusRect.width() * scale1;
+
+ if (y < height) {
+ h = _focusRect.height();
+ if (h > height - y)
+ h = height - y;
+
+ y *= scale1;
+
+ if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+ y = real2Aspect(y);
+
+ if (h > 0 && w > 0) {
+ SDL_LockSurface(_hwscreen);
+
+ // Use white as color for now.
+ Uint32 rectColor = SDL_MapRGB(_hwscreen->format, 0xFF, 0xFF, 0xFF);
+
+ // First draw the top and bottom lines
+ // then draw the left and right lines
+ if (_hwscreen->format->BytesPerPixel == 2) {
+ uint16 *top = (uint16 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2);
+ uint16 *bottom = (uint16 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 2);
+ byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2);
+ byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 2);
+
+ while (w--) {
+ *top++ = rectColor;
+ *bottom++ = rectColor;
+ }
+
+ while (h--) {
+ *(uint16 *)left = rectColor;
+ *(uint16 *)right = rectColor;
+
+ left += _hwscreen->pitch;
+ right += _hwscreen->pitch;
+ }
+ } else if (_hwscreen->format->BytesPerPixel == 4) {
+ uint32 *top = (uint32 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4);
+ uint32 *bottom = (uint32 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 4);
+ byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4);
+ byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 4);
+
+ while (w--) {
+ *top++ = rectColor;
+ *bottom++ = rectColor;
+ }
+
+ while (h--) {
+ *(uint32 *)left = rectColor;
+ *(uint32 *)right = rectColor;
+
+ left += _hwscreen->pitch;
+ right += _hwscreen->pitch;
+ }
+ }
+
+ SDL_UnlockSurface(_hwscreen);
+ }
+ }
+ }
+#endif
+
// Finally, blit all our changes to the screen
SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
}
@@ -1166,25 +1241,25 @@ void SdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int
error("SDL_LockSurface failed: %s", SDL_GetError());
#ifdef USE_RGB_COLOR
- byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth * _screenFormat.bytesPerPixel + x * _screenFormat.bytesPerPixel;
- if (_videoMode.screenWidth == w && pitch == w * _screenFormat.bytesPerPixel) {
- memcpy(dst, src, h*w*_screenFormat.bytesPerPixel);
+ byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x * _screenFormat.bytesPerPixel;
+ if (_videoMode.screenWidth == w && pitch == _screen->pitch) {
+ memcpy(dst, src, h*pitch);
} else {
do {
memcpy(dst, src, w * _screenFormat.bytesPerPixel);
src += pitch;
- dst += _videoMode.screenWidth * _screenFormat.bytesPerPixel;
+ dst += _screen->pitch;
} while (--h);
}
#else
- byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
- if (_videoMode.screenWidth == pitch && pitch == w) {
+ byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x;
+ if (_screen->pitch == pitch && pitch == w) {
memcpy(dst, src, h*w);
} else {
do {
memcpy(dst, src, w);
src += pitch;
- dst += _videoMode.screenWidth;
+ dst += _screen->pitch;
} while (--h);
}
#endif
@@ -1337,11 +1412,10 @@ void SdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
const byte *b = colors;
uint i;
SDL_Color *base = _currentPalette + start;
- for (i = 0; i < num; i++) {
+ for (i = 0; i < num; i++, b += 3) {
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
- b += 4;
}
if (start < _paletteDirtyStart)
@@ -1365,10 +1439,9 @@ void SdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
const SDL_Color *base = _currentPalette + start;
for (uint i = 0; i < num; ++i) {
- colors[i * 4] = base[i].r;
- colors[i * 4 + 1] = base[i].g;
- colors[i * 4 + 2] = base[i].b;
- colors[i * 4 + 3] = 0xFF;
+ colors[i * 3] = base[i].r;
+ colors[i * 3 + 1] = base[i].g;
+ colors[i * 3 + 2] = base[i].b;
}
}
@@ -1377,11 +1450,10 @@ void SdlGraphicsManager::setCursorPalette(const byte *colors, uint start, uint n
const byte *b = colors;
uint i;
SDL_Color *base = _cursorPalette + start;
- for (i = 0; i < num; i++) {
+ for (i = 0; i < num; i++, b += 3) {
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
- b += 4;
}
_cursorPaletteDisabled = false;
@@ -1399,6 +1471,41 @@ void SdlGraphicsManager::setShakePos(int shake_pos) {
_newShakePos = shake_pos;
}
+void SdlGraphicsManager::setFocusRectangle(const Common::Rect &rect) {
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ // Only enable focus rectangle debug code, when the user wants it
+ if (!_enableFocusRectDebugCode)
+ return;
+
+ _enableFocusRect = true;
+ _focusRect = rect;
+
+ if (rect.left < 0 || rect.top < 0 || rect.right > _videoMode.screenWidth || rect.bottom > _videoMode.screenHeight)
+ warning("SdlGraphicsManager::setFocusRectangle: Got a rect which does not fit inside the screen bounds: %d,%d,%d,%d", rect.left, rect.top, rect.right, rect.bottom);
+
+ // It's gross but we actually sometimes get rects, which are not inside the screen bounds,
+ // thus we need to clip the rect here...
+ _focusRect.clip(_videoMode.screenWidth, _videoMode.screenHeight);
+
+ // We just fake this as a dirty rect for now, to easily force an screen update whenever
+ // the rect changes.
+ addDirtyRect(_focusRect.left, _focusRect.top, _focusRect.width(), _focusRect.height());
+#endif
+}
+
+void SdlGraphicsManager::clearFocusRectangle() {
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ // Only enable focus rectangle debug code, when the user wants it
+ if (!_enableFocusRectDebugCode)
+ return;
+
+ _enableFocusRect = false;
+
+ // We just fake this as a dirty rect for now, to easily force an screen update whenever
+ // the rect changes.
+ addDirtyRect(_focusRect.left, _focusRect.top, _focusRect.width(), _focusRect.height());
+#endif
+}
#pragma mark -
#pragma mark --- Overlays ---
@@ -1871,7 +1978,6 @@ void SdlGraphicsManager::drawMouse() {
SDL_Rect dst;
int scale;
- int width, height;
int hotX, hotY;
dst.x = _mouseCurState.x;
@@ -1879,16 +1985,12 @@ void SdlGraphicsManager::drawMouse() {
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
- width = _videoMode.screenWidth;
- height = _videoMode.screenHeight;
dst.w = _mouseCurState.vW;
dst.h = _mouseCurState.vH;
hotX = _mouseCurState.vHotX;
hotY = _mouseCurState.vHotY;
} else {
scale = 1;
- width = _videoMode.overlayWidth;
- height = _videoMode.overlayHeight;
dst.w = _mouseCurState.rW;
dst.h = _mouseCurState.rH;
hotX = _mouseCurState.rHotX;
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index 0daaab104c..f467c38d5f 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -35,6 +35,10 @@
#include "backends/platform/sdl/sdl-sys.h"
+#ifndef RELEASE_BUILD
+// Define this to allow for focus rectangle debugging
+#define USE_SDL_DEBUG_FOCUSRECT
+#endif
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
// Uncomment this to enable the 'on screen display' code.
@@ -114,8 +118,8 @@ public:
virtual void fillScreen(uint32 col);
virtual void updateScreen();
virtual void setShakePos(int shakeOffset);
- virtual void setFocusRectangle(const Common::Rect& rect) {}
- virtual void clearFocusRectangle() {}
+ virtual void setFocusRectangle(const Common::Rect& rect);
+ virtual void clearFocusRectangle();
virtual void showOverlay();
virtual void hideOverlay();
@@ -301,6 +305,12 @@ protected:
*/
OSystem::MutexRef _graphicsMutex;
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ bool _enableFocusRectDebugCode;
+ bool _enableFocusRect;
+ Common::Rect _focusRect;
+#endif
+
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false);
virtual void drawMouse();
diff --git a/backends/graphics/wincesdl/wincesdl-graphics.cpp b/backends/graphics/wincesdl/wincesdl-graphics.cpp
new file mode 100644
index 0000000000..37c6624560
--- /dev/null
+++ b/backends/graphics/wincesdl/wincesdl-graphics.cpp
@@ -0,0 +1,1639 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef _WIN32_WCE
+
+#include "common/system.h"
+#include "common/translation.h"
+#include "common/mutex.h"
+
+#include "graphics/scaler/downscaler.h"
+#include "graphics/scaler/aspect.h"
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/platform/wince/wince-sdl.h"
+
+#include "backends/platform/wince/resource.h"
+#include "backends/platform/wince/CEActionsPocket.h"
+#include "backends/platform/wince/CEActionsSmartphone.h"
+#include "backends/platform/wince/CEDevice.h"
+#include "backends/platform/wince/CEScaler.h"
+#include "backends/platform/wince/CEgui/ItemAction.h"
+
+WINCESdlGraphicsManager::WINCESdlGraphicsManager(SdlEventSource *sdlEventSource)
+ : SdlGraphicsManager(sdlEventSource),
+ _panelInitialized(false), _noDoubleTapRMB(false),
+ _toolbarHighDrawn(false), _newOrientation(0), _orientationLandscape(0),
+ _panelVisible(true), _saveActiveToolbar(NAME_MAIN_PANEL), _panelStateForced(false),
+ _canBeAspectScaled(false), _scalersChanged(false), _saveToolbarState(false),
+ _mouseBackupOld(NULL), _mouseBackupDim(0), _mouseBackupToolbar(NULL),
+ _usesEmulatedMouse(false), _forceHideMouse(false), _hasfocus(true),
+ _zoomUp(false), _zoomDown(false) {
+ memset(&_mouseCurState, 0, sizeof(_mouseCurState));
+ if (_isSmartphone) {
+ _mouseCurState.x = 20;
+ _mouseCurState.y = 20;
+ }
+
+ loadDeviceConfigurationElement("repeatTrigger", _keyRepeatTrigger, 200);
+ loadDeviceConfigurationElement("repeatX", _repeatX, 4);
+ loadDeviceConfigurationElement("repeatY", _repeatY, 4);
+ loadDeviceConfigurationElement("stepX1", _stepX1, 2);
+ loadDeviceConfigurationElement("stepX2", _stepX2, 10);
+ loadDeviceConfigurationElement("stepX3", _stepX3, 40);
+ loadDeviceConfigurationElement("stepY1", _stepY1, 2);
+ loadDeviceConfigurationElement("stepY2", _stepY2, 10);
+ loadDeviceConfigurationElement("stepY3", _stepY3, 20);
+ ConfMan.flushToDisk();
+
+ _isSmartphone = CEDevice::isSmartphone();
+
+ // Query SDL for screen size and init screen dependent stuff
+ OSystem_WINCE3::initScreenInfos();
+ create_toolbar();
+ _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone();
+ if (_hasSmartphoneResolution)
+ _panelVisible = false; // init correctly in smartphones
+
+ _screen = NULL;
+}
+
+// Graphics mode consts
+
+// Low end devices 240x320
+
+static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = {
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
+ {0, 0, 0}
+};
+
+// High end device 480x640
+
+static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = {
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
+ {"2x", "2x", GFX_DOUBLESIZE},
+#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :)
+ {"2xsai", "2xSAI", GFX_2XSAI},
+ {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI},
+ {"supereagle", "SuperEagle", GFX_SUPEREAGLE},
+#endif
+ {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X},
+#ifndef _MSC_VER
+ {"hq2x", "HQ2x", GFX_HQ2X},
+ {"tv2x", "TV2x", GFX_TV2X},
+#endif
+ {"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
+ {0, 0, 0}
+};
+
+const OSystem::GraphicsMode *WINCESdlGraphicsManager::getSupportedGraphicsModes() const {
+ if (CEDevice::hasWideResolution())
+ return s_supportedGraphicsModesHigh;
+ else
+ return s_supportedGraphicsModesLow;
+}
+
+bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) {
+ return (f == OSystem::kFeatureVirtualKeyboard);
+}
+
+void WINCESdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return;
+
+ case OSystem::kFeatureVirtualKeyboard:
+ if (_hasSmartphoneResolution)
+ return;
+ _toolbarHighDrawn = false;
+ if (enable) {
+ _panelStateForced = true;
+ if (!_toolbarHandler.visible()) swap_panel_visibility();
+ //_saveToolbarState = _toolbarHandler.visible();
+ _saveActiveToolbar = _toolbarHandler.activeName();
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ _toolbarHandler.setVisible(true);
+ } else if (_panelStateForced) {
+ _panelStateForced = false;
+ _toolbarHandler.setActive(_saveActiveToolbar);
+ //_toolbarHandler.setVisible(_saveToolbarState);
+ }
+ return;
+
+ case OSystem::kFeatureDisableKeyFiltering:
+ if (_hasSmartphoneResolution) {
+ GUI::Actions::Instance()->beginMapping(enable);
+ }
+ return;
+
+ default:
+ SdlGraphicsManager::setFeatureState(f, enable);
+ }
+}
+
+bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return false;
+ case OSystem::kFeatureVirtualKeyboard:
+ return (_panelStateForced);
+ default:
+ return SdlGraphicsManager::getFeatureState(f);
+ }
+}
+
+int WINCESdlGraphicsManager::getDefaultGraphicsMode() const {
+ return GFX_NORMAL;
+}
+
+void WINCESdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
+ if (_hasSmartphoneResolution && h == 240)
+ h = 200; // mainly for the launcher
+
+ if (_isSmartphone && !ConfMan.hasKey("landscape")) {
+ ConfMan.setInt("landscape", 1);
+ ConfMan.flushToDisk();
+ }
+
+ _canBeAspectScaled = false;
+ if (w == 320 && h == 200 && !_hasSmartphoneResolution) {
+ _canBeAspectScaled = true;
+ h = 240; // use the extra 40 pixels height for the toolbar
+ }
+
+ if (h == 400) // touche engine fixup
+ h += 80;
+
+ if (!_hasSmartphoneResolution) {
+ if (h == 240)
+ _toolbarHandler.setOffset(200);
+ else
+ _toolbarHandler.setOffset(400);
+ } else {
+ if (h == 240)
+ _toolbarHandler.setOffset(200);
+ else // 176x220
+ _toolbarHandler.setOffset(0);
+ }
+
+ if (w != (uint) _videoMode.screenWidth || h != (uint) _videoMode.screenHeight)
+ _scalersChanged = false;
+
+ _videoMode.overlayWidth = w;
+ _videoMode.overlayHeight = h;
+
+ SdlGraphicsManager::initSize(w, h, format);
+
+ if (_scalersChanged) {
+ unloadGFXMode();
+ loadGFXMode();
+ _scalersChanged = false;
+ }
+
+ update_game_settings();
+}
+
+void WINCESdlGraphicsManager::loadDeviceConfigurationElement(Common::String element, int &value, int defaultValue) {
+ value = ConfMan.getInt(element, ConfMan.kApplicationDomain);
+ if (!value) {
+ value = defaultValue;
+ ConfMan.setInt(element, value, ConfMan.kApplicationDomain);
+ }
+}
+
+void WINCESdlGraphicsManager::move_cursor_up() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatY)
+ y -= _stepY3;
+ else if (_keyRepeat)
+ y -= _stepY2;
+ else
+ y -= _stepY1;
+
+ if (y < 0)
+ y = 0;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::move_cursor_down() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatY)
+ y += _stepY3;
+ else if (_keyRepeat)
+ y += _stepY2;
+ else
+ y += _stepY1;
+
+ if (y > _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd)
+ y = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::move_cursor_left() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatX)
+ x -= _stepX3;
+ else if (_keyRepeat)
+ x -= _stepX2;
+ else
+ x -= _stepX1;
+
+ if (x < 0)
+ x = 0;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::move_cursor_right() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatX)
+ x += _stepX3;
+ else if (_keyRepeat)
+ x += _stepX2;
+ else
+ x += _stepX1;
+
+ if (x > _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd)
+ x = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::retrieve_mouse_location(int &x, int &y) {
+ x = _mouseCurState.x;
+ y = _mouseCurState.y;
+
+ x = x * _scaleFactorXm / _scaleFactorXd;
+ y = y * _scaleFactorYm / _scaleFactorYd;
+
+ if (_zoomDown)
+ y -= 240;
+}
+
+void WINCESdlGraphicsManager::switch_zone() {
+ int x, y;
+ int i;
+ retrieve_mouse_location(x, y);
+
+ for (i = 0; i < TOTAL_ZONES; i++)
+ if (x >= _zones[i].x && y >= _zones[i].y &&
+ x <= _zones[i].x + _zones[i].width && y <= _zones[i].y + _zones[i].height) {
+ _mouseXZone[i] = x;
+ _mouseYZone[i] = y;
+ break;
+ }
+ _currentZone = i + 1;
+ if (_currentZone >= TOTAL_ZONES)
+ _currentZone = 0;
+
+ EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]);
+}
+
+void WINCESdlGraphicsManager::add_right_click(bool pushed) {
+ int x, y;
+ retrieve_mouse_location(x, y);
+ EventsBuffer::simulateMouseRightClick(x, y, pushed);
+}
+
+void WINCESdlGraphicsManager::add_left_click(bool pushed) {
+ int x, y;
+ retrieve_mouse_location(x, y);
+ EventsBuffer::simulateMouseLeftClick(x, y, pushed);
+}
+
+bool WINCESdlGraphicsManager::update_scalers() {
+ _videoMode.aspectRatioCorrection = false;
+
+ if (CEDevice::hasPocketPCResolution()) {
+ if (_videoMode.mode != GFX_NORMAL)
+ return false;
+
+ if ((!_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth))
+ || CEDevice::hasSquareQVGAResolution()) {
+ if (OSystem_WINCE3::getScreenWidth() != 320) {
+ _scaleFactorXm = 3;
+ _scaleFactorXd = 4;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = DownscaleHorizByThreeQuarters;
+ } else {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ }
+ } else if (_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
+ if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 6;
+ _scaleFactorYd = 5;
+ _scalerProc = Normal1xAspect;
+ _videoMode.aspectRatioCorrection = true;
+ } else {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ }
+ } else if (_videoMode.screenWidth == 640 && !(OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640))) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 2;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 2;
+ _scalerProc = DownscaleAllByHalf;
+ } else if (_videoMode.screenWidth == 640 && (OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640))) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ }
+
+ return true;
+ } else if (CEDevice::hasWideResolution()) {
+#ifdef USE_ARM_SCALER_ASM
+ if (_videoMode.mode == GFX_DOUBLESIZE && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
+ if (!_panelVisible && !_overlayVisible && _canBeAspectScaled) {
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 12;
+ _scaleFactorYd = 5;
+ _scalerProc = Normal2xAspect;
+ _videoMode.aspectRatioCorrection = true;
+ } else if ((_panelVisible || _overlayVisible) && _canBeAspectScaled) {
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 2;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal2x;
+ }
+ return true;
+ }
+#endif
+ } else if (CEDevice::hasSmartphoneResolution()) {
+ if (_videoMode.mode != GFX_NORMAL)
+ return false;
+
+ if (_videoMode.screenWidth > 320)
+ error("Game resolution not supported on Smartphone");
+#ifdef ARM
+ _scaleFactorXm = 11;
+ _scaleFactorXd = 16;
+#else
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 3;
+#endif
+ _scaleFactorYm = 7;
+ _scaleFactorYd = 8;
+ _scalerProc = SmartphoneLandscape;
+ initZones();
+ return true;
+ }
+
+ return false;
+}
+
+void WINCESdlGraphicsManager::update_game_settings() {
+ Common::String gameid(ConfMan.get("gameid"));
+
+ // Finish panel initialization
+ if (!_panelInitialized && !gameid.empty()) {
+ CEGUI::Panel *panel;
+ _panelInitialized = true;
+ // Add the main panel
+ panel = new CEGUI::Panel(0, 32);
+ panel->setBackground(IMAGE_PANEL);
+
+ // Save
+ panel->add(NAME_ITEM_OPTIONS, new CEGUI::ItemAction(ITEM_OPTIONS, POCKET_ACTION_SAVE));
+ // Skip
+ panel->add(NAME_ITEM_SKIP, new CEGUI::ItemAction(ITEM_SKIP, POCKET_ACTION_SKIP));
+ // sound
+//__XXX__ panel->add(NAME_ITEM_SOUND, new CEGUI::ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &_soundMaster));
+ panel->add(NAME_ITEM_SOUND, new CEGUI::ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &OSystem_WINCE3::_soundMaster));
+
+ // bind keys
+ panel->add(NAME_ITEM_BINDKEYS, new CEGUI::ItemAction(ITEM_BINDKEYS, POCKET_ACTION_BINDKEYS));
+ // portrait/landscape - screen dependent
+ // FIXME : will still display the portrait/landscape icon when using a scaler (but will be disabled)
+ if (ConfMan.hasKey("landscape")) {
+ if (ConfMan.get("landscape")[0] > 57) {
+ _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
+ //ConfMan.removeKey("landscape", "");
+ ConfMan.setInt("landscape", _orientationLandscape);
+ } else
+ _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
+ } else {
+ _newOrientation = _orientationLandscape = 0;
+ }
+ panel->add(NAME_ITEM_ORIENTATION, new CEGUI::ItemSwitch(ITEM_VIEW_LANDSCAPE, ITEM_VIEW_PORTRAIT, &_newOrientation, 2));
+ _toolbarHandler.add(NAME_MAIN_PANEL, *panel);
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ _toolbarHandler.setVisible(true);
+
+ if (_videoMode.mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) {
+ setGraphicsMode(GFX_NORMAL);
+ hotswapGFXMode();
+ }
+
+ if (_hasSmartphoneResolution)
+ panel->setVisible(false);
+
+ _saveToolbarState = true;
+ }
+
+ if (ConfMan.hasKey("no_doubletap_rightclick"))
+ _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick");
+}
+
+void WINCESdlGraphicsManager::internUpdateScreen() {
+ SDL_Surface *srcSurf, *origSurf;
+ static bool old_overlayVisible = false;
+ int numRectsOut = 0;
+ int16 routx, routy, routw, routh, stretch, shakestretch;
+
+ assert(_hwscreen != NULL);
+
+ // bail if the application is minimized, be nice to OS
+ if (!_hasfocus) {
+ Sleep(20);
+ return;
+ }
+
+ // If the shake position changed, fill the dirty area with blackness
+ if (_currentShakePos != _newShakePos) {
+ SDL_Rect blackrect = {0, 0, _videoMode.screenWidth *_scaleFactorXm / _scaleFactorXd, _newShakePos *_scaleFactorYm / _scaleFactorYd};
+ if (_videoMode.aspectRatioCorrection)
+ blackrect.h = real2Aspect(blackrect.h - 1) + 1;
+ SDL_FillRect(_hwscreen, &blackrect, 0);
+ _currentShakePos = _newShakePos;
+ _forceFull = true;
+ }
+
+ // Make sure the mouse is drawn, if it should be drawn.
+ drawMouse();
+
+ // Check whether the palette was changed in the meantime and update the
+ // screen surface accordingly.
+ if (_paletteDirtyEnd != 0) {
+ SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart);
+ _paletteDirtyEnd = 0;
+ _forceFull = true;
+ }
+
+ if (!_overlayVisible) {
+ origSurf = _screen;
+ srcSurf = _tmpscreen;
+ } else {
+ origSurf = _overlayscreen;
+ srcSurf = _tmpscreen2;
+ }
+
+ if (old_overlayVisible != _overlayVisible) {
+ old_overlayVisible = _overlayVisible;
+ update_scalers();
+ }
+
+ // Force a full redraw if requested
+ if (_forceFull) {
+ _numDirtyRects = 1;
+
+ _dirtyRectList[0].x = 0;
+ if (!_zoomDown)
+ _dirtyRectList[0].y = 0;
+ else
+ _dirtyRectList[0].y = _videoMode.screenHeight / 2;
+ _dirtyRectList[0].w = _videoMode.screenWidth;
+ if (!_zoomUp && !_zoomDown)
+ _dirtyRectList[0].h = _videoMode.screenHeight;
+ else
+ _dirtyRectList[0].h = _videoMode.screenHeight / 2;
+
+ _toolbarHandler.forceRedraw();
+ }
+
+ // Only draw anything if necessary
+ if (_numDirtyRects > 0) {
+
+ SDL_Rect *r, *rout;
+ SDL_Rect dst;
+ uint32 srcPitch, dstPitch;
+ SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects;
+ bool toolbarVisible = _toolbarHandler.visible();
+ int toolbarOffset = _toolbarHandler.getOffset();
+
+ for (r = _dirtyRectList; r != last_rect; ++r) {
+ dst = *r;
+ dst.x++; // Shift rect by one since 2xSai needs to access the data around
+ dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
+ // NOTE: This is also known as BLACK MAGIC, copied from the sdl backend
+ if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+
+ SDL_LockSurface(srcSurf);
+ SDL_LockSurface(_hwscreen);
+
+ srcPitch = srcSurf->pitch;
+ dstPitch = _hwscreen->pitch;
+
+ for (r = _dirtyRectList, rout = _dirtyRectOut; r != last_rect; ++r) {
+
+ // always clamp to enclosing, downsampled-grid-aligned rect in the downscaled image
+ if (_scaleFactorXd != 1) {
+ stretch = r->x % _scaleFactorXd;
+ r->x -= stretch;
+ r->w += stretch;
+ r->w = (r->x + r->w + _scaleFactorXd - 1) / _scaleFactorXd * _scaleFactorXd - r->x;
+ }
+ if (_scaleFactorYd != 1) {
+ stretch = r->y % _scaleFactorYd;
+ r->y -= stretch;
+ r->h += stretch;
+ r->h = (r->y + r->h + _scaleFactorYd - 1) / _scaleFactorYd * _scaleFactorYd - r->y;
+ }
+
+ // transform
+ shakestretch = _currentShakePos * _scaleFactorYm / _scaleFactorYd;
+ routx = r->x * _scaleFactorXm / _scaleFactorXd; // locate position in scaled screen
+ routy = r->y * _scaleFactorYm / _scaleFactorYd + shakestretch; // adjust for shake offset
+ routw = r->w * _scaleFactorXm / _scaleFactorXd;
+ routh = r->h * _scaleFactorYm / _scaleFactorYd - shakestretch;
+
+ // clipping destination rectangle inside device screen (more strict, also more tricky but more stable)
+ // note that all current scalers do not make dst rect exceed left/right, unless chosen badly (FIXME)
+ if (_zoomDown) routy -= 240; // adjust for zoom position
+ if (routy + routh < 0) continue;
+ if (routy < 0) {
+ routh += routy;
+ r->y -= routy * _scaleFactorYd / _scaleFactorYm;
+ routy = 0;
+ r->h = routh * _scaleFactorYd / _scaleFactorYm;
+ }
+ if (_orientationLandscape) {
+ if (routy > OSystem_WINCE3::getScreenWidth()) continue;
+ if (routy + routh > OSystem_WINCE3::getScreenWidth()) {
+ routh = OSystem_WINCE3::getScreenWidth() - routy;
+ r->h = routh * _scaleFactorYd / _scaleFactorYm;
+ }
+ } else {
+ if (routy > OSystem_WINCE3::getScreenHeight()) continue;
+ if (routy + routh > OSystem_WINCE3::getScreenHeight()) {
+ routh = OSystem_WINCE3::getScreenHeight() - routy;
+ r->h = routh * _scaleFactorYd / _scaleFactorYm;
+ }
+ }
+
+ // check if the toolbar is overwritten
+ if (toolbarVisible && r->y + r->h >= toolbarOffset)
+ _toolbarHandler.forceRedraw();
+
+ // blit it (with added voodoo from the sdl backend, shifting the source rect again)
+ _scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
+ (byte *)_hwscreen->pixels + routx * 2 + routy * dstPitch, dstPitch,
+ r->w, r->h - _currentShakePos);
+
+ // add this rect to output
+ rout->x = routx;
+ rout->y = routy - shakestretch;
+ rout->w = routw;
+ rout->h = routh + shakestretch;
+ numRectsOut++;
+ rout++;
+
+ }
+ SDL_UnlockSurface(srcSurf);
+ SDL_UnlockSurface(_hwscreen);
+ }
+ // Add the toolbar if needed
+ SDL_Rect toolbar_rect[1];
+ if (_panelVisible && _toolbarHandler.draw(_toolbarLow, &toolbar_rect[0])) {
+ // It can be drawn, scale it
+ uint32 srcPitch, dstPitch;
+ SDL_Surface *toolbarSurface;
+ ScalerProc *toolbarScaler;
+
+ if (_videoMode.screenHeight > 240) {
+ if (!_toolbarHighDrawn) {
+ // Resize the toolbar
+ SDL_LockSurface(_toolbarLow);
+ SDL_LockSurface(_toolbarHigh);
+ Normal2x((byte *)_toolbarLow->pixels, _toolbarLow->pitch, (byte *)_toolbarHigh->pixels, _toolbarHigh->pitch, toolbar_rect[0].w, toolbar_rect[0].h);
+ SDL_UnlockSurface(_toolbarHigh);
+ SDL_UnlockSurface(_toolbarLow);
+ _toolbarHighDrawn = true;
+ }
+ toolbar_rect[0].w *= 2;
+ toolbar_rect[0].h *= 2;
+ toolbarSurface = _toolbarHigh;
+ } else
+ toolbarSurface = _toolbarLow;
+
+ drawToolbarMouse(toolbarSurface, true); // draw toolbar mouse if applicable
+
+ // Apply the appropriate scaler
+ SDL_LockSurface(toolbarSurface);
+ SDL_LockSurface(_hwscreen);
+ srcPitch = toolbarSurface->pitch;
+ dstPitch = _hwscreen->pitch;
+
+ toolbarScaler = _scalerProc;
+ if (_videoMode.scaleFactor == 2)
+ toolbarScaler = Normal2x;
+ else if (_videoMode.scaleFactor == 3)
+ toolbarScaler = Normal3x;
+ toolbarScaler((byte *)toolbarSurface->pixels, srcPitch,
+ (byte *)_hwscreen->pixels + (_toolbarHandler.getOffset() * _scaleFactorYm / _scaleFactorYd * dstPitch),
+ dstPitch, toolbar_rect[0].w, toolbar_rect[0].h);
+ SDL_UnlockSurface(toolbarSurface);
+ SDL_UnlockSurface(_hwscreen);
+
+ // And blit it
+ toolbar_rect[0].y = _toolbarHandler.getOffset();
+ toolbar_rect[0].x = toolbar_rect[0].x * _scaleFactorXm / _scaleFactorXd;
+ toolbar_rect[0].y = toolbar_rect[0].y * _scaleFactorYm / _scaleFactorYd;
+ toolbar_rect[0].w = toolbar_rect[0].w * _scaleFactorXm / _scaleFactorXd;
+ toolbar_rect[0].h = toolbar_rect[0].h * _scaleFactorYm / _scaleFactorYd;
+
+ SDL_UpdateRects(_hwscreen, 1, toolbar_rect);
+
+ drawToolbarMouse(toolbarSurface, false); // undraw toolbar mouse
+ }
+
+ // Finally, blit all our changes to the screen
+ if (numRectsOut > 0)
+ SDL_UpdateRects(_hwscreen, numRectsOut, _dirtyRectOut);
+
+ _numDirtyRects = 0;
+ _forceFull = false;
+}
+
+bool WINCESdlGraphicsManager::setGraphicsMode(int mode) {
+
+ Common::StackLock lock(_graphicsMutex);
+ int oldScaleFactorXm = _scaleFactorXm;
+ int oldScaleFactorXd = _scaleFactorXd;
+ int oldScaleFactorYm = _scaleFactorYm;
+ int oldScaleFactorYd = _scaleFactorYd;
+
+ _scaleFactorXm = -1;
+ _scaleFactorXd = -1;
+ _scaleFactorYm = -1;
+ _scaleFactorYd = -1;
+
+ if (ConfMan.hasKey("landscape"))
+ if (ConfMan.get("landscape")[0] > 57) {
+ _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
+ ConfMan.setInt("landscape", _orientationLandscape);
+ } else
+ _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
+ else
+ _newOrientation = _orientationLandscape = 0;
+
+ if (OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640) && mode)
+ _scaleFactorXm = -1;
+
+ if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape)
+ _videoMode.mode = GFX_NORMAL;
+ else
+ _videoMode.mode = mode;
+
+ if (_scaleFactorXm < 0) {
+ /* Standard scalers, from the SDL backend */
+ switch (_videoMode.mode) {
+ case GFX_NORMAL:
+ _videoMode.scaleFactor = 1;
+ _scalerProc = Normal1x;
+ break;
+ case GFX_DOUBLESIZE:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = Normal2x;
+ break;
+ case GFX_TRIPLESIZE:
+ _videoMode.scaleFactor = 3;
+ _scalerProc = Normal3x;
+ break;
+ case GFX_2XSAI:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = _2xSaI;
+ break;
+ case GFX_SUPER2XSAI:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = Super2xSaI;
+ break;
+ case GFX_SUPEREAGLE:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = SuperEagle;
+ break;
+ case GFX_ADVMAME2X:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = AdvMame2x;
+ break;
+ case GFX_ADVMAME3X:
+ _videoMode.scaleFactor = 3;
+ _scalerProc = AdvMame3x;
+ break;
+#ifdef USE_HQ_SCALERS
+ case GFX_HQ2X:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = HQ2x;
+ break;
+ case GFX_HQ3X:
+ _videoMode.scaleFactor = 3;
+ _scalerProc = HQ3x;
+ break;
+#endif
+ case GFX_TV2X:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = TV2x;
+ break;
+ case GFX_DOTMATRIX:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = DotMatrix;
+ break;
+
+ default:
+ error("unknown gfx mode %d", mode);
+ }
+ }
+
+ // Check if the scaler can be accepted, if not get back to normal scaler
+ if (_videoMode.scaleFactor && ((_videoMode.scaleFactor * _videoMode.screenWidth > OSystem_WINCE3::getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenWidth > OSystem_WINCE3::getScreenHeight())
+ || (_videoMode.scaleFactor * _videoMode.screenHeight > OSystem_WINCE3::getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenHeight > OSystem_WINCE3::getScreenHeight()))) {
+ _videoMode.scaleFactor = 1;
+ _scalerProc = Normal1x;
+ }
+
+ // Common scaler system was used
+ if (_scaleFactorXm < 0) {
+ _scaleFactorXm = _videoMode.scaleFactor;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = _videoMode.scaleFactor;
+ _scaleFactorYd = 1;
+ }
+
+ _forceFull = true;
+
+ if (oldScaleFactorXm != _scaleFactorXm ||
+ oldScaleFactorXd != _scaleFactorXd ||
+ oldScaleFactorYm != _scaleFactorYm ||
+ oldScaleFactorYd != _scaleFactorYd) {
+ _scalersChanged = true;
+ } else
+ _scalersChanged = false;
+
+
+ return true;
+
+}
+
+bool WINCESdlGraphicsManager::loadGFXMode() {
+ int displayWidth;
+ int displayHeight;
+ unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE;
+
+ _videoMode.fullscreen = true; // forced
+ _forceFull = true;
+
+ _tmpscreen = NULL;
+
+ // Recompute scalers if necessary
+ update_scalers();
+
+ // Create the surface that contains the 8 bit game data
+ _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
+ if (_screen == NULL)
+ error("_screen failed (%s)", SDL_GetError());
+
+ // Create the surface that contains the scaled graphics in 16 bit mode
+ // Always use full screen mode to have a "clean screen"
+ if (!_videoMode.aspectRatioCorrection) {
+ displayWidth = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
+ displayHeight = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
+ } else {
+ displayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ displayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+ }
+
+ switch (_orientationLandscape) {
+ case 1:
+ flags |= SDL_LANDSCVIDEO;
+ break;
+ case 2:
+ flags |= SDL_INVLNDVIDEO;
+ break;
+ default:
+ flags |= SDL_PORTRTVIDEO;
+ }
+ _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags);
+
+ if (_hwscreen == NULL) {
+ warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
+ g_system->quit();
+ }
+
+ // see what orientation sdl finally accepted
+ if (_hwscreen->flags & SDL_PORTRTVIDEO)
+ _orientationLandscape = _newOrientation = 0;
+ else if (_hwscreen->flags & SDL_LANDSCVIDEO)
+ _orientationLandscape = _newOrientation = 1;
+ else
+ _orientationLandscape = _newOrientation = 2;
+
+ // Create the surface used for the graphics in 16 bit before scaling, and also the overlay
+ // Distinguish 555 and 565 mode
+ if (_hwscreen->format->Rmask == 0x7C00)
+ InitScalers(555);
+ else
+ InitScalers(565);
+ _overlayFormat.bytesPerPixel = _hwscreen->format->BytesPerPixel;
+ _overlayFormat.rLoss = _hwscreen->format->Rloss;
+ _overlayFormat.gLoss = _hwscreen->format->Gloss;
+ _overlayFormat.bLoss = _hwscreen->format->Bloss;
+ _overlayFormat.aLoss = _hwscreen->format->Aloss;
+ _overlayFormat.rShift = _hwscreen->format->Rshift;
+ _overlayFormat.gShift = _hwscreen->format->Gshift;
+ _overlayFormat.bShift = _hwscreen->format->Bshift;
+ _overlayFormat.aShift = _hwscreen->format->Ashift;
+
+ // Need some extra bytes around when using 2xSaI
+ _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
+
+ if (_tmpscreen == NULL)
+ error("_tmpscreen creation failed (%s)", SDL_GetError());
+
+ // Overlay
+ if (CEDevice::hasDesktopResolution()) {
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0);
+ if (_overlayscreen == NULL)
+ error("_overlayscreen failed (%s)", SDL_GetError());
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0);
+ if (_tmpscreen2 == NULL)
+ error("_tmpscreen2 failed (%s)", SDL_GetError());
+ } else {
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, 0, 0, 0, 0);
+ if (_overlayscreen == NULL)
+ error("_overlayscreen failed (%s)", SDL_GetError());
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, 0, 0, 0, 0);
+ if (_tmpscreen2 == NULL)
+ error("_tmpscreen2 failed (%s)", SDL_GetError());
+ }
+
+ // Toolbar
+ _toolbarHighDrawn = false;
+ uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16)); // *not* leaking memory here
+ _toolbarLow = SDL_CreateRGBSurfaceFrom(toolbar_screen, 320, 40, 16, 320 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
+
+ if (_toolbarLow == NULL)
+ error("_toolbarLow failed (%s)", SDL_GetError());
+
+ if (_videoMode.screenHeight > 240) {
+ uint16 *toolbar_screen_high = (uint16 *)calloc(640 * 80, sizeof(uint16));
+ _toolbarHigh = SDL_CreateRGBSurfaceFrom(toolbar_screen_high, 640, 80, 16, 640 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
+
+ if (_toolbarHigh == NULL)
+ error("_toolbarHigh failed (%s)", SDL_GetError());
+ } else
+ _toolbarHigh = NULL;
+
+ // keyboard cursor control, some other better place for it?
+ _sdlEventSource->resetKeyboadEmulation(_videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd - 1, _videoMode.screenHeight * _scaleFactorXm / _scaleFactorXd - 1);
+
+ return true;
+}
+
+void WINCESdlGraphicsManager::unloadGFXMode() {
+ if (_screen) {
+ SDL_FreeSurface(_screen);
+ _screen = NULL;
+ }
+
+ if (_hwscreen) {
+ SDL_FreeSurface(_hwscreen);
+ _hwscreen = NULL;
+ }
+
+ if (_tmpscreen) {
+ SDL_FreeSurface(_tmpscreen);
+ _tmpscreen = NULL;
+ }
+}
+
+bool WINCESdlGraphicsManager::hotswapGFXMode() {
+ if (!_screen)
+ return false;
+
+ // Keep around the old _screen & _tmpscreen so we can restore the screen data
+ // after the mode switch. (also for the overlay)
+ SDL_Surface *old_screen = _screen;
+ SDL_Surface *old_tmpscreen = _tmpscreen;
+ SDL_Surface *old_overlayscreen = _overlayscreen;
+ SDL_Surface *old_tmpscreen2 = _tmpscreen2;
+
+ // Release the HW screen surface
+ SDL_FreeSurface(_hwscreen);
+
+ // Release toolbars
+ free(_toolbarLow->pixels);
+ SDL_FreeSurface(_toolbarLow);
+ if (_toolbarHigh) {
+ free(_toolbarHigh->pixels);
+ SDL_FreeSurface(_toolbarHigh);
+ }
+
+ // Setup the new GFX mode
+ if (!loadGFXMode()) {
+ unloadGFXMode();
+
+ _screen = old_screen;
+ _overlayscreen = old_overlayscreen;
+
+ return false;
+ }
+
+ // reset palette
+ SDL_SetColors(_screen, _currentPalette, 0, 256);
+
+ // Restore old screen content
+ SDL_BlitSurface(old_screen, NULL, _screen, NULL);
+ SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
+ if (_overlayVisible) {
+ SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
+ SDL_BlitSurface(old_tmpscreen2, NULL, _tmpscreen2, NULL);
+ }
+
+ // Free the old surfaces
+ SDL_FreeSurface(old_screen);
+ SDL_FreeSurface(old_tmpscreen);
+ SDL_FreeSurface(old_overlayscreen);
+ SDL_FreeSurface(old_tmpscreen2);
+
+ // Blit everything back to the screen
+ _toolbarHighDrawn = false;
+ internUpdateScreen();
+
+ // Make sure that a Common::EVENT_SCREEN_CHANGED gets sent later -> FIXME this crashes when no game has been loaded.
+// _modeChanged = true;
+
+ return true;
+}
+
+bool WINCESdlGraphicsManager::saveScreenshot(const char *filename) {
+ assert(_hwscreen != NULL);
+
+ Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+ SDL_SaveBMP(_hwscreen, filename);
+ return true;
+}
+
+void WINCESdlGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
+ assert(_transactionMode == kTransactionNone);
+
+ if (_overlayscreen == NULL)
+ return;
+
+ // Clip the coordinates
+ if (x < 0) {
+ w += x;
+ buf -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ buf -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _videoMode.overlayWidth - x) {
+ w = _videoMode.overlayWidth - x;
+ }
+
+ if (h > _videoMode.overlayHeight - y) {
+ h = _videoMode.overlayHeight - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Mark the modified region as dirty
+ addDirtyRect(x, y, w, h);
+
+ undrawMouse();
+
+ if (SDL_LockSurface(_overlayscreen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
+ do {
+ memcpy(dst, buf, w * 2);
+ dst += _overlayscreen->pitch;
+ buf += pitch;
+ } while (--h);
+
+ SDL_UnlockSurface(_overlayscreen);
+}
+
+void WINCESdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
+ assert(_transactionMode == kTransactionNone);
+ assert(src);
+
+ if (_screen == NULL)
+ return;
+
+ Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+
+ /* Clip the coordinates */
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ src -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _videoMode.screenWidth - x) {
+ w = _videoMode.screenWidth - x;
+ }
+
+ if (h > _videoMode.screenHeight - y) {
+ h = _videoMode.screenHeight - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ addDirtyRect(x, y, w, h);
+
+ undrawMouse();
+
+ // Try to lock the screen surface
+ if (SDL_LockSurface(_screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
+
+ if (_videoMode.screenWidth == pitch && pitch == w) {
+ memcpy(dst, src, h * w);
+ } else {
+ do {
+ memcpy(dst, src, w);
+ src += pitch;
+ dst += _videoMode.screenWidth;
+ } while (--h);
+ }
+
+ // Unlock the screen surface
+ SDL_UnlockSurface(_screen);
+}
+
+void WINCESdlGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
+
+ undrawMouse();
+ if (w == 0 || h == 0)
+ return;
+
+ _mouseCurState.w = w;
+ _mouseCurState.h = h;
+
+ _mouseHotspotX = hotspot_x;
+ _mouseHotspotY = hotspot_y;
+
+ _mouseKeyColor = keycolor;
+
+ free(_mouseData);
+
+ _mouseData = (byte *) malloc(w * h);
+ memcpy(_mouseData, buf, w * h);
+
+ if (w > _mouseBackupDim || h > _mouseBackupDim) {
+ // mouse has been undrawn, adjust sprite backup area
+ free(_mouseBackupOld);
+ free(_mouseBackupToolbar);
+ uint16 tmp = (w > h) ? w : h;
+ _mouseBackupOld = (byte *) malloc(tmp * tmp * 2); // can hold 8bpp (playfield) or 16bpp (overlay) data
+ _mouseBackupToolbar = (uint16 *) malloc(tmp * tmp * 2); // 16 bpp
+ _mouseBackupDim = tmp;
+ }
+}
+
+void WINCESdlGraphicsManager::adjustMouseEvent(const Common::Event &event) {
+ if (!event.synthetic) {
+ Common::Event newEvent(event);
+ newEvent.synthetic = true;
+ if (!_overlayVisible) {
+ /*
+ newEvent.mouse.x = newEvent.mouse.x * _scaleFactorXd / _scaleFactorXm;
+ newEvent.mouse.y = newEvent.mouse.y * _scaleFactorYd / _scaleFactorYm;
+ newEvent.mouse.x /= _videoMode.scaleFactor;
+ newEvent.mouse.y /= _videoMode.scaleFactor;
+ */
+ if (_videoMode.aspectRatioCorrection)
+ newEvent.mouse.y = aspect2Real(newEvent.mouse.y);
+ }
+ g_system->getEventManager()->pushEvent(newEvent);
+ }
+}
+
+void WINCESdlGraphicsManager::setMousePos(int x, int y) {
+ if (x != _mouseCurState.x || y != _mouseCurState.y) {
+ undrawMouse();
+ _mouseCurState.x = x;
+ _mouseCurState.y = y;
+ updateScreen();
+ }
+}
+
+Graphics::Surface *WINCESdlGraphicsManager::lockScreen() {
+ // Make sure mouse pointer is not painted over the playfield at the time of locking
+ undrawMouse();
+ return SdlGraphicsManager::lockScreen();
+}
+
+void WINCESdlGraphicsManager::showOverlay() {
+ assert(_transactionMode == kTransactionNone);
+
+ if (_overlayVisible)
+ return;
+
+ undrawMouse();
+ _overlayVisible = true;
+ update_scalers();
+ clearOverlay();
+}
+
+void WINCESdlGraphicsManager::hideOverlay() {
+ assert(_transactionMode == kTransactionNone);
+
+ if (!_overlayVisible)
+ return;
+
+ undrawMouse();
+ _overlayVisible = false;
+ clearOverlay();
+ _forceFull = true;
+}
+
+void WINCESdlGraphicsManager::blitCursor() {
+}
+
+void WINCESdlGraphicsManager::drawToolbarMouse(SDL_Surface *surf, bool draw) {
+
+ if (!_mouseData || !_usesEmulatedMouse)
+ return;
+
+ int x = _mouseCurState.x - _mouseHotspotX;
+ int y = _mouseCurState.y - _mouseHotspotY - _toolbarHandler.getOffset();
+ int w = _mouseCurState.w;
+ int h = _mouseCurState.h;
+ byte color;
+ const byte *src = _mouseData;
+ int width;
+
+ // clip
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ src -= y * _mouseCurState.w;
+ y = 0;
+ }
+ if (w > surf->w - x)
+ w = surf->w - x;
+ if (h > surf->h - y)
+ h = surf->h - y;
+ if (w <= 0 || h <= 0)
+ return;
+
+ if (SDL_LockSurface(surf) == -1)
+ error("SDL_LockSurface failed at internDrawToolbarMouse: %s", SDL_GetError());
+
+ uint16 *bak = _mouseBackupToolbar; // toolbar surfaces are 16bpp
+ uint16 *dst;
+ dst = (uint16 *)surf->pixels + y * surf->w + x;
+
+ if (draw) { // blit it
+ while (h > 0) {
+ width = w;
+ while (width > 0) {
+ *bak++ = *dst;
+ color = *src++;
+ if (color != _mouseKeyColor) // transparent color
+ *dst = 0xFFFF;
+ dst++;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += _mouseBackupDim - w;
+ dst += surf->w - w;
+ h--;
+ }
+ } else { // restore bg
+ for (y = 0; y < h; ++y, bak += _mouseBackupDim, dst += surf->w)
+ memcpy(dst, bak, w << 1);
+ }
+
+ SDL_UnlockSurface(surf);
+}
+
+void WINCESdlGraphicsManager::warpMouse(int x, int y) {
+ if (_mouseCurState.x != x || _mouseCurState.y != y) {
+ SDL_WarpMouse(x * _scaleFactorXm / _scaleFactorXd, y * _scaleFactorYm / _scaleFactorYd);
+
+ // SDL_WarpMouse() generates a mouse movement event, so
+ // set_mouse_pos() would be called eventually. However, the
+ // cannon script in CoMI calls this function twice each time
+ // the cannon is reloaded. Unless we update the mouse position
+ // immediately the second call is ignored, causing the cannon
+ // to change its aim.
+
+ setMousePos(x, y);
+ }
+}
+
+void WINCESdlGraphicsManager::unlockScreen() {
+ SdlGraphicsManager::unlockScreen();
+}
+
+void WINCESdlGraphicsManager::internDrawMouse() {
+ if (!_mouseNeedsRedraw || !_mouseVisible || !_mouseData)
+ return;
+
+ int x = _mouseCurState.x - _mouseHotspotX;
+ int y = _mouseCurState.y - _mouseHotspotY;
+ int w = _mouseCurState.w;
+ int h = _mouseCurState.h;
+ byte color;
+ const byte *src = _mouseData; // Image representing the mouse
+ int width;
+
+ // clip the mouse rect, and adjust the src pointer accordingly
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ src -= y * _mouseCurState.w;
+ y = 0;
+ }
+
+ if (w > _videoMode.screenWidth - x)
+ w = _videoMode.screenWidth - x;
+ if (h > _videoMode.screenHeight - y)
+ h = _videoMode.screenHeight - y;
+
+ // Quick check to see if anything has to be drawn at all
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Draw the mouse cursor; backup the covered area in "bak"
+ if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ // Mark as dirty
+ addDirtyRect(x, y, w, h);
+
+ if (!_overlayVisible) {
+ byte *bak = _mouseBackupOld; // Surface used to backup the area obscured by the mouse
+ byte *dst; // Surface we are drawing into
+
+ dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
+ while (h > 0) {
+ width = w;
+ while (width > 0) {
+ *bak++ = *dst;
+ color = *src++;
+ if (color != _mouseKeyColor) // transparent, don't draw
+ *dst = color;
+ dst++;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += _mouseBackupDim - w;
+ dst += _videoMode.screenWidth - w;
+ h--;
+ }
+
+ } else {
+ uint16 *bak = (uint16 *)_mouseBackupOld; // Surface used to backup the area obscured by the mouse
+ byte *dst; // Surface we are drawing into
+
+ dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2;
+ while (h > 0) {
+ width = w;
+ while (width > 0) {
+ *bak++ = *(uint16 *)dst;
+ color = *src++;
+ if (color != 0xFF) // 0xFF = transparent, don't draw
+ *(uint16 *)dst = SDL_MapRGB(_overlayscreen->format, _currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
+ dst += 2;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += _mouseBackupDim - w;
+ dst += _overlayscreen->pitch - w * 2;
+ h--;
+ }
+ }
+
+ SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
+
+ // Finally, set the flag to indicate the mouse has been drawn
+ _mouseNeedsRedraw = false;
+}
+
+void WINCESdlGraphicsManager::undrawMouse() {
+ assert(_transactionMode == kTransactionNone);
+
+ if (_mouseNeedsRedraw)
+ return;
+
+ int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
+ int old_mouse_y = _mouseCurState.y - _mouseHotspotY;
+ int old_mouse_w = _mouseCurState.w;
+ int old_mouse_h = _mouseCurState.h;
+
+ // clip the mouse rect, and adjust the src pointer accordingly
+ if (old_mouse_x < 0) {
+ old_mouse_w += old_mouse_x;
+ old_mouse_x = 0;
+ }
+ if (old_mouse_y < 0) {
+ old_mouse_h += old_mouse_y;
+ old_mouse_y = 0;
+ }
+
+ if (old_mouse_w > _videoMode.screenWidth - old_mouse_x)
+ old_mouse_w = _videoMode.screenWidth - old_mouse_x;
+ if (old_mouse_h > _videoMode.screenHeight - old_mouse_y)
+ old_mouse_h = _videoMode.screenHeight - old_mouse_y;
+
+ // Quick check to see if anything has to be drawn at all
+ if (old_mouse_w <= 0 || old_mouse_h <= 0)
+ return;
+
+
+ if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ int y;
+ if (!_overlayVisible) {
+ byte *dst, *bak = _mouseBackupOld;
+
+ // No need to do clipping here, since drawMouse() did that already
+ dst = (byte *)_screen->pixels + old_mouse_y * _videoMode.screenWidth + old_mouse_x;
+ for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _videoMode.screenWidth)
+ memcpy(dst, bak, old_mouse_w);
+ } else {
+ byte *dst;
+ uint16 *bak = (uint16 *)_mouseBackupOld;
+
+ // No need to do clipping here, since drawMouse() did that already
+ dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2;
+ for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _overlayscreen->pitch)
+ memcpy(dst, bak, old_mouse_w << 1);
+ }
+
+ addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
+
+ SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
+
+ _mouseNeedsRedraw = true;
+}
+
+void WINCESdlGraphicsManager::drawMouse() {
+ if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset() && !_usesEmulatedMouse) && !_forceHideMouse)
+ internDrawMouse();
+}
+
+bool WINCESdlGraphicsManager::showMouse(bool visible) {
+ if (_mouseVisible == visible)
+ return visible;
+
+ if (visible == false)
+ undrawMouse();
+
+ bool last = _mouseVisible;
+ _mouseVisible = visible;
+ _mouseNeedsRedraw = true;
+
+ return last;
+}
+
+void WINCESdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
+
+ if (_forceFull || _paletteDirtyEnd)
+ return;
+
+ SdlGraphicsManager::addDirtyRect(x, y, w, h, false);
+}
+
+void WINCESdlGraphicsManager::swap_panel_visibility() {
+ //if (!_forcePanelInvisible && !_panelStateForced) {
+ if (_zoomDown || _zoomUp)
+ return;
+
+ if (_panelVisible) {
+ if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD)
+ _panelVisible = !_panelVisible;
+ else
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ } else {
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ _panelVisible = !_panelVisible;
+ }
+ _toolbarHandler.setVisible(_panelVisible);
+ _toolbarHighDrawn = false;
+
+ if (_videoMode.screenHeight > 240)
+ addDirtyRect(0, 400, 640, 80);
+ else
+ addDirtyRect(0, 200, 320, 40);
+
+ if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
+ internUpdateScreen();
+ else {
+ update_scalers();
+ hotswapGFXMode();
+ }
+ //}
+}
+
+void WINCESdlGraphicsManager::swap_panel() {
+ _toolbarHighDrawn = false;
+ //if (!_panelStateForced) {
+ if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ else
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+
+ if (_videoMode.screenHeight > 240)
+ addDirtyRect(0, 400, 640, 80);
+ else
+ addDirtyRect(0, 200, 320, 40);
+
+ _toolbarHandler.setVisible(true);
+ if (!_panelVisible) {
+ _panelVisible = true;
+ update_scalers();
+ hotswapGFXMode();
+ }
+ //}
+}
+
+void WINCESdlGraphicsManager::swap_smartphone_keyboard() {
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ _panelVisible = !_panelVisible;
+ _toolbarHandler.setVisible(_panelVisible);
+ if (_videoMode.screenHeight > 240)
+ addDirtyRect(0, 0, 640, 80);
+ else
+ addDirtyRect(0, 0, 320, 40);
+ internUpdateScreen();
+}
+
+void WINCESdlGraphicsManager::swap_zoom_up() {
+ if (_zoomUp) {
+ // restore visibility
+ _toolbarHandler.setVisible(_saveToolbarZoom);
+ // restore scaler
+ _scaleFactorYd = 2;
+ _scalerProc = DownscaleAllByHalf;
+ _zoomUp = false;
+ _zoomDown = false;
+ } else {
+ // only active if running on a PocketPC
+ if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
+ return;
+ if (_scalerProc == DownscaleAllByHalf) {
+ _saveToolbarZoom = _toolbarHandler.visible();
+ _toolbarHandler.setVisible(false);
+ // set zoom scaler
+ _scaleFactorYd = 1;
+ _scalerProc = DownscaleHorizByHalf;
+ }
+
+ _zoomDown = false;
+ _zoomUp = true;
+ }
+ // redraw whole screen
+ addDirtyRect(0, 0, 640, 480);
+ internUpdateScreen();
+}
+
+void WINCESdlGraphicsManager::swap_zoom_down() {
+ if (_zoomDown) {
+ // restore visibility
+ _toolbarHandler.setVisible(_saveToolbarZoom);
+ // restore scaler
+ _scaleFactorYd = 2;
+ _scalerProc = DownscaleAllByHalf;
+ _zoomDown = false;
+ _zoomUp = false;
+ } else {
+ // only active if running on a PocketPC
+ if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
+ return;
+ if (_scalerProc == DownscaleAllByHalf) {
+ _saveToolbarZoom = _toolbarHandler.visible();
+ _toolbarHandler.setVisible(false);
+ // set zoom scaler
+ _scaleFactorYd = 1;
+ _scalerProc = DownscaleHorizByHalf;
+ }
+
+ _zoomUp = false;
+ _zoomDown = true;
+ }
+ // redraw whole screen
+ addDirtyRect(0, 0, 640, 480);
+ internUpdateScreen();
+}
+
+void WINCESdlGraphicsManager::swap_mouse_visibility() {
+ _forceHideMouse = !_forceHideMouse;
+ if (_forceHideMouse)
+ undrawMouse();
+}
+
+// Smartphone actions
+void WINCESdlGraphicsManager::initZones() {
+ int i;
+
+ _currentZone = 0;
+ for (i = 0; i < TOTAL_ZONES; i++) {
+ _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)) * _scaleFactorXm / _scaleFactorXd;
+ _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)) * _scaleFactorYm / _scaleFactorYd;
+ }
+}
+
+void WINCESdlGraphicsManager::smartphone_rotate_display() {
+ _orientationLandscape = _newOrientation = _orientationLandscape == 1 ? 2 : 1;
+ ConfMan.setInt("landscape", _orientationLandscape);
+ ConfMan.flushToDisk();
+ hotswapGFXMode();
+}
+
+void WINCESdlGraphicsManager::create_toolbar() {
+ CEGUI::PanelKeyboard *keyboard;
+
+ // Add the keyboard
+ keyboard = new CEGUI::PanelKeyboard(PANEL_KEYBOARD);
+ _toolbarHandler.add(NAME_PANEL_KEYBOARD, *keyboard);
+ _toolbarHandler.setVisible(false);
+}
+
+WINCESdlGraphicsManager::zoneDesc WINCESdlGraphicsManager::_zones[TOTAL_ZONES] = {
+ { 0, 0, 320, 145 },
+ { 0, 145, 150, 55 },
+ { 150, 145, 170, 55 }
+};
+
+#endif /* _WIN32_WCE */
+
diff --git a/backends/graphics/wincesdl/wincesdl-graphics.h b/backends/graphics/wincesdl/wincesdl-graphics.h
new file mode 100644
index 0000000000..c8d683b158
--- /dev/null
+++ b/backends/graphics/wincesdl/wincesdl-graphics.h
@@ -0,0 +1,206 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_WINCE_SDL_H
+#define BACKENDS_GRAPHICS_WINCE_SDL_H
+
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "backends/platform/wince/CEgui/CEGUI.h"
+
+// Internal GUI names
+#define NAME_MAIN_PANEL "MainPanel"
+#define NAME_PANEL_KEYBOARD "Keyboard"
+#define NAME_ITEM_OPTIONS "Options"
+#define NAME_ITEM_SKIP "Skip"
+#define NAME_ITEM_SOUND "Sound"
+#define NAME_ITEM_ORIENTATION "Orientation"
+#define NAME_ITEM_BINDKEYS "Bindkeys"
+
+#define TOTAL_ZONES 3
+
+extern bool _hasSmartphoneResolution;
+
+class WINCESdlGraphicsManager : public SdlGraphicsManager {
+public:
+ WINCESdlGraphicsManager(SdlEventSource *sdlEventSource);
+
+ const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL);
+
+ bool hasFeature(OSystem::Feature f);
+ void setFeatureState(OSystem::Feature f, bool enable);
+ bool getFeatureState(OSystem::Feature f);
+
+ int getDefaultGraphicsMode() const;
+ bool setGraphicsMode(int mode);
+ bool loadGFXMode();
+ void unloadGFXMode();
+ bool hotswapGFXMode();
+
+ // Overloaded from SDL backend (toolbar handling)
+ void drawMouse();
+ // Overloaded from SDL backend (new scaler handling)
+ void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false);
+ // Overloaded from SDL backend (new scaler handling)
+ void warpMouse(int x, int y);
+
+ // Update the dirty areas of the screen
+ void internUpdateScreen();
+ bool saveScreenshot(const char *filename);
+
+ // Overloaded from SDL_Common (FIXME)
+ void internDrawMouse();
+ void undrawMouse();
+ bool showMouse(bool visible);
+ void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend
+ void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
+ void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)
+ Graphics::Surface *lockScreen();
+ void unlockScreen();
+ void blitCursor();
+ void showOverlay();
+ void hideOverlay();
+ void setMousePos(int x, int y);
+
+ // GUI and action stuff
+ void swap_panel_visibility();
+ void swap_panel();
+ void swap_smartphone_keyboard();
+ void swap_zoom_up();
+ void swap_zoom_down();
+ void swap_mouse_visibility();
+
+
+//#ifdef WIN32_PLATFORM_WFSP
+ void move_cursor_up();
+ void move_cursor_down();
+ void move_cursor_left();
+ void move_cursor_right();
+
+ void retrieve_mouse_location(int &x, int &y);
+ void switch_zone();
+
+ void add_right_click(bool pushed);
+ void add_left_click(bool pushed);
+
+ void initZones();
+ void smartphone_rotate_display();
+//#endif
+
+ bool _panelInitialized; // only initialize the toolbar once
+ bool _noDoubleTapRMB; // disable double tap -> rmb click
+
+ CEGUI::ToolbarHandler _toolbarHandler;
+
+ bool _toolbarHighDrawn; // cache toolbar 640x80
+ int _newOrientation; // new orientation
+ int _orientationLandscape; // current orientation
+
+ int _scaleFactorXm; // scaler X *
+ int _scaleFactorXd; // scaler X /
+ int _scaleFactorYm; // scaler Y *
+ int _scaleFactorYd; // scaler Y /
+
+ bool _hasfocus; // scummvm has the top window
+
+ bool hasPocketPCResolution();
+ bool hasDesktopResolution();
+ bool hasSquareQVGAResolution();
+ bool hasWideResolution() const;
+
+ MousePos _mouseCurState;
+
+ bool _zoomUp; // zooming up mode
+ bool _zoomDown; // zooming down mode
+
+ bool _usesEmulatedMouse; // emulated mousemove ever been used in this session
+
+ int _mouseXZone[TOTAL_ZONES];
+ int _mouseYZone[TOTAL_ZONES];
+ int _currentZone;
+
+ // Smartphone specific variables
+ int _lastKeyPressed; // last key pressed
+ int _keyRepeat; // number of time the last key was repeated
+ int _keyRepeatTime; // elapsed time since the key was pressed
+ int _keyRepeatTrigger; // minimum time to consider the key was repeated
+
+ struct zoneDesc {
+ int x;
+ int y;
+ int width;
+ int height;
+ };
+
+ static zoneDesc _zones[TOTAL_ZONES];
+
+protected:
+ virtual void adjustMouseEvent(const Common::Event &event);
+
+private:
+ bool update_scalers();
+ void update_game_settings();
+ void drawToolbarMouse(SDL_Surface *surf, bool draw);
+
+ void create_toolbar();
+ bool _panelVisible; // panel visibility
+ bool _panelStateForced; // panel visibility forced by external call
+ String _saveActiveToolbar; // save active toolbar when forced
+
+ bool _canBeAspectScaled; // game screen size allows for aspect scaling
+
+ SDL_Rect _dirtyRectOut[NUM_DIRTY_RECT];
+ bool _scalersChanged;
+
+ bool isOzone();
+
+ bool _saveToolbarState; // save visibility when forced
+ bool _saveToolbarZoom; // save visibility when zooming
+
+ SDL_Surface *_toolbarLow; // toolbar 320x40
+ SDL_Surface *_toolbarHigh; // toolbar 640x80
+
+ // Mouse
+ int _mouseHotspotX, _mouseHotspotY;
+ byte *_mouseBackupOld;
+ uint16 *_mouseBackupToolbar;
+ uint16 _mouseBackupDim;
+
+ bool _forceHideMouse; // force invisible mouse cursor
+
+ // Smartphone specific variables
+ void loadDeviceConfigurationElement(Common::String element, int &value, int defaultValue);
+ int _repeatX; // repeat trigger for left and right cursor moves
+ int _repeatY; // repeat trigger for up and down cursor moves
+ int _stepX1; // offset for left and right cursor moves (slowest)
+ int _stepX2; // offset for left and right cursor moves (faster)
+ int _stepX3; // offset for left and right cursor moves (fastest)
+ int _stepY1; // offset for up and down cursor moves (slowest)
+ int _stepY2; // offset for up and down cursor moves (faster)
+ int _stepY3; // offset for up and down cursor moves (fastest)
+};
+
+#endif /* BACKENDS_GRAPHICS_WINCE_SDL_H */
+
diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp
index 953b088958..2257f60e27 100644
--- a/backends/midi/alsa.cpp
+++ b/backends/midi/alsa.cpp
@@ -44,7 +44,7 @@
#if SND_LIB_MAJOR >= 1 || SND_LIB_MINOR >= 6
#define snd_seq_flush_output(x) snd_seq_drain_output(x)
-#define snd_seq_set_client_group(x,name) /*nop */
+#define snd_seq_set_client_group(x,name) /*nop */
#define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0)
#else
/* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */
@@ -53,9 +53,8 @@
#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
-static int check_permission(snd_seq_port_info_t *pinfo)
-{
- if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
+static int check_permission(snd_seq_port_info_t *pinfo) {
+ if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) {
if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
return 1;
}
@@ -68,10 +67,11 @@ static int check_permission(snd_seq_port_info_t *pinfo)
#define ADDR_DELIM ".:"
-class MidiDriver_ALSA:public MidiDriver_MPU401 {
+class MidiDriver_ALSA : public MidiDriver_MPU401 {
public:
MidiDriver_ALSA(int client, int port);
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -83,11 +83,12 @@ private:
snd_seq_t *seq_handle;
int seq_client, seq_port;
int my_client, my_port;
+ // The volume controller value of the first MIDI channel
+ int8 _channel0Volume;
};
MidiDriver_ALSA::MidiDriver_ALSA(int client, int port)
- : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0)
-{
+ : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0), _channel0Volume(127) {
memset(&ev, 0, sizeof(ev));
}
@@ -114,7 +115,7 @@ int MidiDriver_ALSA::open() {
// with those capabilities.
my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM port 0", 0,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
if (my_port < 0) {
snd_seq_close(seq_handle);
@@ -208,24 +209,41 @@ void MidiDriver_ALSA::send(uint32 b) {
case 0xB0:
/* is it this simple ? Wow... */
snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]);
+
+ // We save the volume of the first MIDI channel here to utilize it in
+ // our workaround for broken USB-MIDI cables.
+ if (chanID == 0 && midiCmd[1] == 0x07)
+ _channel0Volume = midiCmd[2];
+
send_event(1);
break;
case 0xC0:
snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]);
send_event(0);
+
+ // Send a volume change command to work around a firmware bug in common
+ // USB-MIDI cables. If the first MIDI command in a USB packet is a
+ // Cx or Dx command, the second command in the packet is dropped
+ // somewhere.
+ send(0x07B0 | (_channel0Volume << 16));
break;
case 0xD0:
snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]);
send_event(1);
+
+ // Send a volume change command to work around a firmware bug in common
+ // USB-MIDI cables. If the first MIDI command in a USB packet is a
+ // Cx or Dx command, the second command in the packet is dropped
+ // somewhere.
+ send(0x07B0 | (_channel0Volume << 16));
break;
- case 0xE0:{
- // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
- // snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
- long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
- snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
- send_event(1);
- }
- break;
+ case 0xE0: {
+ // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
+ // snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
+ long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
+ snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
+ send_event(1);
+ } break;
default:
warning("Unknown MIDI Command: %08x", (int)b);
@@ -280,6 +298,9 @@ typedef Common::List<AlsaDevice> AlsaDevices;
AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client)
: _name(name), _type(mt), _client(client) {
+ // Make sure we do not get any trailing spaces to avoid problems when
+ // storing the name in the configuration file.
+ _name.trim();
}
Common::String AlsaDevice::getName() {
diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp
index 57251b45e1..ee3baaadd2 100644
--- a/backends/midi/camd.cpp
+++ b/backends/midi/camd.cpp
@@ -46,6 +46,7 @@ class MidiDriver_CAMD : public MidiDriver_MPU401 {
public:
MidiDriver_CAMD();
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp
index 75c512cad7..0158cc4a1d 100644
--- a/backends/midi/coreaudio.cpp
+++ b/backends/midi/coreaudio.cpp
@@ -72,7 +72,9 @@ do { \
class MidiDriver_CORE : public MidiDriver_MPU401 {
public:
MidiDriver_CORE();
+ ~MidiDriver_CORE();
int open();
+ bool isOpen() const { return _auGraph != 0; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -86,10 +88,18 @@ MidiDriver_CORE::MidiDriver_CORE()
: _auGraph(0) {
}
+MidiDriver_CORE::~MidiDriver_CORE() {
+ if (_auGraph) {
+ AUGraphStop(_auGraph);
+ DisposeAUGraph(_auGraph);
+ _auGraph = 0;
+ }
+}
+
int MidiDriver_CORE::open() {
OSStatus err = 0;
- if (_auGraph)
+ if (isOpen())
return MERR_ALREADY_OPEN;
// Open the Music Device.
@@ -176,7 +186,6 @@ bail:
void MidiDriver_CORE::close() {
MidiDriver_MPU401::close();
-
if (_auGraph) {
AUGraphStop(_auGraph);
DisposeAUGraph(_auGraph);
@@ -185,7 +194,7 @@ void MidiDriver_CORE::close() {
}
void MidiDriver_CORE::send(uint32 b) {
- assert(_auGraph != NULL);
+ assert(isOpen());
byte status_byte = (b & 0x000000FF);
byte first_byte = (b & 0x0000FF00) >> 8;
@@ -198,7 +207,7 @@ void MidiDriver_CORE::sysEx(const byte *msg, uint16 length) {
unsigned char buf[266];
assert(length + 2 <= ARRAYSIZE(buf));
- assert(_auGraph != NULL);
+ assert(isOpen());
// Add SysEx frame
buf[0] = 0xF0;
diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp
index c0663352cb..9123c9bc8c 100644
--- a/backends/midi/coremidi.cpp
+++ b/backends/midi/coremidi.cpp
@@ -56,6 +56,7 @@ public:
MidiDriver_CoreMIDI();
~MidiDriver_CoreMIDI();
int open();
+ bool isOpen() const { return mOutPort != 0 && mDest != 0; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -80,7 +81,7 @@ MidiDriver_CoreMIDI::~MidiDriver_CoreMIDI() {
}
int MidiDriver_CoreMIDI::open() {
- if (mDest)
+ if (isOpen())
return MERR_ALREADY_OPEN;
OSStatus err = noErr;
@@ -106,7 +107,7 @@ int MidiDriver_CoreMIDI::open() {
void MidiDriver_CoreMIDI::close() {
MidiDriver_MPU401::close();
- if (mOutPort && mDest) {
+ if (isOpen()) {
MIDIPortDispose(mOutPort);
mOutPort = 0;
mDest = 0;
@@ -114,8 +115,7 @@ void MidiDriver_CoreMIDI::close() {
}
void MidiDriver_CoreMIDI::send(uint32 b) {
- assert(mOutPort != 0);
- assert(mDest != 0);
+ assert(isOpen());
// Extract the MIDI data
byte status_byte = (b & 0x000000FF);
@@ -158,8 +158,7 @@ void MidiDriver_CoreMIDI::send(uint32 b) {
}
void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) {
- assert(mOutPort != 0);
- assert(mDest != 0);
+ assert(isOpen());
byte buf[384];
MIDIPacketList *packetList = (MIDIPacketList *)buf;
diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp
index f0ab84c934..c4c1968354 100644
--- a/backends/midi/dmedia.cpp
+++ b/backends/midi/dmedia.cpp
@@ -57,6 +57,7 @@ class MidiDriver_DMEDIA : public MidiDriver_MPU401 {
public:
MidiDriver_DMEDIA();
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -179,7 +180,7 @@ void MidiDriver_DMEDIA::sysEx (const byte *msg, uint16 length) {
memcpy(buf, msg, length);
buf[length] = MD_EOX;
event.sysexmsg = buf;
- event.msglen = length;
+ event.msglen = length;
event.msg[0] = MD_SYSEX;
event.msg[1] = 0;
event.msg[2] = 0;
diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 064129b74a..7cd7f0a38e 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -55,6 +55,7 @@ class MidiDriver_SEQ : public MidiDriver_MPU401 {
public:
MidiDriver_SEQ();
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp
index 562c3c7ece..42f829a7a3 100644
--- a/backends/midi/stmidi.cpp
+++ b/backends/midi/stmidi.cpp
@@ -48,8 +48,9 @@
class MidiDriver_STMIDI : public MidiDriver_MPU401 {
public:
- MidiDriver_STMIDI() : _isOpen (false) { }
+ MidiDriver_STMIDI() : _isOpen (false) { }
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -59,7 +60,7 @@ private:
};
int MidiDriver_STMIDI::open() {
- if ((_isOpen) && (!Bcostat(4)))
+ if (_isOpen && (!Bcostat(4)))
return MERR_ALREADY_OPEN;
warning("ST Midi Port Open");
_isOpen = true;
@@ -123,36 +124,36 @@ void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
class StMidiMusicPlugin : public MusicPluginObject {
public:
- const char *getName() const {
- return "STMIDI";
- }
+ const char *getName() const {
+ return "STMIDI";
+ }
- const char *getId() const {
- return "stmidi";
- }
+ const char *getId() const {
+ return "stmidi";
+ }
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices StMidiMusicPlugin::getDevices() const {
- MusicDevices devices;
- // TODO: Return a different music type depending on the configuration
- // TODO: List the available devices
- devices.push_back(MusicDevice(this, "", MT_GM));
- return devices;
+ MusicDevices devices;
+ // TODO: Return a different music type depending on the configuration
+ // TODO: List the available devices
+ devices.push_back(MusicDevice(this, "", MT_GM));
+ return devices;
}
Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_STMIDI();
+ *mididriver = new MidiDriver_STMIDI();
- return Common::kNoError;
+ return Common::kNoError;
}
//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
- //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+ //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#else
- REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+ REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#endif
#endif
diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp
index eeaf872747..c01b9bbef7 100644
--- a/backends/midi/timidity.cpp
+++ b/backends/midi/timidity.cpp
@@ -92,49 +92,50 @@ class MidiDriver_TIMIDITY : public MidiDriver_MPU401 {
public:
MidiDriver_TIMIDITY();
- int open();
- void close();
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
+ int open();
+ bool isOpen() const { return _isOpen; }
+ void close();
+ void send(uint32 b);
+ void sysEx(const byte *msg, uint16 length);
private:
/* standart routine to extract ip address from a string */
- in_addr_t host_to_addr(const char* address);
+ in_addr_t host_to_addr(const char* address);
/* creates a tcp connection to TiMidity server, returns filedesc (like open()) */
- int connect_to_server(const char* hostname, unsigned short tcp_port);
+ int connect_to_server(const char* hostname, unsigned short tcp_port);
/* send command to the server; printf-like; returns reply string */
- char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3);
+ char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3);
/* timidity data socket-related stuff */
- void timidity_meta_seq(int p1, int p2, int p3);
- int timidity_sync(int centsec);
- int timidity_eot();
+ void timidity_meta_seq(int p1, int p2, int p3);
+ int timidity_sync(int centsec);
+ int timidity_eot();
/* write() analogue for any midi data */
- void timidity_write_data(const void *buf, size_t nbytes);
+ void timidity_write_data(const void *buf, size_t nbytes);
/* get single line of server reply on control connection */
- int fdgets(char *buff, size_t buff_size);
+ int fdgets(char *buff, size_t buff_size);
/* teardown connection to server */
- void teardown();
+ void teardown();
/* close (if needed) and nullify both control and data filedescs */
- void close_all();
+ void close_all();
private:
- bool _isOpen;
- int _device_num;
+ bool _isOpen;
+ int _device_num;
- int _control_fd;
- int _data_fd;
+ int _control_fd;
+ int _data_fd;
/* buffer for partial data read from _control_fd - from timidity-io.c, see fdgets() */
- char _controlbuffer[BUFSIZ];
- int _controlbuffer_count; /* beginning of read pointer */
- int _controlbuffer_size; /* end of read pointer */
+ char _controlbuffer[BUFSIZ];
+ int _controlbuffer_count; /* beginning of read pointer */
+ int _controlbuffer_size; /* end of read pointer */
};
MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
@@ -149,9 +150,9 @@ MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
}
int MidiDriver_TIMIDITY::open() {
- char *res;
- char timidity_host[MAXHOSTNAMELEN];
- int timidity_port, data_port, i;
+ char *res;
+ char timidity_host[MAXHOSTNAMELEN];
+ int timidity_port, data_port, i;
/* count ourselves open */
if (_isOpen)
@@ -427,10 +428,9 @@ void MidiDriver_TIMIDITY::timidity_write_data(const void *buf, size_t nbytes) {
}
int MidiDriver_TIMIDITY::fdgets(char *buff, size_t buff_size) {
- int n, len, count, size;
+ int n, count, size;
char *buff_endp = buff + buff_size - 1, *pbuff, *beg;
- len = 0;
count = _controlbuffer_count;
size = _controlbuffer_size;
pbuff = _controlbuffer;
diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp
index b585b71fbe..aad7f48d94 100644
--- a/backends/midi/windows.cpp
+++ b/backends/midi/windows.cpp
@@ -61,6 +61,7 @@ private:
public:
MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { }
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -93,6 +94,8 @@ void MidiDriver_WIN::close() {
}
void MidiDriver_WIN::send(uint32 b) {
+ assert(_isOpen);
+
union {
DWORD dwData;
BYTE bData[4];
diff --git a/backends/mixer/wincesdl/wincesdl-mixer.cpp b/backends/mixer/wincesdl/wincesdl-mixer.cpp
new file mode 100644
index 0000000000..fb8a7d10c7
--- /dev/null
+++ b/backends/mixer/wincesdl/wincesdl-mixer.cpp
@@ -0,0 +1,183 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifdef _WIN32_WCE
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "common/config-manager.h"
+#include "backends/platform/wince/wince-sdl.h"
+#include "backends/mixer/wincesdl/wincesdl-mixer.h"
+#include "common/system.h"
+
+#ifdef USE_VORBIS
+#ifndef USE_TREMOR
+#include <vorbis/vorbisfile.h>
+#else
+#include <tremor/ivorbisfile.h>
+#endif
+#endif
+
+#define SAMPLES_PER_SEC_OLD 11025
+#define SAMPLES_PER_SEC_NEW 22050
+
+WINCESdlMixerManager::WINCESdlMixerManager() {
+
+}
+
+WINCESdlMixerManager::~WINCESdlMixerManager() {
+
+}
+
+void WINCESdlMixerManager::init() {
+ SDL_AudioSpec desired;
+ int thread_priority;
+
+ uint32 sampleRate = compute_sample_rate();
+ if (sampleRate == 0)
+ warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work");
+ else if (_mixer && _mixer->getOutputRate() == sampleRate) {
+ debug(1, "Skipping sound mixer re-init: samplerate is good");
+ return;
+ }
+
+ memset(&desired, 0, sizeof(desired));
+ desired.freq = sampleRate;
+ desired.format = AUDIO_S16SYS;
+ desired.channels = 2;
+ desired.samples = 128;
+ desired.callback = private_sound_proc;
+ desired.userdata = this;
+
+ // Create the mixer instance
+ if (_mixer == 0)
+ _mixer = new Audio::MixerImpl(g_system, sampleRate);
+
+ // Add sound thread priority
+ if (!ConfMan.hasKey("sound_thread_priority"))
+ thread_priority = THREAD_PRIORITY_NORMAL;
+ else
+ thread_priority = ConfMan.getInt("sound_thread_priority");
+
+ desired.thread_priority = thread_priority;
+
+ SDL_CloseAudio();
+ if (SDL_OpenAudio(&desired, NULL) != 0) {
+ warning("Could not open audio device: %s", SDL_GetError());
+ _mixer->setReady(false);
+
+ } else {
+ debug(1, "Sound opened OK, mixing at %d Hz", sampleRate);
+
+ // Re-create mixer to match the output rate
+ int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
+ int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
+ int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
+ int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
+ delete _mixer;
+ _mixer = new Audio::MixerImpl(g_system, sampleRate);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4);
+ _mixer->setReady(true);
+ SDL_PauseAudio(0);
+ }
+}
+
+void WINCESdlMixerManager::private_sound_proc(void *param, byte *buf, int len) {
+ WINCESdlMixerManager *this_ = (WINCESdlMixerManager *)param;
+ assert(this_);
+
+ if (this_->_mixer)
+ this_->_mixer->mixCallback(buf, len);
+ if (!OSystem_WINCE3::_soundMaster)
+ memset(buf, 0, len);
+}
+
+uint32 WINCESdlMixerManager::compute_sample_rate() {
+ uint32 sampleRate;
+
+ // Force at least medium quality FM synthesis for FOTAQ
+ Common::String gameid(ConfMan.get("gameid"));
+ if (gameid == "queen") {
+ if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) ||
+ (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) {
+ ConfMan.setBool("FM_medium_quality", true);
+ ConfMan.flushToDisk();
+ }
+ }
+ // See if the output frequency is forced by the game
+ if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi")
+ sampleRate = SAMPLES_PER_SEC_NEW;
+ else {
+ if (ConfMan.hasKey("high_sample_rate") && ConfMan.getBool("high_sample_rate"))
+ sampleRate = SAMPLES_PER_SEC_NEW;
+ else
+ sampleRate = SAMPLES_PER_SEC_OLD;
+ }
+
+#ifdef USE_VORBIS
+ // Modify the sample rate on the fly if OGG is involved
+ if (sampleRate == SAMPLES_PER_SEC_OLD)
+ if (checkOggHighSampleRate())
+ sampleRate = SAMPLES_PER_SEC_NEW;
+#endif
+
+ return sampleRate;
+}
+
+#ifdef USE_VORBIS
+bool WINCESdlMixerManager::checkOggHighSampleRate() {
+ char trackFile[255];
+ FILE *testFile;
+ OggVorbis_File *test_ov_file = new OggVorbis_File;
+
+ // FIXME: The following sprintf assumes that "path" is always
+ // terminated by a path separator. This is *not* true in general.
+ // This code really should check for the path separator, or even
+ // better, use the FSNode API.
+ sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str());
+ // Check if we have an OGG audio track
+ testFile = fopen(trackFile, "rb");
+ if (testFile) {
+ if (!ov_open(testFile, test_ov_file, NULL, 0)) {
+ bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050);
+ ov_clear(test_ov_file);
+ delete test_ov_file;
+ return highSampleRate;
+ }
+ }
+
+ // Do not test for OGG samples - too big and too slow anyway :)
+
+ delete test_ov_file;
+ return false;
+}
+#endif
+
+#endif
+
diff --git a/backends/mixer/wincesdl/wincesdl-mixer.h b/backends/mixer/wincesdl/wincesdl-mixer.h
new file mode 100644
index 0000000000..6c2f1efeee
--- /dev/null
+++ b/backends/mixer/wincesdl/wincesdl-mixer.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_MIXER_WINCE_SDL_H
+#define BACKENDS_MIXER_WINCE_SDL_H
+
+#include "backends/mixer/sdl/sdl-mixer.h"
+
+/**
+ * SDL mixer manager for WinCE
+ */
+class WINCESdlMixerManager : public SdlMixerManager {
+public:
+ WINCESdlMixerManager();
+ virtual ~WINCESdlMixerManager();
+
+ virtual void init();
+
+private:
+
+#ifdef USE_VORBIS
+ bool checkOggHighSampleRate();
+#endif
+
+ static void private_sound_proc(void *param, byte *buf, int len);
+ uint32 compute_sample_rate();
+
+};
+
+#endif
+
diff --git a/backends/module.mk b/backends/module.mk
index 5a8a63c2a2..426409ab73 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -8,10 +8,14 @@ MODULE_OBJS := \
events/default/default-events.o \
events/dinguxsdl/dinguxsdl-events.o \
events/gp2xsdl/gp2xsdl-events.o \
+ events/gph/gph-events.o \
events/linuxmotosdl/linuxmotosdl-events.o \
+ events/openpandora/op-events.o \
events/samsungtvsdl/samsungtvsdl-events.o \
events/sdl/sdl-events.o \
events/symbiansdl/symbiansdl-events.o \
+ events/webossdl/webossdl-events.o \
+ events/wincesdl/wincesdl-events.o \
fs/abstract-fs.o \
fs/stdiostream.o \
fs/amigaos4/amigaos4-fs-factory.o \
@@ -20,13 +24,16 @@ MODULE_OBJS := \
fs/windows/windows-fs-factory.o \
graphics/dinguxsdl/dinguxsdl-graphics.o \
graphics/gp2xsdl/gp2xsdl-graphics.o \
+ graphics/gph/gph-graphics.o \
graphics/linuxmotosdl/linuxmotosdl-graphics.o \
graphics/opengl/glerrorcheck.o \
graphics/opengl/gltexture.o \
graphics/opengl/opengl-graphics.o \
graphics/openglsdl/openglsdl-graphics.o \
+ graphics/openpandora/op-graphics.o \
graphics/sdl/sdl-graphics.o \
graphics/symbiansdl/symbiansdl-graphics.o \
+ graphics/wincesdl/wincesdl-graphics.o \
keymapper/action.o \
keymapper/keymap.o \
keymapper/keymapper.o \
@@ -44,6 +51,7 @@ MODULE_OBJS := \
mixer/doublebuffersdl/doublebuffersdl-mixer.o \
mixer/sdl/sdl-mixer.o \
mixer/symbiansdl/symbiansdl-mixer.o \
+ mixer/wincesdl/wincesdl-mixer.o \
mutex/sdl/sdl-mutex.o \
plugins/elf/elf-loader.o \
plugins/elf/mips-loader.o \
diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build
deleted file mode 100644
index a4253112da..0000000000
--- a/backends/platform/android/README.build
+++ /dev/null
@@ -1,90 +0,0 @@
-Building the ScummVM Android port
-=================================
-
-You will need these things to build:
-1. Android SDK
-2. An arm-oe-linux-androideabi GCC toolchain(*)
-
-In the example commands, we are going to build against the Android 1.5
-native ABI (but using the Android 1.6 SDK tools). Other version
-combinations might/should be possible with a bit of tweaking.
-
-(*) Any other sane Android toolchain should be easy to use, but this
-is the toolchain prefix that is used by default. You can trivially
-find and modify the single location where it appears in ./configure if
-you have some other prefix variation.
-
-
-In detail:
-
-1. Android SDK
-
-Download the SDK from http://developer.android.com/ and install
-somewhere. You will need both the API level 8 (aka Android 2.2) and
-API level 3 (aka Android 1.5) platforms.
-
-2. arm-*-linux-androideabi GCC toolchain
-
-You have several choices for toolchains:
-
- - Use Google arm-eabi prebuilt toolchain.
-
-This is shipped with both the Android source release and Android NDK.
-The problem is that "arm-eabi-gcc" can't actually link anything
-successfully without extra command line flags. To use this with the
-ScummVM configure/build environment you will need to create a family
-of shell wrapper scripts that convert "arm-oe-linux-androideabi-foo" to
-"arm-eabi-foo -mandroid".
-
-For example, I use this script:
- #!/bin/sh
- exec arm-eabi-${0##*-} -mandroid -DANDROID "$@"
-
-... and create a family of symlinks/hardlinks pointing to it called
-arm-oe-android-linuxeabi-gcc, arm-oe-android-linuxeabi-g++, etc. For
-tools that don't take a "-mandroid" argument - like arm-eabi-strip - I
-bypass the shell wrapper and just create an arm-oe-android-linuxeabi-strip
-symlink to the tool directly.
-
-In practice you will probably need significant linker command line
-massaging in order to get the crtbegin/end and libraries all linked in
-the right way. It's not hard to do manually, but it is annoying to
-script in a general purpose way.
-
- - Build your own arm-*-linux-androideabi toolchain from GCC source.
-
-This is lots of fun, but will become significantly easier once gcc-4.6
-is released. In the interim, I suggest using my precompiled Android
-openembedded-based toolchain:
- wget http://commondatastorage.googleapis.com/anr/sdk/android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2
- sudo tar jxf android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2 -C /
- . /usr/local/android/arm/environment-setup
-
-Alternatively, do a websearch - there are several other cross-compile
-toolchains around.
-
-
-Building ScummVM
-================
-
-(Optionally) compress scummmodern.zip:
-(ScummVM usually ships it uncompressed, but Android can read it more
-efficiently if it is compressed *before* adding it to the apk)
-
- ( cd gui/themes/scummmodern && zip -f ../scummmodern.zip )
-
-Then build ScummVM:
-
- export ANDROID_SDK=<root of Android SDK>
-
- PATH=$ANDROID_SDK/platforms/android-1.6/tools:$ANDROID_SDK/tools:$PATH
- # You also want to ensure your arm-oe-linux-androideabi toolchain is in $PATH
-
- ./configure --backend=android --host=android --enable-zlib --disable-timidity
- # ... and any other configure flags you want
- make scummvm.apk
-
-This will build a "monolithic" ScummVM package, with the engines
-statically linked in. If you want to build separate engine packages,
-like on the market, add "--enable-plugins --default-dynamic" to
-configure and also make scummvm-engine-scumm.apk, etc.
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index efcee488a5..bbfdb06b8d 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -23,27 +23,14 @@
*
*/
-#include "backends/base-backend.h"
-#include "base/main.h"
-#include "graphics/surface.h"
+#if defined(__ANDROID__)
-#include "backends/platform/android/video.h"
-
-#if defined(ANDROID_BACKEND)
-
-#include <jni.h>
-
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/system_properties.h>
#include <time.h>
+#include <unistd.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <android/log.h>
-
-#include "common/archive.h"
#include "common/util.h"
#include "common/rect.h"
#include "common/queue.h"
@@ -51,1087 +38,397 @@
#include "common/events.h"
#include "common/config-manager.h"
-#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/keymapper/keymapper.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
-#include "backends/plugins/posix/posix-provider.h"
-#include "audio/mixer_intern.h"
-
-#include "backends/platform/android/asset-archive.h"
-
-#undef LOG_TAG
-#define LOG_TAG "ScummVM"
-#if 0
-#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args)
-#else
-#define ENTER(args...) /**/
-#endif
+#include "backends/platform/android/jni.h"
+#include "backends/platform/android/android.h"
-// Fix JNIEXPORT declaration to actually do something useful
-#undef JNIEXPORT
-#define JNIEXPORT __attribute__ ((visibility("default")))
+const char *android_log_tag = "ScummVM";
-// This replaces the bionic libc assert message with something that
+// This replaces the bionic libc assert functions with something that
// actually prints the assertion failure before aborting.
-extern "C"
-void __assert(const char *file, int line, const char *expr) {
- __android_log_assert(expr, LOG_TAG, "%s:%d: Assertion failure: %s",
- file, line, expr);
-}
-
-static JavaVM *cached_jvm;
-static jfieldID FID_Event_type;
-static jfieldID FID_Event_synthetic;
-static jfieldID FID_Event_kbd_keycode;
-static jfieldID FID_Event_kbd_ascii;
-static jfieldID FID_Event_kbd_flags;
-static jfieldID FID_Event_mouse_x;
-static jfieldID FID_Event_mouse_y;
-static jfieldID FID_Event_mouse_relative;
-static jfieldID FID_ScummVM_nativeScummVM;
-static jmethodID MID_Object_wait;
-
-JNIEnv* JNU_GetEnv() {
- JNIEnv* env;
- bool version_unsupported =
- cached_jvm->GetEnv((void**)&env, JNI_VERSION_1_2);
- assert(! version_unsupported);
- return env;
-}
-
-static void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
- jclass cls = env->FindClass(name);
- // if cls is NULL, an exception has already been thrown
- if (cls != NULL)
- env->ThrowNew(cls, msg);
- env->DeleteLocalRef(cls);
-}
-
-// floating point. use sparingly.
-template <class T>
-static inline T scalef(T in, float numerator, float denominator) {
- return static_cast<float>(in) * numerator / denominator;
-}
+extern "C" {
+ void __assert(const char *file, int line, const char *expr) {
+ __android_log_assert(expr, android_log_tag,
+ "Assertion failure: '%s' in %s:%d",
+ expr, file, line);
+ }
-static inline GLfixed xdiv(int numerator, int denominator) {
- assert(numerator < (1<<16));
- return (numerator << 16) / denominator;
+ void __assert2(const char *file, int line, const char *func,
+ const char *expr) {
+ __android_log_assert(expr, android_log_tag,
+ "Assertion failure: '%s' in %s:%d (%s)",
+ expr, file, line, func);
+ }
}
-#ifdef DYNAMIC_MODULES
-class AndroidPluginProvider : public POSIXPluginProvider {
-protected:
- virtual void addCustomDirectories(Common::FSList &dirs) const;
-};
-#endif
-
-
-#if 0
-#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
-static const char* getGlErrStr(GLenum error) {
+#ifdef ANDROID_DEBUG_GL
+static const char *getGlErrStr(GLenum error) {
switch (error) {
- case GL_NO_ERROR: return "GL_NO_ERROR";
- case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
- case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
- case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
- case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
- case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
+ case GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
}
static char buf[40];
snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
+
return buf;
}
-static void checkGlError(const char* file, int line) {
+
+void checkGlError(const char *expr, const char *file, int line) {
GLenum error = glGetError();
+
if (error != GL_NO_ERROR)
- warning("%s:%d: GL error: %s", file, line, getGlErrStr(error));
+ LOGE("GL ERROR: %s on %s (%s:%d)", getGlErrStr(error), expr, file, line);
}
-#else
-#define CHECK_GL_ERROR() do {} while (false)
#endif
-class OSystem_Android : public BaseBackend, public PaletteManager {
-private:
- jobject _back_ptr; // back pointer to (java) peer instance
- jmethodID MID_displayMessageOnOSD;
- jmethodID MID_setWindowCaption;
- jmethodID MID_initBackend;
- jmethodID MID_audioSampleRate;
- jmethodID MID_showVirtualKeyboard;
- jmethodID MID_getSysArchives;
- jmethodID MID_getPluginDirectories;
- jmethodID MID_setupScummVMSurface;
- jmethodID MID_destroyScummVMSurface;
- jmethodID MID_swapBuffers;
-
- int _screen_changeid;
- int _egl_surface_width;
- int _egl_surface_height;
-
- bool _force_redraw;
-
- // Game layer
- GLESPaletteTexture* _game_texture;
- int _shake_offset;
- Common::Rect _focus_rect;
-
- // Overlay layer
- GLES4444Texture* _overlay_texture;
- bool _show_overlay;
-
- // Mouse layer
- GLESPaletteATexture* _mouse_texture;
- Common::Point _mouse_hotspot;
- int _mouse_targetscale;
- bool _show_mouse;
- bool _use_mouse_palette;
-
- Common::Queue<Common::Event> _event_queue;
- MutexRef _event_queue_lock;
-
- bool _timer_thread_exit;
- pthread_t _timer_thread;
- static void* timerThreadFunc(void* arg);
-
- bool _enable_zoning;
- bool _virtkeybd_on;
-
- Common::SaveFileManager *_savefile;
- Audio::MixerImpl *_mixer;
- Common::TimerManager *_timer;
- FilesystemFactory *_fsFactory;
- Common::Archive *_asset_archive;
- timeval _startTime;
-
- void setupScummVMSurface();
- void destroyScummVMSurface();
- void setupKeymapper();
- void _setCursorPalette(const byte *colors, uint start, uint num);
-
-public:
- OSystem_Android(jobject am);
- virtual ~OSystem_Android();
- bool initJavaHooks(JNIEnv* env, jobject self);
-
- static OSystem_Android* fromJavaObject(JNIEnv* env, jobject obj);
- virtual void initBackend();
- void addPluginDirectories(Common::FSList &dirs) const;
- void enableZoning(bool enable) { _enable_zoning = enable; }
- void setSurfaceSize(int width, int height) {
- _egl_surface_width = width;
- _egl_surface_height = height;
- }
-
- virtual bool hasFeature(Feature f);
- virtual void setFeatureState(Feature f, bool enable);
- virtual bool getFeatureState(Feature f);
- virtual const GraphicsMode *getSupportedGraphicsModes() const;
- virtual int getDefaultGraphicsMode() const;
- bool setGraphicsMode(const char *name);
- virtual bool setGraphicsMode(int mode);
- virtual int getGraphicsMode() const;
- virtual void initSize(uint width, uint height,
- const Graphics::PixelFormat *format);
- virtual int getScreenChangeID() const { return _screen_changeid; }
- virtual int16 getHeight();
- virtual int16 getWidth();
-
- virtual PaletteManager *getPaletteManager() { return this; }
-protected:
- // PaletteManager API
- virtual void setPalette(const byte *colors, uint start, uint num);
- virtual void grabPalette(byte *colors, uint start, uint num);
-
-public:
- virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
- virtual void updateScreen();
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
- virtual void setShakePos(int shakeOffset);
- virtual void fillScreen(uint32 col);
- virtual void setFocusRectangle(const Common::Rect& rect);
- virtual void clearFocusRectangle();
-
- virtual void showOverlay();
- virtual void hideOverlay();
- virtual void clearOverlay();
- virtual void grabOverlay(OverlayColor *buf, int pitch);
- virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
- virtual int16 getOverlayHeight();
- virtual int16 getOverlayWidth();
- virtual Graphics::PixelFormat getOverlayFormat() const {
- // RGBA 4444
- Graphics::PixelFormat format;
- format.bytesPerPixel = 2;
- format.rLoss = 8 - 4;
- format.gLoss = 8 - 4;
- format.bLoss = 8 - 4;
- format.aLoss = 8 - 4;
- format.rShift = 3*4;
- format.gShift = 2*4;
- format.bShift = 1*4;
- format.aShift = 0*4;
- return format;
- }
-
- virtual bool showMouse(bool visible);
-
- virtual void warpMouse(int x, int y);
- virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
- virtual void setCursorPalette(const byte *colors, uint start, uint num);
- virtual void disableCursorPalette(bool disable);
-
- virtual bool pollEvent(Common::Event &event);
- void pushEvent(const Common::Event& event);
- virtual uint32 getMillis();
- virtual void delayMillis(uint msecs);
-
- virtual MutexRef createMutex(void);
- virtual void lockMutex(MutexRef mutex);
- virtual void unlockMutex(MutexRef mutex);
- virtual void deleteMutex(MutexRef mutex);
-
- virtual void quit();
-
- virtual void setWindowCaption(const char *caption);
- virtual void displayMessageOnOSD(const char *msg);
- virtual void showVirtualKeyboard(bool enable);
-
- virtual Common::SaveFileManager *getSavefileManager();
- virtual Audio::Mixer *getMixer();
- virtual void getTimeAndDate(TimeDate &t) const;
- virtual Common::TimerManager *getTimerManager();
- virtual FilesystemFactory *getFilesystemFactory();
- virtual void logMessage(LogMessageType::Type type, const char *message);
- virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
-};
-
-OSystem_Android::OSystem_Android(jobject am)
- : _back_ptr(0),
- _screen_changeid(0),
- _force_redraw(false),
- _game_texture(NULL),
- _overlay_texture(NULL),
- _mouse_texture(NULL),
- _use_mouse_palette(false),
- _show_mouse(false),
- _show_overlay(false),
- _enable_zoning(false),
- _savefile(0),
- _mixer(0),
- _timer(0),
- _fsFactory(new POSIXFilesystemFactory()),
- _asset_archive(new AndroidAssetArchive(am)),
- _shake_offset(0),
- _event_queue_lock(createMutex()) {
+OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
+ _audio_sample_rate(audio_sample_rate),
+ _audio_buffer_size(audio_buffer_size),
+ _screen_changeid(0),
+ _egl_surface_width(0),
+ _egl_surface_height(0),
+ _htc_fail(false),
+ _force_redraw(false),
+ _game_texture(0),
+ _overlay_texture(0),
+ _mouse_texture(0),
+ _mouse_texture_palette(0),
+ _mouse_texture_rgb(0),
+ _mouse_hotspot(),
+ _mouse_keycolor(0),
+ _use_mouse_palette(false),
+ _graphicsMode(0),
+ _fullscreen(true),
+ _ar_correction(true),
+ _show_mouse(false),
+ _show_overlay(false),
+ _enable_zoning(false),
+ _savefile(0),
+ _mixer(0),
+ _timer(0),
+ _fsFactory(new POSIXFilesystemFactory()),
+ _shake_offset(0),
+ _event_queue_lock(createMutex()),
+ _touch_pt_down(),
+ _touch_pt_scroll(),
+ _touch_pt_dt(),
+ _eventScaleX(100),
+ _eventScaleY(100),
+ // TODO put these values in some option dlg?
+ _touchpad_mode(true),
+ _touchpad_scale(66),
+ _dpad_scale(4),
+ _fingersDown(0),
+ _trackball_scale(2) {
+ Common::String mf = getSystemProperty("ro.product.manufacturer");
+
+ LOGI("Running on: [%s] [%s] [%s] [%s] [%s] SDK:%s ABI:%s",
+ mf.c_str(),
+ getSystemProperty("ro.product.model").c_str(),
+ getSystemProperty("ro.product.brand").c_str(),
+ getSystemProperty("ro.build.fingerprint").c_str(),
+ getSystemProperty("ro.build.display.id").c_str(),
+ getSystemProperty("ro.build.version.sdk").c_str(),
+ getSystemProperty("ro.product.cpu.abi").c_str());
+
+ mf.toLowercase();
+ _htc_fail = mf.contains("htc");
+
+ if (_htc_fail)
+ LOGI("Enabling HTC workaround");
}
OSystem_Android::~OSystem_Android() {
- ENTER("~OSystem_Android()");
- delete _game_texture;
- delete _overlay_texture;
- delete _mouse_texture;
- destroyScummVMSurface();
- JNIEnv* env = JNU_GetEnv();
- //env->DeleteWeakGlobalRef(_back_ptr);
- env->DeleteGlobalRef(_back_ptr);
+ ENTER();
+
delete _savefile;
- delete _mixer;
delete _timer;
+ delete _mixer;
delete _fsFactory;
- delete _asset_archive;
- deleteMutex(_event_queue_lock);
-}
-
-OSystem_Android* OSystem_Android::fromJavaObject(JNIEnv* env, jobject obj) {
- jlong peer = env->GetLongField(obj, FID_ScummVM_nativeScummVM);
- return (OSystem_Android*)peer;
-}
-
-bool OSystem_Android::initJavaHooks(JNIEnv* env, jobject self) {
- // weak global ref to allow class to be unloaded
- // ... except dalvik doesn't implement NewWeakGlobalRef (yet)
- //_back_ptr = env->NewWeakGlobalRef(self);
- _back_ptr = env->NewGlobalRef(self);
-
- jclass cls = env->GetObjectClass(_back_ptr);
-
-#define FIND_METHOD(name, signature) do { \
- MID_ ## name = env->GetMethodID(cls, #name, signature); \
- if (MID_ ## name == NULL) \
- return false; \
- } while (0)
-
- FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
- FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
- FIND_METHOD(initBackend, "()V");
- FIND_METHOD(audioSampleRate, "()I");
- FIND_METHOD(showVirtualKeyboard, "(Z)V");
- FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
- FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
- FIND_METHOD(setupScummVMSurface, "()V");
- FIND_METHOD(destroyScummVMSurface, "()V");
- FIND_METHOD(swapBuffers, "()Z");
-
-#undef FIND_METHOD
-
- return true;
-}
-
-static void ScummVM_create(JNIEnv* env, jobject self, jobject am) {
- OSystem_Android* cpp_obj = new OSystem_Android(am);
- if (!cpp_obj->initJavaHooks(env, self))
- // Exception already thrown by initJavaHooks
- return;
-
- env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)cpp_obj);
-
-#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new AndroidPluginProvider());
-#endif
-}
-static void ScummVM_nativeDestroy(JNIEnv* env, jobject self) {
- OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
- delete cpp_obj;
-}
-
-static void ScummVM_audioMixCallback(JNIEnv* env, jobject self,
- jbyteArray jbuf) {
- OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
- jsize len = env->GetArrayLength(jbuf);
- jbyte* buf = env->GetByteArrayElements(jbuf, NULL);
- if (buf == NULL) {
- warning("Unable to get Java audio byte array. Skipping");
- return;
- }
- Audio::MixerImpl* mixer =
- static_cast<Audio::MixerImpl*>(cpp_obj->getMixer());
- assert(mixer);
- mixer->mixCallback(reinterpret_cast<byte*>(buf), len);
- env->ReleaseByteArrayElements(jbuf, buf, 0);
+ deleteMutex(_event_queue_lock);
}
-static void ScummVM_setConfManInt(JNIEnv* env, jclass cls,
- jstring key_obj, jint value) {
- ENTER("setConfManInt(%p, %d)", key_obj, (int)value);
- const char* key = env->GetStringUTFChars(key_obj, NULL);
- if (key == NULL)
- return;
- ConfMan.setInt(key, value);
- env->ReleaseStringUTFChars(key_obj, key);
-}
+void *OSystem_Android::timerThreadFunc(void *arg) {
+ OSystem_Android *system = (OSystem_Android *)arg;
+ DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
-static void ScummVM_setConfManString(JNIEnv* env, jclass cls, jstring key_obj,
- jstring value_obj) {
- ENTER("setConfManStr(%p, %p)", key_obj, value_obj);
- const char* key = env->GetStringUTFChars(key_obj, NULL);
- if (key == NULL)
- return;
- const char* value = env->GetStringUTFChars(value_obj, NULL);
- if (value == NULL) {
- env->ReleaseStringUTFChars(key_obj, key);
- return;
- }
- ConfMan.set(key, value);
- env->ReleaseStringUTFChars(value_obj, value);
- env->ReleaseStringUTFChars(key_obj, key);
-}
+ // renice this thread to boost the audio thread
+ if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+ LOGW("couldn't renice the timer thread");
-void* OSystem_Android::timerThreadFunc(void* arg) {
- OSystem_Android* system = (OSystem_Android*)arg;
- DefaultTimerManager* timer = (DefaultTimerManager*)(system->_timer);
+ JNI::attachThread();
struct timespec tv;
tv.tv_sec = 0;
- tv.tv_nsec = 100 * 1000 * 1000; // 100ms
+ tv.tv_nsec = 10 * 1000 * 1000; // 10ms
while (!system->_timer_thread_exit) {
- timer->handler();
- nanosleep(&tv, NULL);
- }
-
- return NULL;
-}
-
-void OSystem_Android::initBackend() {
- ENTER("initBackend()");
- JNIEnv* env = JNU_GetEnv();
-
- ConfMan.setInt("autosave_period", 0);
- ConfMan.setInt("FM_medium_quality", true);
-
- // must happen before creating TimerManager to avoid race in
- // creating EventManager
- setupKeymapper();
-
- // BUG: "transient" ConfMan settings get nuked by the options
- // screen. Passing the savepath in this way makes it stick
- // (via ConfMan.registerDefault)
- _savefile = new DefaultSaveFileManager(ConfMan.get("savepath"));
- _timer = new DefaultTimerManager();
-
- gettimeofday(&_startTime, NULL);
-
- jint sample_rate = env->CallIntMethod(_back_ptr, MID_audioSampleRate);
- if (env->ExceptionCheck()) {
- warning("Error finding audio sample rate - assuming 11025HZ");
- env->ExceptionDescribe();
- env->ExceptionClear();
- sample_rate = 11025;
- }
- _mixer = new Audio::MixerImpl(this, sample_rate);
- _mixer->setReady(true);
-
- env->CallVoidMethod(_back_ptr, MID_initBackend);
- if (env->ExceptionCheck()) {
- error("Error in Java initBackend");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
-
- _timer_thread_exit = false;
- pthread_create(&_timer_thread, NULL, timerThreadFunc, this);
-
- OSystem::initBackend();
-
- setupScummVMSurface();
-}
-
-void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
- ENTER("OSystem_Android::addPluginDirectories()");
- JNIEnv* env = JNU_GetEnv();
-
- jobjectArray array =
- (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getPluginDirectories);
- if (env->ExceptionCheck()) {
- warning("Error finding plugin directories");
- env->ExceptionDescribe();
- env->ExceptionClear();
- return;
- }
-
- jsize size = env->GetArrayLength(array);
- for (jsize i = 0; i < size; ++i) {
- jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
- if (path_obj == NULL)
- continue;
- const char* path = env->GetStringUTFChars(path_obj, NULL);
- if (path == NULL) {
- warning("Error getting string characters from plugin directory");
- env->ExceptionClear();
- env->DeleteLocalRef(path_obj);
- continue;
+ if (JNI::pause) {
+ LOGD("timer thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("timer thread woke up");
}
- dirs.push_back(Common::FSNode(path));
- env->ReleaseStringUTFChars(path_obj, path);
- env->DeleteLocalRef(path_obj);
- }
-}
-
-bool OSystem_Android::hasFeature(Feature f) {
- return (f == kFeatureCursorHasPalette ||
- f == kFeatureVirtualKeyboard ||
- f == kFeatureOverlaySupportsAlpha);
-}
-
-void OSystem_Android::setFeatureState(Feature f, bool enable) {
- ENTER("setFeatureState(%d, %d)", f, enable);
- switch (f) {
- case kFeatureVirtualKeyboard:
- _virtkeybd_on = enable;
- showVirtualKeyboard(enable);
- break;
- default:
- break;
- }
-}
-bool OSystem_Android::getFeatureState(Feature f) {
- switch (f) {
- case kFeatureVirtualKeyboard:
- return _virtkeybd_on;
- default:
- return false;
+ timer->handler();
+ nanosleep(&tv, 0);
}
-}
-const OSystem::GraphicsMode* OSystem_Android::getSupportedGraphicsModes() const {
- static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- {"default", "Default", 1},
- {0, 0, 0},
- };
- return s_supportedGraphicsModes;
-}
-
-
-int OSystem_Android::getDefaultGraphicsMode() const {
- return 1;
-}
+ JNI::detachThread();
-bool OSystem_Android::setGraphicsMode(const char *mode) {
- ENTER("setGraphicsMode(%s)", mode);
- return true;
+ return 0;
}
-bool OSystem_Android::setGraphicsMode(int mode) {
- ENTER("setGraphicsMode(%d)", mode);
- return true;
-}
-
-int OSystem_Android::getGraphicsMode() const {
- return 1;
-}
+void *OSystem_Android::audioThreadFunc(void *arg) {
+ JNI::attachThread();
-void OSystem_Android::setupScummVMSurface() {
- ENTER("setupScummVMSurface");
- JNIEnv* env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
- if (env->ExceptionCheck())
- return;
+ OSystem_Android *system = (OSystem_Android *)arg;
+ Audio::MixerImpl *mixer = system->_mixer;
- // EGL set up with a new surface. Initialise OpenGLES context.
+ uint buf_size = system->_audio_buffer_size;
- GLESTexture::initGLExtensions();
+ JNIEnv *env = JNI::getEnv();
- // Turn off anything that looks like 3D ;)
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_LIGHTING);
- glDisable(GL_FOG);
- glDisable(GL_DITHER);
- glShadeModel(GL_FLAT);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+ jbyteArray bufa = env->NewByteArray(buf_size);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ bool paused = true;
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ byte *buf;
+ int offset, left, written;
+ int samples, i;
- glEnable(GL_TEXTURE_2D);
+ struct timespec tv_delay;
+ tv_delay.tv_sec = 0;
+ tv_delay.tv_nsec = 20 * 1000 * 1000;
- if (!_game_texture)
- _game_texture = new GLESPaletteTexture();
- else
- _game_texture->reinitGL();
+ uint msecs_full = buf_size * 1000 / (mixer->getOutputRate() * 2 * 2);
- if (!_overlay_texture)
- _overlay_texture = new GLES4444Texture();
- else
- _overlay_texture->reinitGL();
-
- if (!_mouse_texture)
- _mouse_texture = new GLESPaletteATexture();
- else
- _mouse_texture->reinitGL();
-
- glViewport(0, 0, _egl_surface_width, _egl_surface_height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- clearFocusRectangle();
- CHECK_GL_ERROR();
-}
+ struct timespec tv_full;
+ tv_full.tv_sec = 0;
+ tv_full.tv_nsec = msecs_full * 1000 * 1000;
-void OSystem_Android::destroyScummVMSurface() {
- JNIEnv* env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
- // Can't use OpenGLES functions after this
-}
+ bool silence;
+ uint silence_count = 33;
-void OSystem_Android::initSize(uint width, uint height,
- const Graphics::PixelFormat *format) {
- ENTER("initSize(%d,%d,%p)", width, height, format);
+ while (!system->_audio_thread_exit) {
+ if (JNI::pause) {
+ JNI::setAudioStop();
- _game_texture->allocBuffer(width, height);
+ paused = true;
+ silence_count = 33;
- // Cap at 320x200 or the ScummVM themes abort :/
- GLuint overlay_width = MIN(_egl_surface_width, 320);
- GLuint overlay_height = MIN(_egl_surface_height, 200);
- _overlay_texture->allocBuffer(overlay_width, overlay_height);
+ LOGD("audio thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("audio thread woke up");
+ }
- // Don't know mouse size yet - it gets reallocated in
- // setMouseCursor. We need the palette allocated before
- // setMouseCursor however, so just take a guess at the desired
- // size (it's small).
- _mouse_texture->allocBuffer(20, 20);
-}
+ buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0);
+ assert(buf);
-int16 OSystem_Android::getHeight() {
- return _game_texture->height();
-}
+ samples = mixer->mixCallback(buf, buf_size);
-int16 OSystem_Android::getWidth() {
- return _game_texture->width();
-}
+ silence = samples < 1;
-void OSystem_Android::setPalette(const byte* colors, uint start, uint num) {
- ENTER("setPalette(%p, %u, %u)", colors, start, num);
+ // looks stupid, and it is, but currently there's no way to detect
+ // silence-only buffers from the mixer
+ if (!silence) {
+ silence = true;
- if (!_use_mouse_palette)
- _setCursorPalette(colors, start, num);
+ for (i = 0; i < samples; i += 2)
+ // SID streams constant crap
+ if (READ_UINT16(buf + i) > 32) {
+ silence = false;
+ break;
+ }
+ }
- byte* palette = _game_texture->palette() + start*3;
- do {
- for (int i = 0; i < 3; ++i)
- palette[i] = colors[i];
- palette += 3;
- colors += 4;
- } while (--num);
-}
+ env->ReleasePrimitiveArrayCritical(bufa, buf, 0);
-void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
- ENTER("grabPalette(%p, %u, %u)", colors, start, num);
- const byte* palette = _game_texture->palette_const() + start*3;
- do {
- for (int i = 0; i < 3; ++i)
- colors[i] = palette[i];
- colors[3] = 0xff; // alpha
-
- palette += 3;
- colors += 4;
- } while (--num);
-}
+ if (silence) {
+ if (!paused)
+ silence_count++;
-void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
- int x, int y, int w, int h) {
- ENTER("copyRectToScreen(%p, %d, %d, %d, %d, %d)",
- buf, pitch, x, y, w, h);
+ // only pause after a while to prevent toggle mania
+ if (silence_count > 32) {
+ if (!paused) {
+ LOGD("AudioTrack pause");
- _game_texture->updateBuffer(x, y, w, h, buf, pitch);
-}
+ JNI::setAudioPause();
+ paused = true;
+ }
-void OSystem_Android::updateScreen() {
- //ENTER("updateScreen()");
+ nanosleep(&tv_full, 0);
- if (!_force_redraw &&
- !_game_texture->dirty() &&
- !_overlay_texture->dirty() &&
- !_mouse_texture->dirty())
- return;
+ continue;
+ }
+ }
- _force_redraw = false;
+ if (paused) {
+ LOGD("AudioTrack play");
- glPushMatrix();
+ JNI::setAudioPlay();
+ paused = false;
- if (_shake_offset != 0 ||
- (!_focus_rect.isEmpty() &&
- !Common::Rect(_game_texture->width(),
- _game_texture->height()).contains(_focus_rect))) {
- // These are the only cases where _game_texture doesn't
- // cover the entire screen.
- glClearColorx(0, 0, 0, 1 << 16);
- glClear(GL_COLOR_BUFFER_BIT);
+ silence_count = 0;
+ }
- // Move everything up by _shake_offset (game) pixels
- glTranslatex(0, -_shake_offset << 16, 0);
- }
+ offset = 0;
+ left = buf_size;
+ written = 0;
- if (_focus_rect.isEmpty()) {
- _game_texture->drawTexture(0, 0,
- _egl_surface_width, _egl_surface_height);
- } else {
- glPushMatrix();
- glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
- xdiv(_egl_surface_height, _focus_rect.height()),
- 1 << 16);
- glTranslatex(-_focus_rect.left << 16, -_focus_rect.top << 16, 0);
- glScalex(xdiv(_game_texture->width(), _egl_surface_width),
- xdiv(_game_texture->height(), _egl_surface_height),
- 1 << 16);
- _game_texture->drawTexture(0, 0,
- _egl_surface_width, _egl_surface_height);
- glPopMatrix();
- }
+ while (left > 0) {
+ written = JNI::writeAudio(env, bufa, offset, left);
- CHECK_GL_ERROR();
+ if (written < 0) {
+ LOGE("AudioTrack error: %d", written);
+ break;
+ }
- if (_show_overlay) {
- _overlay_texture->drawTexture(0, 0,
- _egl_surface_width,
- _egl_surface_height);
- CHECK_GL_ERROR();
- }
+ // buffer full
+ if (written < left)
+ nanosleep(&tv_delay, 0);
- if (_show_mouse) {
- glPushMatrix();
-
- glTranslatex(-_mouse_hotspot.x << 16,
- -_mouse_hotspot.y << 16,
- 0);
-
- // Scale up ScummVM -> OpenGL (pixel) coordinates
- int texwidth, texheight;
- if (_show_overlay) {
- texwidth = getOverlayWidth();
- texheight = getOverlayHeight();
- } else {
- texwidth = getWidth();
- texheight = getHeight();
+ offset += written;
+ left -= written;
}
- glScalex(xdiv(_egl_surface_width, texwidth),
- xdiv(_egl_surface_height, texheight),
- 1 << 16);
-
- // Note the extra half texel to position the mouse in
- // the middle of the x,y square:
- const Common::Point& mouse = getEventManager()->getMousePos();
- glTranslatex((mouse.x << 16) | 1 << 15,
- (mouse.y << 16) | 1 << 15, 0);
-
- // Mouse targetscale just seems to make the cursor way
- // too big :/
- //glScalex(_mouse_targetscale << 16, _mouse_targetscale << 16,
- // 1 << 16);
- _mouse_texture->drawTexture();
+ if (written < 0)
+ break;
- glPopMatrix();
+ // prepare the next buffer, and run into the blocking AudioTrack.write
}
- glPopMatrix();
+ JNI::setAudioStop();
- CHECK_GL_ERROR();
+ env->DeleteLocalRef(bufa);
- JNIEnv* env = JNU_GetEnv();
- if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
- // Context lost -> need to reinit GL
- destroyScummVMSurface();
- setupScummVMSurface();
- }
-}
-
-Graphics::Surface *OSystem_Android::lockScreen() {
- ENTER("lockScreen()");
- Graphics::Surface* surface = _game_texture->surface();
- assert(surface->pixels);
- return surface;
-}
+ JNI::detachThread();
-void OSystem_Android::unlockScreen() {
- ENTER("unlockScreen()");
- assert(_game_texture->dirty());
+ return 0;
}
-void OSystem_Android::setShakePos(int shake_offset) {
- ENTER("setShakePos(%d)", shake_offset);
- if (_shake_offset != shake_offset) {
- _shake_offset = shake_offset;
- _force_redraw = true;
- }
-}
-
-void OSystem_Android::fillScreen(uint32 col) {
- ENTER("fillScreen(%u)", col);
- assert(col < 256);
- _game_texture->fillBuffer(col);
-}
+void OSystem_Android::initBackend() {
+ ENTER();
-void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
- ENTER("setFocusRectangle(%d,%d,%d,%d)",
- rect.left, rect.top, rect.right, rect.bottom);
- if (_enable_zoning) {
- _focus_rect = rect;
- _force_redraw = true;
- }
-}
+ _main_thread = pthread_self();
-void OSystem_Android::clearFocusRectangle() {
- ENTER("clearFocusRectangle()");
- if (_enable_zoning) {
- _focus_rect = Common::Rect();
- _force_redraw = true;
- }
-}
+ ConfMan.registerDefault("fullscreen", true);
+ ConfMan.registerDefault("aspect_ratio", true);
-void OSystem_Android::showOverlay() {
- ENTER("showOverlay()");
- _show_overlay = true;
- _force_redraw = true;
-}
+ ConfMan.setInt("autosave_period", 0);
+ ConfMan.setBool("FM_high_quality", false);
+ ConfMan.setBool("FM_medium_quality", true);
-void OSystem_Android::hideOverlay() {
- ENTER("hideOverlay()");
- _show_overlay = false;
- _force_redraw = true;
-}
+ // TODO hackity hack
+ if (ConfMan.hasKey("multi_midi"))
+ _touchpad_mode = !ConfMan.getBool("multi_midi");
-void OSystem_Android::clearOverlay() {
- ENTER("clearOverlay()");
- _overlay_texture->fillBuffer(0);
+ // must happen before creating TimerManager to avoid race in
+ // creating EventManager
+ setupKeymapper();
- // Shouldn't need this, but works around a 'blank screen' bug on Nexus1
- updateScreen();
-}
+ // BUG: "transient" ConfMan settings get nuked by the options
+ // screen. Passing the savepath in this way makes it stick
+ // (via ConfMan.registerDefault)
+ _savefile = new DefaultSaveFileManager(ConfMan.get("savepath"));
+ _timer = new DefaultTimerManager();
-void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
- ENTER("grabOverlay(%p, %d)", buf, pitch);
- // We support overlay alpha blending, so the pixel data here
- // shouldn't actually be used. Let's fill it with zeros, I'm sure
- // it will be fine...
- const Graphics::Surface* surface = _overlay_texture->surface_const();
- assert(surface->bytesPerPixel == sizeof(buf[0]));
- int h = surface->h;
- do {
- memset(buf, 0, surface->w * sizeof(buf[0]));
- buf += pitch; // This 'pitch' is pixels not bytes
- } while (--h);
-}
+ gettimeofday(&_startTime, 0);
-void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
- int x, int y, int w, int h) {
- ENTER("copyRectToOverlay(%p, %d, %d, %d, %d, %d)",
- buf, pitch, x, y, w, h);
- const Graphics::Surface* surface = _overlay_texture->surface_const();
- assert(surface->bytesPerPixel == sizeof(buf[0]));
+ _mixer = new Audio::MixerImpl(this, _audio_sample_rate);
+ _mixer->setReady(true);
- // This 'pitch' is pixels not bytes
- _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
+ _timer_thread_exit = false;
+ pthread_create(&_timer_thread, 0, timerThreadFunc, this);
- // Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
- updateScreen();
-}
+ _audio_thread_exit = false;
+ pthread_create(&_audio_thread, 0, audioThreadFunc, this);
-int16 OSystem_Android::getOverlayHeight() {
- return _overlay_texture->height();
-}
+ initSurface();
+ initViewport();
-int16 OSystem_Android::getOverlayWidth() {
- return _overlay_texture->width();
-}
+ _game_texture = new GLESFakePalette565Texture();
+ _overlay_texture = new GLES4444Texture();
+ _mouse_texture_palette = new GLESFakePalette5551Texture();
+ _mouse_texture = _mouse_texture_palette;
-bool OSystem_Android::showMouse(bool visible) {
- ENTER("showMouse(%d)", visible);
- _show_mouse = visible;
- return true;
-}
+ initOverlay();
-void OSystem_Android::warpMouse(int x, int y) {
- ENTER("warpMouse(%d, %d)", x, y);
- // We use only the eventmanager's idea of the current mouse
- // position, so there is nothing extra to do here.
-}
+ // renice this thread to boost the audio thread
+ if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+ warning("couldn't renice the main thread");
-void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
- int hotspotX, int hotspotY,
- uint32 keycolor, int cursorTargetScale,
- const Graphics::PixelFormat *format) {
- ENTER("setMouseCursor(%p, %u, %u, %d, %d, %d, %d, %p)",
- buf, w, h, hotspotX, hotspotY, (int)keycolor, cursorTargetScale,
- format);
-
- assert(keycolor < 256);
-
- _mouse_texture->allocBuffer(w, h);
-
- // Update palette alpha based on keycolor
- byte* palette = _mouse_texture->palette();
- int i = 256;
- do {
- palette[3] = 0xff;
- palette += 4;
- } while (--i);
- palette = _mouse_texture->palette();
- palette[keycolor*4 + 3] = 0x00;
- _mouse_texture->updateBuffer(0, 0, w, h, buf, w);
-
- _mouse_hotspot = Common::Point(hotspotX, hotspotY);
- _mouse_targetscale = cursorTargetScale;
+ JNI::setReadyForEvents(true);
}
-void OSystem_Android::_setCursorPalette(const byte *colors,
- uint start, uint num) {
- byte* palette = _mouse_texture->palette() + start*4;
- do {
- for (int i = 0; i < 3; ++i)
- palette[i] = colors[i];
- // Leave alpha untouched to preserve keycolor
-
- palette += 4;
- colors += 4;
- } while (--num);
-}
+void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
+ ENTER();
-void OSystem_Android::setCursorPalette(const byte *colors,
- uint start, uint num) {
- ENTER("setCursorPalette(%p, %u, %u)", colors, start, num);
- _setCursorPalette(colors, start, num);
- _use_mouse_palette = true;
+ JNI::getPluginDirectories(dirs);
}
-void OSystem_Android::disableCursorPalette(bool disable) {
- ENTER("disableCursorPalette(%d)", disable);
- _use_mouse_palette = !disable;
+bool OSystem_Android::hasFeature(Feature f) {
+ return (f == kFeatureFullscreenMode ||
+ f == kFeatureAspectRatioCorrection ||
+ f == kFeatureCursorHasPalette ||
+ f == kFeatureVirtualKeyboard ||
+ f == kFeatureOverlaySupportsAlpha);
}
-void OSystem_Android::setupKeymapper() {
-#ifdef ENABLE_KEYMAPPER
- using namespace Common;
-
- Keymapper *mapper = getEventManager()->getKeymapper();
-
- HardwareKeySet *keySet = new HardwareKeySet();
- keySet->addHardwareKey(
- new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)",
- kTriggerLeftKeyType,
- kVirtualKeyboardActionType));
- mapper->registerHardwareKeySet(keySet);
-
- Keymap *globalMap = new Keymap("global");
- Action *act;
-
- act = new Action(globalMap, "VIRT", "Display keyboard",
- kVirtualKeyboardActionType);
- act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
-
- mapper->addGlobalKeymap(globalMap);
-
- mapper->pushKeymap("global");
-#endif
-}
+void OSystem_Android::setFeatureState(Feature f, bool enable) {
+ ENTER("%d, %d", f, enable);
-bool OSystem_Android::pollEvent(Common::Event &event) {
- //ENTER("pollEvent()");
- lockMutex(_event_queue_lock);
- if (_event_queue.empty()) {
- unlockMutex(_event_queue_lock);
- return false;
- }
- event = _event_queue.pop();
- unlockMutex(_event_queue_lock);
-
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- // TODO: only dirty/redraw move bounds
- _force_redraw = true;
- // fallthrough
- case Common::EVENT_LBUTTONDOWN:
- case Common::EVENT_LBUTTONUP:
- case Common::EVENT_RBUTTONDOWN:
- case Common::EVENT_RBUTTONUP:
- case Common::EVENT_WHEELUP:
- case Common::EVENT_WHEELDOWN:
- case Common::EVENT_MBUTTONDOWN:
- case Common::EVENT_MBUTTONUP: {
- if (event.kbd.flags == 1) { // relative mouse hack
- // Relative (trackball) mouse hack.
- const Common::Point& mouse_pos =
- getEventManager()->getMousePos();
- event.mouse.x += mouse_pos.x;
- event.mouse.y += mouse_pos.y;
- event.mouse.x = CLIP(event.mouse.x, (int16)0, _show_overlay ?
- getOverlayWidth() : getWidth());
- event.mouse.y = CLIP(event.mouse.y, (int16)0, _show_overlay ?
- getOverlayHeight() : getHeight());
- } else {
- // Touchscreen events need to be converted
- // from device to game coords first.
- const GLESTexture* tex = _show_overlay
- ? static_cast<GLESTexture*>(_overlay_texture)
- : static_cast<GLESTexture*>(_game_texture);
- event.mouse.x = scalef(event.mouse.x, tex->width(),
- _egl_surface_width);
- event.mouse.y = scalef(event.mouse.y, tex->height(),
- _egl_surface_height);
- event.mouse.x -= _shake_offset;
- }
+ switch (f) {
+ case kFeatureFullscreenMode:
+ _fullscreen = enable;
+ updateScreenRect();
break;
- }
- case Common::EVENT_SCREEN_CHANGED:
- debug("EVENT_SCREEN_CHANGED");
- _screen_changeid++;
- destroyScummVMSurface();
- setupScummVMSurface();
+ case kFeatureAspectRatioCorrection:
+ _ar_correction = enable;
+ updateScreenRect();
+ break;
+ case kFeatureVirtualKeyboard:
+ _virtkeybd_on = enable;
+ showVirtualKeyboard(enable);
break;
default:
break;
}
-
- return true;
-}
-
-void OSystem_Android::pushEvent(const Common::Event& event) {
- lockMutex(_event_queue_lock);
-
- // Try to combine multiple queued mouse move events
- if (event.type == Common::EVENT_MOUSEMOVE &&
- !_event_queue.empty() &&
- _event_queue.back().type == Common::EVENT_MOUSEMOVE) {
- Common::Event tail = _event_queue.back();
- if (event.kbd.flags) {
- // relative movement hack
- tail.mouse.x += event.mouse.x;
- tail.mouse.y += event.mouse.y;
- } else {
- // absolute position
- tail.kbd.flags = 0; // clear relative flag
- tail.mouse.x = event.mouse.x;
- tail.mouse.y = event.mouse.y;
- }
- }
- else
- _event_queue.push(event);
-
- unlockMutex(_event_queue_lock);
}
-static void ScummVM_pushEvent(JNIEnv* env, jobject self, jobject java_event) {
- OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
-
- Common::Event event;
- event.type = (Common::EventType)env->GetIntField(java_event,
- FID_Event_type);
- event.synthetic =
- env->GetBooleanField(java_event, FID_Event_synthetic);
-
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- case Common::EVENT_KEYUP:
- event.kbd.keycode = (Common::KeyCode)env->GetIntField(
- java_event, FID_Event_kbd_keycode);
- event.kbd.ascii = static_cast<int>(env->GetIntField(
- java_event, FID_Event_kbd_ascii));
- event.kbd.flags = static_cast<int>(env->GetIntField(
- java_event, FID_Event_kbd_flags));
- break;
- case Common::EVENT_MOUSEMOVE:
- case Common::EVENT_LBUTTONDOWN:
- case Common::EVENT_LBUTTONUP:
- case Common::EVENT_RBUTTONDOWN:
- case Common::EVENT_RBUTTONUP:
- case Common::EVENT_WHEELUP:
- case Common::EVENT_WHEELDOWN:
- case Common::EVENT_MBUTTONDOWN:
- case Common::EVENT_MBUTTONUP:
- event.mouse.x =
- env->GetIntField(java_event, FID_Event_mouse_x);
- event.mouse.y =
- env->GetIntField(java_event, FID_Event_mouse_y);
- // This is a terrible hack. We stash "relativeness"
- // in the kbd.flags field until pollEvent() can work
- // it out.
- event.kbd.flags = env->GetBooleanField(
- java_event, FID_Event_mouse_relative) ? 1 : 0;
- break;
+bool OSystem_Android::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureFullscreenMode:
+ return _fullscreen;
+ case kFeatureAspectRatioCorrection:
+ return _ar_correction;
+ case kFeatureVirtualKeyboard:
+ return _virtkeybd_on;
default:
- break;
+ return false;
}
-
- cpp_obj->pushEvent(event);
}
uint32 OSystem_Android::getMillis() {
timeval curTime;
- gettimeofday(&curTime, NULL);
- return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + \
+
+ gettimeofday(&curTime, 0);
+
+ return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) +
((curTime.tv_usec - _startTime.tv_usec) / 1000));
}
@@ -1141,30 +438,36 @@ void OSystem_Android::delayMillis(uint msecs) {
OSystem::MutexRef OSystem_Android::createMutex() {
pthread_mutexattr_t attr;
+
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_t *mutex = new pthread_mutex_t;
+
if (pthread_mutex_init(mutex, &attr) != 0) {
warning("pthread_mutex_init() failed");
+
delete mutex;
- return NULL;
+
+ return 0;
}
+
return (MutexRef)mutex;
}
void OSystem_Android::lockMutex(MutexRef mutex) {
- if (pthread_mutex_lock((pthread_mutex_t*)mutex) != 0)
+ if (pthread_mutex_lock((pthread_mutex_t *)mutex) != 0)
warning("pthread_mutex_lock() failed");
}
void OSystem_Android::unlockMutex(MutexRef mutex) {
- if (pthread_mutex_unlock((pthread_mutex_t*)mutex) != 0)
+ if (pthread_mutex_unlock((pthread_mutex_t *)mutex) != 0)
warning("pthread_mutex_unlock() failed");
}
void OSystem_Android::deleteMutex(MutexRef mutex) {
- pthread_mutex_t* m = (pthread_mutex_t*)mutex;
+ pthread_mutex_t *m = (pthread_mutex_t *)mutex;
+
if (pthread_mutex_destroy(m) != 0)
warning("pthread_mutex_destroy() failed");
else
@@ -1172,47 +475,40 @@ void OSystem_Android::deleteMutex(MutexRef mutex) {
}
void OSystem_Android::quit() {
- ENTER("quit()");
+ ENTER();
+
+ JNI::setReadyForEvents(false);
+
+ _audio_thread_exit = true;
+ pthread_join(_audio_thread, 0);
_timer_thread_exit = true;
- pthread_join(_timer_thread, NULL);
+ pthread_join(_timer_thread, 0);
+
+ delete _game_texture;
+ delete _overlay_texture;
+ delete _mouse_texture_palette;
+ delete _mouse_texture_rgb;
+
+ deinitSurface();
}
void OSystem_Android::setWindowCaption(const char *caption) {
- ENTER("setWindowCaption(%s)", caption);
- JNIEnv* env = JNU_GetEnv();
- jstring java_caption = env->NewStringUTF(caption);
- env->CallVoidMethod(_back_ptr, MID_setWindowCaption, java_caption);
- if (env->ExceptionCheck()) {
- warning("Failed to set window caption");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- env->DeleteLocalRef(java_caption);
+ ENTER("%s", caption);
+
+ JNI::setWindowCaption(caption);
}
void OSystem_Android::displayMessageOnOSD(const char *msg) {
- ENTER("displayMessageOnOSD(%s)", msg);
- JNIEnv* env = JNU_GetEnv();
- jstring java_msg = env->NewStringUTF(msg);
- env->CallVoidMethod(_back_ptr, MID_displayMessageOnOSD, java_msg);
- if (env->ExceptionCheck()) {
- warning("Failed to display OSD message");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- env->DeleteLocalRef(java_msg);
+ ENTER("%s", msg);
+
+ JNI::displayMessageOnOSD(msg);
}
void OSystem_Android::showVirtualKeyboard(bool enable) {
- ENTER("showVirtualKeyboard(%d)", enable);
- JNIEnv* env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_showVirtualKeyboard, enable);
- if (env->ExceptionCheck()) {
- error("Error trying to show virtual keyboard");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ ENTER("%d", enable);
+
+ JNI::showVirtualKeyboard(enable);
}
Common::SaveFileManager *OSystem_Android::getSavefileManager() {
@@ -1232,7 +528,8 @@ Common::TimerManager *OSystem_Android::getTimerManager() {
void OSystem_Android::getTimeAndDate(TimeDate &td) const {
struct tm tm;
- const time_t curTime = time(NULL);
+ const time_t curTime = time(0);
+
localtime_r(&curTime, &tm);
td.tm_sec = tm.tm_sec;
td.tm_min = tm.tm_min;
@@ -1247,194 +544,48 @@ FilesystemFactory *OSystem_Android::getFilesystemFactory() {
}
void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
- int priority) {
- s.add("ASSET", _asset_archive, priority, false);
-
- JNIEnv* env = JNU_GetEnv();
-
- jobjectArray array =
- (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getSysArchives);
- if (env->ExceptionCheck()) {
- warning("Error finding system archive path");
- env->ExceptionDescribe();
- env->ExceptionClear();
- return;
- }
+ int priority) {
+ ENTER("");
- jsize size = env->GetArrayLength(array);
- for (jsize i = 0; i < size; ++i) {
- jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
- const char* path = env->GetStringUTFChars(path_obj, NULL);
- if (path != NULL) {
- s.addDirectory(path, path, priority);
- env->ReleaseStringUTFChars(path_obj, path);
- }
- env->DeleteLocalRef(path_obj);
- }
+ JNI::addSysArchivesToSearchSet(s, priority);
}
-void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) {
+void OSystem_Android::logMessage(LogMessageType::Type type,
+ const char *message) {
switch (type) {
case LogMessageType::kDebug:
- BaseBackend::logMessage(type, message);
+ __android_log_write(ANDROID_LOG_DEBUG, android_log_tag, message);
break;
case LogMessageType::kWarning:
- __android_log_write(ANDROID_LOG_WARN, "ScummVM", message);
+ __android_log_write(ANDROID_LOG_WARN, android_log_tag, message);
break;
case LogMessageType::kError:
- // FIXME: From the name it looks like this will also quit the program.
- // This shouldn't do that though.
- __android_log_assert("Fatal error", "ScummVM", "%s", message);
+ __android_log_write(ANDROID_LOG_ERROR, android_log_tag, message);
break;
}
}
-static jint ScummVM_scummVMMain(JNIEnv* env, jobject self, jobjectArray args) {
- OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
-
- const int MAX_NARGS = 32;
- int res = -1;
-
- int argc = env->GetArrayLength(args);
- if (argc > MAX_NARGS) {
- JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
- "too many arguments");
- return 0;
- }
+Common::String OSystem_Android::getSystemLanguage() const {
+ return Common::String::format("%s_%s",
+ getSystemProperty("persist.sys.language").c_str(),
+ getSystemProperty("persist.sys.country").c_str());
+}
- char* argv[MAX_NARGS];
- int nargs; // note use in cleanup loop below
- for (nargs = 0; nargs < argc; ++nargs) {
- jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
- if (arg == NULL) {
- argv[nargs] = NULL;
- } else {
- const char* cstr = env->GetStringUTFChars(arg, NULL);
- argv[nargs] = const_cast<char*>(cstr);
- if (cstr == NULL)
- goto cleanup; // exception already thrown
- }
- env->DeleteLocalRef(arg);
- }
+Common::String OSystem_Android::getSystemProperty(const char *name) const {
+ char value[PROP_VALUE_MAX];
- g_system = cpp_obj;
- assert(g_system);
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "Entering scummvm_main with %d args", argc);
- res = scummvm_main(argc, argv);
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Exiting scummvm_main");
- g_system->quit();
-
-cleanup:
- nargs--;
- for (int i = 0; i < nargs; ++i) {
- if (argv[i] == NULL)
- continue;
- jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
- if (arg == NULL)
- // Exception already thrown
- return res;
- env->ReleaseStringUTFChars(arg, argv[i]);
- env->DeleteLocalRef(arg);
- }
+ int len = __system_property_get(name, value);
- return res;
+ return Common::String(value, len);
}
#ifdef DYNAMIC_MODULES
void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
- OSystem_Android* g_system_android = (OSystem_Android*)g_system;
- g_system_android->addPluginDirectories(dirs);
+ ((OSystem_Android *)g_system)->addPluginDirectories(dirs);
}
#endif
-static void ScummVM_enableZoning(JNIEnv* env, jobject self, jboolean enable) {
- OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
- cpp_obj->enableZoning(enable);
-}
-
-static void ScummVM_setSurfaceSize(JNIEnv* env, jobject self,
- jint width, jint height) {
- OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
- cpp_obj->setSurfaceSize(width, height);
-}
-
-const static JNINativeMethod gMethods[] = {
- { "create", "(Landroid/content/res/AssetManager;)V",
- (void*)ScummVM_create },
- { "nativeDestroy", "()V", (void*)ScummVM_nativeDestroy },
- { "scummVMMain", "([Ljava/lang/String;)I",
- (void*)ScummVM_scummVMMain },
- { "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
- (void*)ScummVM_pushEvent },
- { "audioMixCallback", "([B)V",
- (void*)ScummVM_audioMixCallback },
- { "setConfMan", "(Ljava/lang/String;I)V",
- (void*)ScummVM_setConfManInt },
- { "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
- (void*)ScummVM_setConfManString },
- { "enableZoning", "(Z)V",
- (void*)ScummVM_enableZoning },
- { "setSurfaceSize", "(II)V",
- (void*)ScummVM_setSurfaceSize },
-};
-
-JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM* jvm, void* reserved) {
- cached_jvm = jvm;
-
- JNIEnv* env;
- if (jvm->GetEnv((void**)&env, JNI_VERSION_1_2))
- return JNI_ERR;
-
- jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
- if (cls == NULL)
- return JNI_ERR;
- if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0)
- return JNI_ERR;
-
- FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
- if (FID_ScummVM_nativeScummVM == NULL)
- return JNI_ERR;
-
- jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
- if (event == NULL)
- return JNI_ERR;
- FID_Event_type = env->GetFieldID(event, "type", "I");
- if (FID_Event_type == NULL)
- return JNI_ERR;
- FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
- if (FID_Event_synthetic == NULL)
- return JNI_ERR;
- FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
- if (FID_Event_kbd_keycode == NULL)
- return JNI_ERR;
- FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
- if (FID_Event_kbd_ascii == NULL)
- return JNI_ERR;
- FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
- if (FID_Event_kbd_flags == NULL)
- return JNI_ERR;
- FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
- if (FID_Event_mouse_x == NULL)
- return JNI_ERR;
- FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
- if (FID_Event_mouse_y == NULL)
- return JNI_ERR;
- FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
- if (FID_Event_mouse_relative == NULL)
- return JNI_ERR;
-
- cls = env->FindClass("java/lang/Object");
- if (cls == NULL)
- return JNI_ERR;
- MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
- if (MID_Object_wait == NULL)
- return JNI_ERR;
-
- return JNI_VERSION_1_2;
-}
-
#endif
+
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
new file mode 100644
index 0000000000..6eebdb97d9
--- /dev/null
+++ b/backends/platform/android/android.h
@@ -0,0 +1,307 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef _ANDROID_H_
+#define _ANDROID_H_
+
+#if defined(__ANDROID__)
+
+#include "common/fs.h"
+#include "common/archive.h"
+#include "audio/mixer_intern.h"
+#include "graphics/surface.h"
+#include "backends/base-backend.h"
+#include "backends/plugins/posix/posix-provider.h"
+#include "backends/fs/posix/posix-fs-factory.h"
+
+#include "backends/platform/android/texture.h"
+
+#include <pthread.h>
+
+#include <android/log.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+// toggles start
+//#define ANDROID_DEBUG_ENTER
+//#define ANDROID_DEBUG_GL
+//#define ANDROID_DEBUG_GL_CALLS
+// toggles end
+
+extern const char *android_log_tag;
+
+#define _ANDROID_LOG(prio, fmt, args...) __android_log_print(prio, android_log_tag, fmt, ## args)
+#define LOGD(fmt, args...) _ANDROID_LOG(ANDROID_LOG_DEBUG, fmt, ##args)
+#define LOGI(fmt, args...) _ANDROID_LOG(ANDROID_LOG_INFO, fmt, ##args)
+#define LOGW(fmt, args...) _ANDROID_LOG(ANDROID_LOG_WARN, fmt, ##args)
+#define LOGE(fmt, args...) _ANDROID_LOG(ANDROID_LOG_ERROR, fmt, ##args)
+
+#ifdef ANDROID_DEBUG_ENTER
+#define ENTER(fmt, args...) LOGD("%s(" fmt ")", __FUNCTION__, ##args)
+#else
+#define ENTER(fmt, args...) do { } while (false)
+#endif
+
+#ifdef ANDROID_DEBUG_GL
+extern void checkGlError(const char *expr, const char *file, int line);
+
+#ifdef ANDROID_DEBUG_GL_CALLS
+#define GLCALLLOG(x, before) \
+ do { \
+ if (before) \
+ LOGD("calling '%s' (%s:%d)", x, __FILE__, __LINE__); \
+ else \
+ LOGD("returned from '%s' (%s:%d)", x, __FILE__, __LINE__); \
+ } while (false)
+#else
+#define GLCALLLOG(x, before) do { } while (false)
+#endif
+
+#define GLCALL(x) \
+ do { \
+ GLCALLLOG(#x, true); \
+ (x); \
+ GLCALLLOG(#x, false); \
+ checkGlError(#x, __FILE__, __LINE__); \
+ } while (false)
+
+#define GLTHREADCHECK \
+ do { \
+ assert(pthread_self() == _main_thread); \
+ } while (false)
+
+#else
+#define GLCALL(x) do { (x); } while (false)
+#define GLTHREADCHECK do { } while (false)
+#endif
+
+#ifdef DYNAMIC_MODULES
+class AndroidPluginProvider : public POSIXPluginProvider {
+protected:
+ virtual void addCustomDirectories(Common::FSList &dirs) const;
+};
+#endif
+
+class OSystem_Android : public BaseBackend, public PaletteManager {
+private:
+ // passed from the dark side
+ int _audio_sample_rate;
+ int _audio_buffer_size;
+
+ int _screen_changeid;
+ int _egl_surface_width;
+ int _egl_surface_height;
+ bool _htc_fail;
+
+ bool _force_redraw;
+
+ // Game layer
+ GLESBaseTexture *_game_texture;
+ int _shake_offset;
+ Common::Rect _focus_rect;
+
+ // Overlay layer
+ GLES4444Texture *_overlay_texture;
+ bool _show_overlay;
+
+ // Mouse layer
+ GLESBaseTexture *_mouse_texture;
+ GLESBaseTexture *_mouse_texture_palette;
+ GLES5551Texture *_mouse_texture_rgb;
+ Common::Point _mouse_hotspot;
+ uint32 _mouse_keycolor;
+ int _mouse_targetscale;
+ bool _show_mouse;
+ bool _use_mouse_palette;
+
+ int _graphicsMode;
+ bool _fullscreen;
+ bool _ar_correction;
+
+ pthread_t _main_thread;
+
+ bool _timer_thread_exit;
+ pthread_t _timer_thread;
+ static void *timerThreadFunc(void *arg);
+
+ bool _audio_thread_exit;
+ pthread_t _audio_thread;
+ static void *audioThreadFunc(void *arg);
+
+ bool _enable_zoning;
+ bool _virtkeybd_on;
+
+ Common::SaveFileManager *_savefile;
+ Audio::MixerImpl *_mixer;
+ Common::TimerManager *_timer;
+ FilesystemFactory *_fsFactory;
+ timeval _startTime;
+
+ Common::String getSystemProperty(const char *name) const;
+
+ void initSurface();
+ void deinitSurface();
+ void initViewport();
+
+ void initOverlay();
+
+#ifdef USE_RGB_COLOR
+ Common::String getPixelFormatName(const Graphics::PixelFormat &format) const;
+ void initTexture(GLESBaseTexture **texture, uint width, uint height,
+ const Graphics::PixelFormat *format);
+#endif
+
+ void setupKeymapper();
+ void setCursorPaletteInternal(const byte *colors, uint start, uint num);
+
+public:
+ OSystem_Android(int audio_sample_rate, int audio_buffer_size);
+ virtual ~OSystem_Android();
+
+ virtual void initBackend();
+ void addPluginDirectories(Common::FSList &dirs) const;
+ void enableZoning(bool enable) { _enable_zoning = enable; }
+
+ virtual bool hasFeature(Feature f);
+ virtual void setFeatureState(Feature f, bool enable);
+ virtual bool getFeatureState(Feature f);
+
+ virtual const GraphicsMode *getSupportedGraphicsModes() const;
+ virtual int getDefaultGraphicsMode() const;
+ virtual bool setGraphicsMode(int mode);
+ virtual int getGraphicsMode() const;
+
+#ifdef USE_RGB_COLOR
+ virtual Graphics::PixelFormat getScreenFormat() const;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+#endif
+
+ virtual void initSize(uint width, uint height,
+ const Graphics::PixelFormat *format);
+
+ enum FixupType {
+ kClear = 0, // glClear
+ kClearSwap, // glClear + swapBuffers
+ kClearUpdate // glClear + updateScreen
+ };
+
+ void clearScreen(FixupType type, byte count = 1);
+
+ void updateScreenRect();
+ virtual int getScreenChangeID() const;
+
+ virtual int16 getHeight();
+ virtual int16 getWidth();
+
+ virtual PaletteManager *getPaletteManager() {
+ return this;
+ }
+
+public:
+ void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5);
+
+private:
+ Common::Queue<Common::Event> _event_queue;
+ MutexRef _event_queue_lock;
+
+ Common::Point _touch_pt_down, _touch_pt_scroll, _touch_pt_dt;
+ int _eventScaleX;
+ int _eventScaleY;
+ bool _touchpad_mode;
+ int _touchpad_scale;
+ int _trackball_scale;
+ int _dpad_scale;
+ int _fingersDown;
+
+ void clipMouse(Common::Point &p);
+ void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true);
+ void updateEventScale();
+
+protected:
+ // PaletteManager API
+ virtual void setPalette(const byte *colors, uint start, uint num);
+ virtual void grabPalette(byte *colors, uint start, uint num);
+
+public:
+ virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y,
+ int w, int h);
+ virtual void updateScreen();
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
+ virtual void setShakePos(int shakeOffset);
+ virtual void fillScreen(uint32 col);
+ virtual void setFocusRectangle(const Common::Rect& rect);
+ virtual void clearFocusRectangle();
+
+ virtual void showOverlay();
+ virtual void hideOverlay();
+ virtual void clearOverlay();
+ virtual void grabOverlay(OverlayColor *buf, int pitch);
+ virtual void copyRectToOverlay(const OverlayColor *buf, int pitch,
+ int x, int y, int w, int h);
+ virtual int16 getOverlayHeight();
+ virtual int16 getOverlayWidth();
+ virtual Graphics::PixelFormat getOverlayFormat() const;
+
+ virtual bool showMouse(bool visible);
+
+ virtual void warpMouse(int x, int y);
+ virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX,
+ int hotspotY, uint32 keycolor,
+ int cursorTargetScale,
+ const Graphics::PixelFormat *format);
+ virtual void setCursorPalette(const byte *colors, uint start, uint num);
+ virtual void disableCursorPalette(bool disable);
+
+ virtual bool pollEvent(Common::Event &event);
+ virtual uint32 getMillis();
+ virtual void delayMillis(uint msecs);
+
+ virtual MutexRef createMutex(void);
+ virtual void lockMutex(MutexRef mutex);
+ virtual void unlockMutex(MutexRef mutex);
+ virtual void deleteMutex(MutexRef mutex);
+
+ virtual void quit();
+
+ virtual void setWindowCaption(const char *caption);
+ virtual void displayMessageOnOSD(const char *msg);
+ virtual void showVirtualKeyboard(bool enable);
+
+ virtual Common::SaveFileManager *getSavefileManager();
+ virtual Audio::Mixer *getMixer();
+ virtual void getTimeAndDate(TimeDate &t) const;
+ virtual Common::TimerManager *getTimerManager();
+ virtual FilesystemFactory *getFilesystemFactory();
+ virtual void logMessage(LogMessageType::Type type, const char *message);
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s,
+ int priority = 0);
+ virtual Common::String getSystemLanguage() const;
+};
+
+#endif
+#endif
+
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 95e848e0d9..77fdb139d8 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -1,59 +1,192 @@
# Android specific build targets
-AAPT = aapt
-DX = dx
-APKBUILDER = apkbuilder
-ADB = adb -e
-JAVAC ?= javac
-JAVACFLAGS = -source 1.5 -target 1.5
+# These must be incremented for each market upload
+ANDROID_VERSIONCODE = 6
+ANDROID_PLUGIN_VERSIONCODE = 6
+
+JAVA_FILES = \
+ ScummVM.java \
+ ScummVMEvents.java \
+ ScummVMApplication.java \
+ ScummVMActivity.java \
+ EditableSurfaceView.java \
+ Unpacker.java
+
+JAVA_FILES_PLUGIN = \
+ PluginProvider.java
+
+JAVA_FILES_GEN = \
+ Manifest.java \
+ R.java
+
+PATH_DIST = $(srcdir)/dists/android
+PATH_RESOURCES = $(PATH_DIST)/res
+
+PORT_DISTFILES = $(PATH_DIST)/README.Android
+
+RESOURCES = \
+ $(PATH_RESOURCES)/values/strings.xml \
+ $(PATH_RESOURCES)/layout/main.xml \
+ $(PATH_RESOURCES)/layout/splash.xml \
+ $(PATH_RESOURCES)/drawable/gradient.xml \
+ $(PATH_RESOURCES)/drawable/scummvm.png \
+ $(PATH_RESOURCES)/drawable/scummvm_big.png
+
+PLUGIN_RESOURCES = \
+ $(PATH_RESOURCES)/values/strings.xml \
+ $(PATH_RESOURCES)/drawable/scummvm.png
# FIXME: find/mark plugin entry points and add all this back again:
#LDFLAGS += -Wl,--gc-sections
#CXXFLAGS += -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden
-resources.ap_: $(srcdir)/dists/android/AndroidManifest.xml $(RESOURCES) $(ASSETS) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
- $(INSTALL) -d build.tmp/assets/
- $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) build.tmp/assets/
- $(AAPT) package -f -M $< -S $(srcdir)/dists/android/res -A build.tmp/assets -I $(ANDROID_JAR8) -F $@
-
-build.tmp/%/resources.ap_: build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml build.stage/%/res/drawable/scummvm.png $(ANDROID_JAR8)
- $(AAPT) package -f -M $< -S build.stage/$*/res -I $(ANDROID_JAR8) -F $@
-
-scummvm.apk: build.tmp/libscummvm.so resources.ap_ classes.dex
- # Package installer won't delete old libscummvm.so on upgrade so
- # replace it with a zero size file
- $(INSTALL) -d build.stage/common/lib/armeabi
- touch build.stage/common/lib/armeabi/libscummvm.so
- # We now handle the library unpacking ourselves from mylib/
- $(INSTALL) -d build.stage/common/mylib/armeabi
- $(INSTALL) -c -m 644 build.tmp/libscummvm.so build.stage/common/mylib/armeabi/
- $(STRIP) build.stage/common/mylib/armeabi/libscummvm.so
- # "-nf lib/armeabi/libscummvm.so" builds bogus paths?
- $(APKBUILDER) $@ -z resources.ap_ -f classes.dex -rf build.stage/common || { $(RM) $@; exit 1; }
-
-scummvm-engine-%.apk: plugins/lib%.so build.tmp/%/resources.ap_ build.tmp/plugins/classes.dex
- $(INSTALL) -d build.stage/$*/apk/mylib/armeabi/
- $(INSTALL) -c -m 644 plugins/lib$*.so build.stage/$*/apk/mylib/armeabi/
- $(STRIP) build.stage/$*/apk/mylib/armeabi/lib$*.so
- $(APKBUILDER) $@ -z build.tmp/$*/resources.ap_ -f build.tmp/plugins/classes.dex -rf build.stage/$*/apk || { $(RM) $@; exit 1; }
+AAPT = $(ANDROID_SDK)/platform-tools/aapt
+ADB = $(ANDROID_SDK)/platform-tools/adb
+DX = $(ANDROID_SDK)/platform-tools/dx
+APKBUILDER = $(ANDROID_SDK)/tools/apkbuilder
+JAVAC ?= javac
+JAVACFLAGS = -source 1.5 -target 1.5
+
+# This is a bit silly. I want to compile against the 1.6 android.jar,
+# to make the compiler check that I don't use something that requires
+# a newer Android. However, in order to use android:installLocation,
+# we need to give aapt a version >=8 android.jar - even though the
+# result will work ok on 1.5+.
+ANDROID_JAR = $(ANDROID_SDK)/platforms/android-4/android.jar
+ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
+
+PATH_BUILD = build.tmp
+PATH_BUILD_ASSETS = $(PATH_BUILD)/assets
+PATH_BUILD_CLASSES_MAIN_TOP = $(PATH_BUILD)/classes.main
+PATH_BUILD_CLASSES_PLUGIN_TOP = $(PATH_BUILD)/classes.plugin
+
+PATH_STAGE_PREFIX = build.stage
+PATH_STAGE_MAIN = $(PATH_STAGE_PREFIX).main
+
+PATH_REL = org/inodes/gus/scummvm
+PATH_SRC_TOP = $(srcdir)/backends/platform/android
+PATH_SRC = $(PATH_SRC_TOP)/$(PATH_REL)
+
+PATH_GEN_TOP = $(PATH_BUILD)/java
+PATH_GEN = $(PATH_GEN_TOP)/$(PATH_REL)
+PATH_CLASSES_MAIN = $(PATH_BUILD_CLASSES_MAIN_TOP)/$(PATH_REL)
+PATH_CLASSES_PLUGIN = $(PATH_BUILD_CLASSES_PLUGIN_TOP)/$(PATH_REL)
+
+FILE_MANIFEST_SRC = $(srcdir)/dists/android/AndroidManifest.xml
+FILE_MANIFEST = $(PATH_BUILD)/AndroidManifest.xml
+FILE_DEX = $(PATH_BUILD)/classes.dex
+FILE_DEX_PLUGIN = $(PATH_BUILD)/plugins/classes.dex
+FILE_RESOURCES = resources.ap_
+FILE_RESOURCES_MAIN = $(PATH_BUILD)/$(FILE_RESOURCES)
+
+SRC_GEN = $(addprefix $(PATH_GEN)/, $(JAVA_FILES_GEN))
+
+CLASSES_MAIN = $(addprefix $(PATH_CLASSES_MAIN)/, $(JAVA_FILES:%.java=%.class))
+CLASSES_GEN = $(addprefix $(PATH_CLASSES_MAIN)/, $(JAVA_FILES_GEN:%.java=%.class))
+CLASSES_PLUGIN = $(addprefix $(PATH_CLASSES_PLUGIN)/, $(JAVA_FILES_PLUGIN:%.java=%.class))
+
+APK_MAIN = scummvm.apk
+APK_PLUGINS = $(patsubst plugins/lib%.so, scummvm-engine-%.apk, $(PLUGINS))
+
+$(FILE_MANIFEST): $(FILE_MANIFEST_SRC)
+ @$(MKDIR) -p $(@D)
+ sed "s/@ANDROID_VERSIONCODE@/$(ANDROID_VERSIONCODE)/" < $< > $@
+
+$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
+ @$(MKDIR) -p $(PATH_GEN_TOP)
+ $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR8)
+
+$(PATH_CLASSES_MAIN)/%.class: $(PATH_GEN)/%.java $(SRC_GEN)
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(PATH_SRC_TOP) -d $(PATH_BUILD_CLASSES_MAIN_TOP) -bootclasspath $(ANDROID_JAR) $<
+
+$(PATH_CLASSES_MAIN)/%.class: $(PATH_SRC)/%.java $(SRC_GEN)
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(PATH_SRC_TOP):$(PATH_GEN_TOP) -d $(PATH_BUILD_CLASSES_MAIN_TOP) -bootclasspath $(ANDROID_JAR) $<
+
+$(PATH_CLASSES_PLUGIN)/%.class: $(PATH_SRC)/%.java
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(PATH_SRC_TOP) -d $(PATH_BUILD_CLASSES_PLUGIN_TOP) -bootclasspath $(ANDROID_JAR) $<
+
+$(FILE_DEX): $(CLASSES_MAIN) $(CLASSES_GEN)
+ $(DX) --dex --output=$@ $(PATH_BUILD_CLASSES_MAIN_TOP)
+
+$(FILE_DEX_PLUGIN): $(CLASSES_PLUGIN)
+ @$(MKDIR) -p $(@D)
+ $(DX) --dex --output=$@ $(PATH_BUILD_CLASSES_PLUGIN_TOP)
+
+$(PATH_BUILD)/%/AndroidManifest.xml: $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $(PATH_DIST)/plugin-manifest.xml
+ @$(MKDIR) -p $(@D)
+ $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $* $(PATH_DIST)/plugin-manifest.xml $(ANDROID_PLUGIN_VERSIONCODE) $@
+
+$(PATH_STAGE_PREFIX).%/res/values/strings.xml: $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $(PATH_DIST)/plugin-manifest.xml
+ @$(MKDIR) -p $(@D)
+ $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $* $(PATH_DIST)/plugin-strings.xml $(ANDROID_PLUGIN_VERSIONCODE) $@
+
+$(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png: $(PATH_RESOURCES)/drawable/scummvm.png
+ @$(MKDIR) -p $(@D)
+ $(CP) $< $@
+$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(PATH_BUILD_ASSETS)/
+ $(AAPT) package -f -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR8) -F $@
+
+$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png plugins/lib%.so $(ANDROID_JAR8)
+ $(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR8) -F $@
+
+# Package installer won't delete old libscummvm.so on upgrade so
+# replace it with a zero size file
+$(APK_MAIN): $(EXECUTABLE) $(FILE_RESOURCES_MAIN) $(FILE_DEX)
+ $(INSTALL) -d $(PATH_STAGE_MAIN)/common/lib/armeabi
+ touch $(PATH_STAGE_MAIN)/common/lib/armeabi/libscummvm.so
+ $(INSTALL) -d $(PATH_STAGE_MAIN)/common/mylib/armeabi
+ $(INSTALL) -c -m 644 libscummvm.so $(PATH_STAGE_MAIN)/common/mylib/armeabi/
+ $(STRIP) $(PATH_STAGE_MAIN)/common/mylib/armeabi/libscummvm.so
+ $(APKBUILDER) $@ -z $(FILE_RESOURCES_MAIN) -f $(FILE_DEX) -rf $(PATH_STAGE_MAIN)/common || { $(RM) $@; exit 1; }
+
+scummvm-engine-%.apk: plugins/lib%.so $(PATH_BUILD)/%/$(FILE_RESOURCES) $(FILE_DEX_PLUGIN)
+ $(INSTALL) -d $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/
+ $(INSTALL) -c -m 644 plugins/lib$*.so $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/
+ $(STRIP) $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/lib$*.so
+ $(APKBUILDER) $@ -z $(PATH_BUILD)/$*/$(FILE_RESOURCES) -f $(FILE_DEX_PLUGIN) -rf $(PATH_STAGE_PREFIX).$*/apk || { $(RM) $@; exit 1; }
+
+all: $(APK_MAIN) $(APK_PLUGINS)
+
+clean: androidclean
+
+androidclean:
+ @$(RM) -rf $(PATH_BUILD) $(PATH_STAGE_PREFIX).* *.apk release
+
+# remove debugging signature
release/%.apk: %.apk
@$(MKDIR) -p $(@D)
@$(RM) $@
$(CP) $< $@.tmp
- # remove debugging signature
zip -d $@.tmp META-INF/\*
jarsigner $(JARSIGNER_FLAGS) $@.tmp release
zipalign 4 $@.tmp $@
$(RM) $@.tmp
-androidrelease: release/scummvm.apk $(patsubst plugins/lib%.so,release/scummvm-engine-%.apk,$(PLUGINS))
+androidrelease: $(addprefix release/, $(APK_MAIN) $(APK_PLUGINS))
+
+androidtestmain: $(APK_MAIN)
+ $(ADB) install -r $(APK_MAIN)
+ $(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker
-androidtest: scummvm.apk scummvm-engine-scumm.apk scummvm-engine-kyra.apk
+androidtest: $(APK_MAIN) $(APK_PLUGINS)
@set -e; for apk in $^; do \
- echo $(ADB) install -r $$apk; \
- $(ADB) install -r $$apk; \
+ $(ADB) install -r $$apk; \
done
$(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker
+# used by buildbot!
+androiddistdebug: all
+ $(MKDIR) debug
+ $(CP) $(APK_MAIN) $(APK_PLUGINS) debug/
+ for i in $(DIST_FILES_DOCS) $(PORT_DISTFILES); do \
+ sed 's/$$/\r/' < $$i > debug/`basename $$i`.txt; \
+ done
+
.PHONY: androidrelease androidtest
+
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index 20c6a653c0..8e95029894 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -23,7 +23,7 @@
*
*/
-#if defined(ANDROID)
+#if defined(__ANDROID__)
#include <jni.h>
@@ -36,10 +36,9 @@
#include "common/archive.h"
#include "common/debug.h"
+#include "backends/platform/android/jni.h"
#include "backends/platform/android/asset-archive.h"
-extern JNIEnv* JNU_GetEnv();
-
// Must match android.content.res.AssetManager.ACCESS_*
const jint ACCESS_UNKNOWN = 0;
const jint ACCESS_RANDOM = 1;
@@ -47,23 +46,43 @@ const jint ACCESS_RANDOM = 1;
// This might be useful to someone else. Assumes markSupported() == true.
class JavaInputStream : public Common::SeekableReadStream {
public:
- JavaInputStream(JNIEnv* env, jobject is);
+ JavaInputStream(JNIEnv *env, jobject is);
virtual ~JavaInputStream();
- virtual bool eos() const { return _eos; }
- virtual bool err() const { return _err; }
- virtual void clearErr() { _eos = _err = false; }
+
+ virtual bool eos() const {
+ return _eos;
+ }
+
+ virtual bool err() const {
+ return _err;
+ }
+
+ virtual void clearErr() {
+ _eos = _err = false;
+ }
+
virtual uint32 read(void *dataPtr, uint32 dataSize);
- virtual int32 pos() const { return _pos; }
- virtual int32 size() const { return _len; }
+
+ virtual int32 pos() const {
+ return _pos;
+ }
+
+ virtual int32 size() const {
+ return _len;
+ }
+
virtual bool seek(int32 offset, int whence = SEEK_SET);
+
private:
- void close(JNIEnv* env);
+ void close(JNIEnv *env);
+
jmethodID MID_mark;
jmethodID MID_available;
jmethodID MID_close;
jmethodID MID_read;
jmethodID MID_reset;
jmethodID MID_skip;
+
jobject _input_stream;
jsize _buflen;
jbyteArray _buf;
@@ -73,12 +92,14 @@ private:
bool _err;
};
-JavaInputStream::JavaInputStream(JNIEnv* env, jobject is) :
- _eos(false), _err(false), _pos(0)
+JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) :
+ _eos(false),
+ _err(false),
+ _pos(0)
{
_input_stream = env->NewGlobalRef(is);
_buflen = 8192;
- _buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
+ _buf = (jbyteArray)env->NewGlobalRef(env->NewByteArray(_buflen));
jclass cls = env->GetObjectClass(_input_stream);
MID_mark = env->GetMethodID(cls, "mark", "(I)V");
@@ -97,53 +118,61 @@ JavaInputStream::JavaInputStream(JNIEnv* env, jobject is) :
// Mark start of stream, so we can reset back to it.
// readlimit is set to something bigger than anything we might
// want to seek within.
- env->CallVoidMethod(_input_stream, MID_mark, 10*1024*1024);
+ env->CallVoidMethod(_input_stream, MID_mark, 10 * 1024 * 1024);
_len = env->CallIntMethod(_input_stream, MID_available);
}
JavaInputStream::~JavaInputStream() {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
close(env);
+
env->DeleteGlobalRef(_buf);
env->DeleteGlobalRef(_input_stream);
}
-void JavaInputStream::close(JNIEnv* env) {
+void JavaInputStream::close(JNIEnv *env) {
env->CallVoidMethod(_input_stream, MID_close);
+
if (env->ExceptionCheck())
env->ExceptionClear();
}
uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
- if (_buflen < dataSize) {
+ if (_buflen < jint(dataSize)) {
_buflen = dataSize;
+
env->DeleteGlobalRef(_buf);
_buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
}
jint ret = env->CallIntMethod(_input_stream, MID_read, _buf, 0, dataSize);
+
if (env->ExceptionCheck()) {
warning("Exception during JavaInputStream::read(%p, %d)",
dataPtr, dataSize);
+
env->ExceptionDescribe();
env->ExceptionClear();
+
_err = true;
ret = -1;
} else if (ret == -1) {
_eos = true;
ret = 0;
} else {
- env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte*>(dataPtr));
+ env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte *>(dataPtr));
_pos += ret;
}
+
return ret;
}
bool JavaInputStream::seek(int32 offset, int whence) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
uint32 newpos;
+
switch (whence) {
case SEEK_SET:
newpos = offset;
@@ -165,37 +194,47 @@ bool JavaInputStream::seek(int32 offset, int whence) {
} else {
// Can't skip backwards, so jump back to start and skip from there.
env->CallVoidMethod(_input_stream, MID_reset);
+
if (env->ExceptionCheck()) {
warning("Failed to rewind to start of asset stream");
+
env->ExceptionDescribe();
env->ExceptionClear();
+
return false;
}
+
_pos = 0;
skip_bytes = newpos;
}
while (skip_bytes > 0) {
jlong ret = env->CallLongMethod(_input_stream, MID_skip, skip_bytes);
+
if (env->ExceptionCheck()) {
warning("Failed to skip %ld bytes into asset stream",
static_cast<long>(skip_bytes));
+
env->ExceptionDescribe();
env->ExceptionClear();
+
return false;
} else if (ret == 0) {
warning("InputStream->skip(%ld) didn't skip any bytes. Aborting seek.",
static_cast<long>(skip_bytes));
- return false; // No point looping forever...
+
+ // No point looping forever...
+ return false;
}
+
_pos += ret;
skip_bytes -= ret;
}
+
_eos = false;
return true;
}
-
// Must match android.content.res.AssetFileDescriptor.UNKNOWN_LENGTH
const jlong UNKNOWN_LENGTH = -1;
@@ -203,17 +242,36 @@ const jlong UNKNOWN_LENGTH = -1;
// worth optimising for.
class AssetFdReadStream : public Common::SeekableReadStream {
public:
- AssetFdReadStream(JNIEnv* env, jobject assetfd);
+ AssetFdReadStream(JNIEnv *env, jobject assetfd);
virtual ~AssetFdReadStream();
- virtual bool eos() const { return _eos; }
- virtual bool err() const { return _err; }
- virtual void clearErr() { _eos = _err = false; }
+
+ virtual bool eos() const {
+ return _eos;
+ }
+
+ virtual bool err() const {
+ return _err;
+ }
+
+ virtual void clearErr() {
+ _eos = _err = false;
+ }
+
virtual uint32 read(void *dataPtr, uint32 dataSize);
- virtual int32 pos() const { return _pos; }
- virtual int32 size() const { return _declared_len; }
+
+ virtual int32 pos() const {
+ return _pos;
+ }
+
+ virtual int32 size() const {
+ return _declared_len;
+ }
+
virtual bool seek(int32 offset, int whence = SEEK_SET);
+
private:
- void close(JNIEnv* env);
+ void close(JNIEnv *env);
+
int _fd;
jmethodID MID_close;
jobject _assetfd;
@@ -224,8 +282,10 @@ private:
bool _err;
};
-AssetFdReadStream::AssetFdReadStream(JNIEnv* env, jobject assetfd) :
- _eos(false), _err(false), _pos(0)
+AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
+ _eos(false),
+ _err(false),
+ _pos(0)
{
_assetfd = env->NewGlobalRef(assetfd);
@@ -244,21 +304,26 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv* env, jobject assetfd) :
_declared_len = env->CallLongMethod(_assetfd, MID_getDeclaredLength);
jmethodID MID_getFileDescriptor =
- env->GetMethodID(cls, "getFileDescriptor", "()Ljava/io/FileDescriptor;");
+ env->GetMethodID(cls, "getFileDescriptor",
+ "()Ljava/io/FileDescriptor;");
assert(MID_getFileDescriptor);
jobject javafd = env->CallObjectMethod(_assetfd, MID_getFileDescriptor);
assert(javafd);
+
jclass fd_cls = env->GetObjectClass(javafd);
jfieldID FID_descriptor = env->GetFieldID(fd_cls, "descriptor", "I");
assert(FID_descriptor);
+
_fd = env->GetIntField(javafd, FID_descriptor);
}
AssetFdReadStream::~AssetFdReadStream() {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
env->CallVoidMethod(_assetfd, MID_close);
+
if (env->ExceptionCheck())
env->ExceptionClear();
+
env->DeleteGlobalRef(_assetfd);
}
@@ -268,13 +333,16 @@ uint32 AssetFdReadStream::read(void *dataPtr, uint32 dataSize) {
if (dataSize > cap)
dataSize = cap;
}
+
int ret = ::read(_fd, dataPtr, dataSize);
+
if (ret == 0)
_eos = true;
else if (ret == -1)
_err = true;
else
_pos += ret;
+
return ret;
}
@@ -282,42 +350,49 @@ bool AssetFdReadStream::seek(int32 offset, int whence) {
if (whence == SEEK_SET) {
if (_declared_len != UNKNOWN_LENGTH && offset > _declared_len)
offset = _declared_len;
+
offset += _start_off;
} else if (whence == SEEK_END && _declared_len != UNKNOWN_LENGTH) {
whence = SEEK_SET;
offset = _start_off + _declared_len + offset;
}
+
int ret = lseek(_fd, offset, whence);
+
if (ret == -1)
return false;
+
_pos = ret - _start_off;
_eos = false;
+
return true;
}
AndroidAssetArchive::AndroidAssetArchive(jobject am) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
_am = env->NewGlobalRef(am);
jclass cls = env->GetObjectClass(_am);
MID_open = env->GetMethodID(cls, "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
assert(MID_open);
- MID_openFd = env->GetMethodID(cls, "openFd",
- "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
+
+ MID_openFd = env->GetMethodID(cls, "openFd", "(Ljava/lang/String;)"
+ "Landroid/content/res/AssetFileDescriptor;");
assert(MID_openFd);
+
MID_list = env->GetMethodID(cls, "list",
"(Ljava/lang/String;)[Ljava/lang/String;");
assert(MID_list);
}
AndroidAssetArchive::~AndroidAssetArchive() {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
env->DeleteGlobalRef(_am);
}
bool AndroidAssetArchive::hasFile(const Common::String &name) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
jstring path = env->NewStringUTF(name.c_str());
jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN);
if (env->ExceptionCheck()) {
@@ -326,15 +401,18 @@ bool AndroidAssetArchive::hasFile(const Common::String &name) {
//env->ExceptionDescribe();
env->ExceptionClear();
env->DeleteLocalRef(path);
+
return false;
}
+
env->DeleteLocalRef(result);
env->DeleteLocalRef(path);
+
return true;
}
int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
Common::List<Common::String> dirlist;
dirlist.push_back("");
@@ -344,30 +422,41 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
dirlist.pop_back();
jstring jpath = env->NewStringUTF(dir.c_str());
- jobjectArray jpathlist = static_cast<jobjectArray>(env->CallObjectMethod(_am, MID_list, jpath));
+ jobjectArray jpathlist =
+ (jobjectArray)env->CallObjectMethod(_am, MID_list, jpath);
+
if (env->ExceptionCheck()) {
warning("Error while calling AssetManager->list(%s). Ignoring.",
dir.c_str());
env->ExceptionDescribe();
env->ExceptionClear();
- continue; // May as well keep going ...
+
+ // May as well keep going ...
+ continue;
}
+
env->DeleteLocalRef(jpath);
for (jsize i = 0; i < env->GetArrayLength(jpathlist); ++i) {
jstring elem = (jstring)env->GetObjectArrayElement(jpathlist, i);
- const char* p = env->GetStringUTFChars(elem, NULL);
- Common::String thispath = dir;
- if (!thispath.empty())
- thispath += "/";
- thispath += p;
-
- // Assume files have a . in them, and directories don't
- if (strchr(p, '.')) {
- member_list.push_back(getMember(thispath));
- ++count;
- } else
- dirlist.push_back(thispath);
+ const char *p = env->GetStringUTFChars(elem, 0);
+
+ if (strlen(p)) {
+ Common::String thispath = dir;
+
+ if (!thispath.empty())
+ thispath += "/";
+
+ thispath += p;
+
+ // Assume files have a . in them, and directories don't
+ if (strchr(p, '.')) {
+ member_list.push_back(getMember(thispath));
+ ++count;
+ } else {
+ dirlist.push_back(thispath);
+ }
+ }
env->ReleaseStringUTFChars(elem, p);
env->DeleteLocalRef(elem);
@@ -384,14 +473,15 @@ Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &na
}
Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
jstring jpath = env->NewStringUTF(path.c_str());
// Try openFd() first ...
jobject afd = env->CallObjectMethod(_am, MID_openFd, jpath);
+
if (env->ExceptionCheck())
env->ExceptionClear();
- else if (afd != NULL) {
+ else if (afd != 0) {
// success :)
env->DeleteLocalRef(jpath);
return new AssetFdReadStream(env, afd);
@@ -399,13 +489,15 @@ Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const
// ... and fallback to normal open() if that doesn't work
jobject is = env->CallObjectMethod(_am, MID_open, jpath, ACCESS_RANDOM);
+
if (env->ExceptionCheck()) {
// Assume FileNotFoundException
//warning("Error opening %s", path.c_str());
//env->ExceptionDescribe();
env->ExceptionClear();
env->DeleteLocalRef(jpath);
- return NULL;
+
+ return 0;
}
return new JavaInputStream(env, is);
diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h
index b3f6993c50..6ec86e4cd0 100644
--- a/backends/platform/android/asset-archive.h
+++ b/backends/platform/android/asset-archive.h
@@ -23,7 +23,10 @@
*
*/
-#if defined(ANDROID)
+#ifndef _ANDROID_ASSET_H_
+#define _ANDROID_ASSET_H_
+
+#if defined(__ANDROID__)
#include <jni.h>
@@ -51,3 +54,5 @@ private:
};
#endif
+#endif
+
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
new file mode 100644
index 0000000000..09466b4d2f
--- /dev/null
+++ b/backends/platform/android/events.cpp
@@ -0,0 +1,805 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "common/events.h"
+
+#include "backends/platform/android/android.h"
+#include "backends/platform/android/jni.h"
+
+// $ANDROID_NDK/platforms/android-9/arch-arm/usr/include/android/keycodes.h
+// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=libs/ui/Input.cpp
+// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/KeyEvent.java
+
+// event type
+enum {
+ JE_SYS_KEY = 0,
+ JE_KEY = 1,
+ JE_DPAD = 2,
+ JE_DOWN = 3,
+ JE_SCROLL = 4,
+ JE_TAP = 5,
+ JE_DOUBLE_TAP = 6,
+ JE_MULTI = 7,
+ JE_BALL = 8,
+ JE_QUIT = 0x1000
+};
+
+// action type
+enum {
+ JACTION_DOWN = 0,
+ JACTION_UP = 1,
+ JACTION_MULTIPLE = 2,
+ JACTION_POINTER_DOWN = 5,
+ JACTION_POINTER_UP = 6
+};
+
+// system keys
+enum {
+ JKEYCODE_SOFT_RIGHT = 2,
+ JKEYCODE_HOME = 3,
+ JKEYCODE_BACK = 4,
+ JKEYCODE_CALL = 5,
+ JKEYCODE_ENDCALL = 6,
+ JKEYCODE_VOLUME_UP = 24,
+ JKEYCODE_VOLUME_DOWN = 25,
+ JKEYCODE_POWER = 26,
+ JKEYCODE_CAMERA = 27,
+ JKEYCODE_HEADSETHOOK = 79,
+ JKEYCODE_FOCUS = 80,
+ JKEYCODE_MENU = 82,
+ JKEYCODE_SEARCH = 84,
+ JKEYCODE_MUTE = 91,
+ JKEYCODE_MEDIA_PLAY_PAUSE = 85,
+ JKEYCODE_MEDIA_STOP = 86,
+ JKEYCODE_MEDIA_NEXT = 87,
+ JKEYCODE_MEDIA_PREVIOUS = 88,
+ JKEYCODE_MEDIA_REWIND = 89,
+ JKEYCODE_MEDIA_FAST_FORWARD = 90
+};
+
+// five-way navigation control
+enum {
+ JKEYCODE_DPAD_UP = 19,
+ JKEYCODE_DPAD_DOWN = 20,
+ JKEYCODE_DPAD_LEFT = 21,
+ JKEYCODE_DPAD_RIGHT = 22,
+ JKEYCODE_DPAD_CENTER = 23
+};
+
+// meta modifier
+enum {
+ JMETA_SHIFT = 0x01,
+ JMETA_ALT = 0x02,
+ JMETA_SYM = 0x04,
+ JMETA_CTRL = 0x1000
+};
+
+// map android key codes to our kbd codes
+static const Common::KeyCode jkeymap[] = {
+ Common::KEYCODE_INVALID, // KEYCODE_UNKNOWN
+ Common::KEYCODE_INVALID, // KEYCODE_SOFT_LEFT
+ Common::KEYCODE_INVALID, // KEYCODE_SOFT_RIGHT
+ Common::KEYCODE_INVALID, // KEYCODE_HOME
+ Common::KEYCODE_INVALID, // KEYCODE_BACK
+ Common::KEYCODE_INVALID, // KEYCODE_CALL
+ Common::KEYCODE_INVALID, // KEYCODE_ENDCALL
+ Common::KEYCODE_0, // KEYCODE_0
+ Common::KEYCODE_1, // KEYCODE_1
+ Common::KEYCODE_2, // KEYCODE_2
+ Common::KEYCODE_3, // KEYCODE_3
+ Common::KEYCODE_4, // KEYCODE_4
+ Common::KEYCODE_5, // KEYCODE_5
+ Common::KEYCODE_6, // KEYCODE_6
+ Common::KEYCODE_7, // KEYCODE_7
+ Common::KEYCODE_8, // KEYCODE_8
+ Common::KEYCODE_9, // KEYCODE_9
+ Common::KEYCODE_ASTERISK, // KEYCODE_STAR
+ Common::KEYCODE_HASH, // KEYCODE_POUND
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_UP
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_DOWN
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_LEFT
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_RIGHT
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_CENTER
+ Common::KEYCODE_INVALID, // KEYCODE_VOLUME_UP
+ Common::KEYCODE_INVALID, // KEYCODE_VOLUME_DOWN
+ Common::KEYCODE_INVALID, // KEYCODE_POWER
+ Common::KEYCODE_INVALID, // KEYCODE_CAMERA
+ Common::KEYCODE_INVALID, // KEYCODE_CLEAR
+ Common::KEYCODE_a, // KEYCODE_A
+ Common::KEYCODE_b, // KEYCODE_B
+ Common::KEYCODE_c, // KEYCODE_C
+ Common::KEYCODE_d, // KEYCODE_D
+ Common::KEYCODE_e, // KEYCODE_E
+ Common::KEYCODE_f, // KEYCODE_F
+ Common::KEYCODE_g, // KEYCODE_G
+ Common::KEYCODE_h, // KEYCODE_H
+ Common::KEYCODE_i, // KEYCODE_I
+ Common::KEYCODE_j, // KEYCODE_J
+ Common::KEYCODE_k, // KEYCODE_K
+ Common::KEYCODE_l, // KEYCODE_L
+ Common::KEYCODE_m, // KEYCODE_M
+ Common::KEYCODE_n, // KEYCODE_N
+ Common::KEYCODE_o, // KEYCODE_O
+ Common::KEYCODE_p, // KEYCODE_P
+ Common::KEYCODE_q, // KEYCODE_Q
+ Common::KEYCODE_r, // KEYCODE_R
+ Common::KEYCODE_s, // KEYCODE_S
+ Common::KEYCODE_t, // KEYCODE_T
+ Common::KEYCODE_u, // KEYCODE_U
+ Common::KEYCODE_v, // KEYCODE_V
+ Common::KEYCODE_w, // KEYCODE_W
+ Common::KEYCODE_x, // KEYCODE_X
+ Common::KEYCODE_y, // KEYCODE_Y
+ Common::KEYCODE_z, // KEYCODE_Z
+ Common::KEYCODE_COMMA, // KEYCODE_COMMA
+ Common::KEYCODE_PERIOD, // KEYCODE_PERIOD
+ Common::KEYCODE_LALT, // KEYCODE_ALT_LEFT
+ Common::KEYCODE_RALT, // KEYCODE_ALT_RIGHT
+ Common::KEYCODE_LSHIFT, // KEYCODE_SHIFT_LEFT
+ Common::KEYCODE_RSHIFT, // KEYCODE_SHIFT_RIGHT
+ Common::KEYCODE_TAB, // KEYCODE_TAB
+ Common::KEYCODE_SPACE, // KEYCODE_SPACE
+ Common::KEYCODE_LCTRL, // KEYCODE_SYM
+ Common::KEYCODE_INVALID, // KEYCODE_EXPLORER
+ Common::KEYCODE_INVALID, // KEYCODE_ENVELOPE
+ Common::KEYCODE_RETURN, // KEYCODE_ENTER
+ Common::KEYCODE_BACKSPACE, // KEYCODE_DEL
+ Common::KEYCODE_BACKQUOTE, // KEYCODE_GRAVE
+ Common::KEYCODE_MINUS, // KEYCODE_MINUS
+ Common::KEYCODE_EQUALS, // KEYCODE_EQUALS
+ Common::KEYCODE_LEFTPAREN, // KEYCODE_LEFT_BRACKET
+ Common::KEYCODE_RIGHTPAREN, // KEYCODE_RIGHT_BRACKET
+ Common::KEYCODE_BACKSLASH, // KEYCODE_BACKSLASH
+ Common::KEYCODE_SEMICOLON, // KEYCODE_SEMICOLON
+ Common::KEYCODE_QUOTE, // KEYCODE_APOSTROPHE
+ Common::KEYCODE_SLASH, // KEYCODE_SLASH
+ Common::KEYCODE_AT, // KEYCODE_AT
+ Common::KEYCODE_INVALID, // KEYCODE_NUM
+ Common::KEYCODE_INVALID, // KEYCODE_HEADSETHOOK
+ Common::KEYCODE_INVALID, // KEYCODE_FOCUS
+ Common::KEYCODE_PLUS, // KEYCODE_PLUS
+ Common::KEYCODE_INVALID, // KEYCODE_MENU
+ Common::KEYCODE_INVALID, // KEYCODE_NOTIFICATION
+ Common::KEYCODE_INVALID, // KEYCODE_SEARCH
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PLAY_PAUSE
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_STOP
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_NEXT
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PREVIOUS
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_REWIND
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_FAST_FORWARD
+ Common::KEYCODE_INVALID, // KEYCODE_MUTE
+ Common::KEYCODE_PAGEUP, // KEYCODE_PAGE_UP
+ Common::KEYCODE_PAGEDOWN // KEYCODE_PAGE_DOWN
+};
+
+// floating point. use sparingly
+template <class T>
+static inline T scalef(T in, float numerator, float denominator) {
+ return static_cast<float>(in) * numerator / denominator;
+}
+
+void OSystem_Android::setupKeymapper() {
+#ifdef ENABLE_KEYMAPPER
+ using namespace Common;
+
+ Keymapper *mapper = getEventManager()->getKeymapper();
+
+ HardwareKeySet *keySet = new HardwareKeySet();
+
+ keySet->addHardwareKey(
+ new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)",
+ kTriggerLeftKeyType,
+ kVirtualKeyboardActionType));
+
+ mapper->registerHardwareKeySet(keySet);
+
+ Keymap *globalMap = new Keymap("global");
+ Action *act;
+
+ act = new Action(globalMap, "VIRT", "Display keyboard",
+ kVirtualKeyboardActionType);
+ act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
+
+ mapper->addGlobalKeymap(globalMap);
+
+ mapper->pushKeymap("global");
+#endif
+}
+
+void OSystem_Android::warpMouse(int x, int y) {
+ ENTER("%d, %d", x, y);
+
+ Common::Event e;
+
+ e.type = Common::EVENT_MOUSEMOVE;
+ e.mouse.x = x;
+ e.mouse.y = y;
+
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+}
+
+void OSystem_Android::clipMouse(Common::Point &p) {
+ const GLESBaseTexture *tex;
+
+ if (_show_overlay)
+ tex = _overlay_texture;
+ else
+ tex = _game_texture;
+
+ p.x = CLIP(p.x, int16(0), int16(tex->width() - 1));
+ p.y = CLIP(p.y, int16(0), int16(tex->height() - 1));
+}
+
+void OSystem_Android::scaleMouse(Common::Point &p, int x, int y,
+ bool deductDrawRect) {
+ const GLESBaseTexture *tex;
+
+ if (_show_overlay)
+ tex = _overlay_texture;
+ else
+ tex = _game_texture;
+
+ const Common::Rect &r = tex->getDrawRect();
+
+ if (_touchpad_mode) {
+ x = x * 100 / _touchpad_scale;
+ y = y * 100 / _touchpad_scale;
+ }
+
+ if (deductDrawRect) {
+ x -= r.left;
+ y -= r.top;
+ }
+
+ p.x = scalef(x, tex->width(), r.width());
+ p.y = scalef(y, tex->height(), r.height());
+}
+
+void OSystem_Android::updateEventScale() {
+ const GLESBaseTexture *tex;
+
+ if (_show_overlay)
+ tex = _overlay_texture;
+ else
+ tex = _game_texture;
+
+ _eventScaleY = 100 * 480 / tex->height();
+ _eventScaleX = 100 * 640 / tex->width();
+}
+
+void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
+ int arg4, int arg5) {
+ Common::Event e;
+
+ switch (type) {
+ case JE_SYS_KEY:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_KEYDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_KEYUP;
+ break;
+ default:
+ LOGE("unhandled jaction on system key: %d", arg1);
+ return;
+ }
+
+ switch (arg2) {
+ case JKEYCODE_BACK:
+ e.kbd.keycode = Common::KEYCODE_ESCAPE;
+ e.kbd.ascii = Common::ASCII_ESCAPE;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ // special case. we'll only get it's up event
+ case JKEYCODE_MENU:
+ e.type = Common::EVENT_MAINMENU;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JKEYCODE_CAMERA:
+ case JKEYCODE_SEARCH:
+ if (arg1 == JACTION_DOWN)
+ e.type = Common::EVENT_RBUTTONDOWN;
+ else
+ e.type = Common::EVENT_RBUTTONUP;
+
+ e.mouse = getEventManager()->getMousePos();
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ default:
+ LOGW("unmapped system key: %d", arg2);
+ return;
+ }
+
+ break;
+
+ case JE_KEY:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_KEYDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_KEYUP;
+ break;
+ default:
+ LOGE("unhandled jaction on key: %d", arg1);
+ return;
+ }
+
+ if (arg2 < 1 || arg2 > ARRAYSIZE(jkeymap)) {
+ if (arg3 < 1) {
+ LOGE("received invalid keycode: %d (%d)", arg2, arg3);
+ return;
+ } else {
+ // lets bet on the ascii code
+ e.kbd.keycode = Common::KEYCODE_INVALID;
+ }
+ } else {
+ e.kbd.keycode = jkeymap[arg2];
+ }
+
+ if (arg5 > 0)
+ e.synthetic = true;
+
+ // map special keys to 'our' ascii codes
+ switch (e.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ e.kbd.ascii = Common::ASCII_BACKSPACE;
+ break;
+ case Common::KEYCODE_TAB:
+ e.kbd.ascii = Common::ASCII_TAB;
+ break;
+ case Common::KEYCODE_RETURN:
+ e.kbd.ascii = Common::ASCII_RETURN;
+ break;
+ case Common::KEYCODE_ESCAPE:
+ e.kbd.ascii = Common::ASCII_ESCAPE;
+ break;
+ case Common::KEYCODE_SPACE:
+ e.kbd.ascii = Common::ASCII_SPACE;
+ break;
+ case Common::KEYCODE_F1:
+ e.kbd.ascii = Common::ASCII_F1;
+ break;
+ case Common::KEYCODE_F2:
+ e.kbd.ascii = Common::ASCII_F2;
+ break;
+ case Common::KEYCODE_F3:
+ e.kbd.ascii = Common::ASCII_F3;
+ break;
+ case Common::KEYCODE_F4:
+ e.kbd.ascii = Common::ASCII_F4;
+ break;
+ case Common::KEYCODE_F5:
+ e.kbd.ascii = Common::ASCII_F5;
+ break;
+ case Common::KEYCODE_F6:
+ e.kbd.ascii = Common::ASCII_F6;
+ break;
+ case Common::KEYCODE_F7:
+ e.kbd.ascii = Common::ASCII_F7;
+ break;
+ case Common::KEYCODE_F8:
+ e.kbd.ascii = Common::ASCII_F8;
+ break;
+ case Common::KEYCODE_F9:
+ e.kbd.ascii = Common::ASCII_F9;
+ break;
+ case Common::KEYCODE_F10:
+ e.kbd.ascii = Common::ASCII_F10;
+ break;
+ case Common::KEYCODE_F11:
+ e.kbd.ascii = Common::ASCII_F11;
+ break;
+ case Common::KEYCODE_F12:
+ e.kbd.ascii = Common::ASCII_F12;
+ break;
+ default:
+ e.kbd.ascii = arg3;
+ break;
+ }
+
+ if (arg4 & JMETA_SHIFT)
+ e.kbd.flags |= Common::KBD_SHIFT;
+ if (arg4 & JMETA_ALT)
+ e.kbd.flags |= Common::KBD_ALT;
+ if (arg4 & (JMETA_SYM | JMETA_CTRL))
+ e.kbd.flags |= Common::KBD_CTRL;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_DPAD:
+ switch (arg2) {
+ case JKEYCODE_DPAD_UP:
+ case JKEYCODE_DPAD_DOWN:
+ case JKEYCODE_DPAD_LEFT:
+ case JKEYCODE_DPAD_RIGHT:
+ if (arg1 != JACTION_DOWN)
+ return;
+
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ e.mouse = getEventManager()->getMousePos();
+
+ {
+ int16 *c;
+ int s;
+
+ if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_DOWN) {
+ c = &e.mouse.y;
+ s = _eventScaleY;
+ } else {
+ c = &e.mouse.x;
+ s = _eventScaleX;
+ }
+
+ // the longer the button held, the faster the pointer is
+ // TODO put these values in some option dlg?
+ int f = CLIP(arg4, 1, 8) * _dpad_scale * 100 / s;
+
+ if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_LEFT)
+ *c -= f;
+ else
+ *c += f;
+ }
+
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JKEYCODE_DPAD_CENTER:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_LBUTTONDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_LBUTTONUP;
+ break;
+ default:
+ LOGE("unhandled jaction on dpad key: %d", arg1);
+ return;
+ }
+
+ e.mouse = getEventManager()->getMousePos();
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+ }
+
+ case JE_DOWN:
+ _touch_pt_down = getEventManager()->getMousePos();
+ _touch_pt_scroll.x = -1;
+ _touch_pt_scroll.y = -1;
+ break;
+
+ case JE_SCROLL:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ if (_touch_pt_scroll.x == -1 && _touch_pt_scroll.y == -1) {
+ _touch_pt_scroll.x = arg3;
+ _touch_pt_scroll.y = arg4;
+ return;
+ }
+
+ scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x,
+ arg4 - _touch_pt_scroll.y, false);
+ e.mouse += _touch_pt_down;
+ clipMouse(e.mouse);
+ } else {
+ scaleMouse(e.mouse, arg3, arg4);
+ clipMouse(e.mouse);
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_TAP:
+ if (_fingersDown > 0) {
+ _fingersDown = 0;
+ return;
+ }
+
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ e.mouse = getEventManager()->getMousePos();
+ } else {
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+ }
+
+ {
+ Common::EventType down, up;
+
+ // TODO put these values in some option dlg?
+ if (arg3 > 1000) {
+ down = Common::EVENT_MBUTTONDOWN;
+ up = Common::EVENT_MBUTTONUP;
+ } else if (arg3 > 500) {
+ down = Common::EVENT_RBUTTONDOWN;
+ up = Common::EVENT_RBUTTONUP;
+ } else {
+ down = Common::EVENT_LBUTTONDOWN;
+ up = Common::EVENT_LBUTTONUP;
+ }
+
+ lockMutex(_event_queue_lock);
+
+ if (!_touchpad_mode)
+ _event_queue.push(e);
+
+ e.type = down;
+ _event_queue.push(e);
+ e.type = up;
+ _event_queue.push(e);
+
+ unlockMutex(_event_queue_lock);
+ }
+
+ return;
+
+ case JE_DOUBLE_TAP:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ e.mouse = getEventManager()->getMousePos();
+ } else {
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+ }
+
+ {
+ Common::EventType dptype = Common::EVENT_INVALID;
+
+ switch (arg3) {
+ case JACTION_DOWN:
+ dptype = Common::EVENT_LBUTTONDOWN;
+ _touch_pt_dt.x = -1;
+ _touch_pt_dt.y = -1;
+ break;
+ case JACTION_UP:
+ dptype = Common::EVENT_LBUTTONUP;
+ break;
+ // held and moved
+ case JACTION_MULTIPLE:
+ if (_touch_pt_dt.x == -1 && _touch_pt_dt.y == -1) {
+ _touch_pt_dt.x = arg1;
+ _touch_pt_dt.y = arg2;
+ return;
+ }
+
+ dptype = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ scaleMouse(e.mouse, arg1 - _touch_pt_dt.x,
+ arg2 - _touch_pt_dt.y, false);
+ e.mouse += _touch_pt_down;
+
+ clipMouse(e.mouse);
+ }
+
+ break;
+ default:
+ LOGE("unhandled jaction on double tap: %d", arg3);
+ return;
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ e.type = dptype;
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+ }
+
+ return;
+
+ case JE_MULTI:
+ switch (arg2) {
+ case JACTION_POINTER_DOWN:
+ if (arg1 > _fingersDown)
+ _fingersDown = arg1;
+
+ return;
+
+ case JACTION_POINTER_UP:
+ if (arg1 != _fingersDown)
+ return;
+
+ {
+ Common::EventType up;
+
+ switch (_fingersDown) {
+ case 1:
+ e.type = Common::EVENT_RBUTTONDOWN;
+ up = Common::EVENT_RBUTTONUP;
+ break;
+ case 2:
+ e.type = Common::EVENT_MBUTTONDOWN;
+ up = Common::EVENT_MBUTTONUP;
+ break;
+ default:
+ LOGD("unmapped multi tap: %d", _fingersDown);
+ return;
+ }
+
+ e.mouse = getEventManager()->getMousePos();
+
+ lockMutex(_event_queue_lock);
+
+ _event_queue.push(e);
+ e.type = up;
+ _event_queue.push(e);
+
+ unlockMutex(_event_queue_lock);
+ return;
+
+ default:
+ LOGE("unhandled jaction on multi tap: %d", arg2);
+ return;
+ }
+ }
+
+ return;
+
+ case JE_BALL:
+ e.mouse = getEventManager()->getMousePos();
+
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_LBUTTONDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_LBUTTONUP;
+ break;
+ case JACTION_MULTIPLE:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ // already multiplied by 100
+ e.mouse.x += arg2 * _trackball_scale / _eventScaleX;
+ e.mouse.y += arg3 * _trackball_scale / _eventScaleY;
+
+ clipMouse(e.mouse);
+
+ break;
+ default:
+ LOGE("unhandled jaction on system key: %d", arg1);
+ return;
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_QUIT:
+ e.type = Common::EVENT_QUIT;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ default:
+ LOGE("unknown jevent type: %d", type);
+
+ break;
+ }
+}
+
+bool OSystem_Android::pollEvent(Common::Event &event) {
+ //ENTER();
+
+ if (pthread_self() == _main_thread) {
+ if (_screen_changeid != JNI::surface_changeid) {
+ if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
+ // surface changed
+ JNI::deinitSurface();
+ initSurface();
+ initViewport();
+ updateScreenRect();
+ updateEventScale();
+
+ // double buffered, flip twice
+ clearScreen(kClearUpdate, 2);
+
+ event.type = Common::EVENT_SCREEN_CHANGED;
+
+ return true;
+ } else {
+ // surface lost
+ deinitSurface();
+ }
+ }
+
+ if (JNI::pause) {
+ deinitSurface();
+
+ LOGD("main thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("main thread woke up");
+ }
+ }
+
+ lockMutex(_event_queue_lock);
+
+ if (_event_queue.empty()) {
+ unlockMutex(_event_queue_lock);
+ return false;
+ }
+
+ event = _event_queue.pop();
+
+ unlockMutex(_event_queue_lock);
+
+ if (event.type == Common::EVENT_MOUSEMOVE) {
+ const Common::Point &m = getEventManager()->getMousePos();
+
+ if (m != event.mouse)
+ _force_redraw = true;
+ }
+
+ return true;
+}
+
+#endif
+
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
new file mode 100644
index 0000000000..86232030ff
--- /dev/null
+++ b/backends/platform/android/gfx.cpp
@@ -0,0 +1,819 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "common/endian.h"
+#include "graphics/conversion.h"
+
+#include "backends/platform/android/android.h"
+#include "backends/platform/android/jni.h"
+
+static inline GLfixed xdiv(int numerator, int denominator) {
+ assert(numerator < (1 << 16));
+ return (numerator << 16) / denominator;
+}
+
+const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
+ static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
+ { "default", "Default", 0 },
+ { "filter", "Linear filtering", 1 },
+ { 0, 0, 0 },
+ };
+
+ return s_supportedGraphicsModes;
+}
+
+int OSystem_Android::getDefaultGraphicsMode() const {
+ return 0;
+}
+
+bool OSystem_Android::setGraphicsMode(int mode) {
+ ENTER("%d", mode);
+
+ if (_game_texture)
+ _game_texture->setLinearFilter(mode == 1);
+
+ if (_overlay_texture)
+ _overlay_texture->setLinearFilter(mode == 1);
+
+ if (_mouse_texture)
+ _mouse_texture->setLinearFilter(mode == 1);
+
+ _graphicsMode = mode;
+
+ return true;
+}
+
+int OSystem_Android::getGraphicsMode() const {
+ return _graphicsMode;
+}
+
+#ifdef USE_RGB_COLOR
+Graphics::PixelFormat OSystem_Android::getScreenFormat() const {
+ return _game_texture->getPixelFormat();
+}
+
+Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const {
+ Common::List<Graphics::PixelFormat> res;
+ res.push_back(GLES565Texture::pixelFormat());
+ res.push_back(GLES5551Texture::pixelFormat());
+ res.push_back(GLES4444Texture::pixelFormat());
+ res.push_back(Graphics::PixelFormat::createFormatCLUT8());
+
+ return res;
+}
+
+Common::String OSystem_Android::getPixelFormatName(const Graphics::PixelFormat &format) const {
+ if (format.bytesPerPixel == 1)
+ return "CLUT8";
+
+ if (format.aLoss == 8)
+ return Common::String::format("RGB%u%u%u",
+ 8 - format.rLoss,
+ 8 - format.gLoss,
+ 8 - format.bLoss);
+
+ return Common::String::format("RGBA%u%u%u%u",
+ 8 - format.rLoss,
+ 8 - format.gLoss,
+ 8 - format.bLoss,
+ 8 - format.aLoss);
+}
+
+void OSystem_Android::initTexture(GLESBaseTexture **texture,
+ uint width, uint height,
+ const Graphics::PixelFormat *format) {
+ assert(texture);
+ Graphics::PixelFormat format_clut8 =
+ Graphics::PixelFormat::createFormatCLUT8();
+ Graphics::PixelFormat format_current;
+ Graphics::PixelFormat format_new;
+
+ if (*texture)
+ format_current = (*texture)->getPixelFormat();
+ else
+ format_current = Graphics::PixelFormat();
+
+ if (format)
+ format_new = *format;
+ else
+ format_new = format_clut8;
+
+ if (format_current != format_new) {
+ if (*texture)
+ LOGD("switching pixel format from: %s",
+ getPixelFormatName((*texture)->getPixelFormat()).c_str());
+
+ delete *texture;
+
+ if (format_new == GLES565Texture::pixelFormat())
+ *texture = new GLES565Texture();
+ else if (format_new == GLES5551Texture::pixelFormat())
+ *texture = new GLES5551Texture();
+ else if (format_new == GLES4444Texture::pixelFormat())
+ *texture = new GLES4444Texture();
+ else {
+ // TODO what now?
+ if (format_new != format_clut8)
+ LOGE("unsupported pixel format: %s",
+ getPixelFormatName(format_new).c_str());
+
+ *texture = new GLESFakePalette565Texture;
+ }
+
+ LOGD("new pixel format: %s",
+ getPixelFormatName((*texture)->getPixelFormat()).c_str());
+ }
+
+ (*texture)->allocBuffer(width, height);
+}
+#endif
+
+void OSystem_Android::initSurface() {
+ LOGD("initializing surface");
+
+ assert(!JNI::haveSurface());
+
+ _screen_changeid = JNI::surface_changeid;
+ _egl_surface_width = JNI::egl_surface_width;
+ _egl_surface_height = JNI::egl_surface_height;
+
+ assert(_egl_surface_width > 0 && _egl_surface_height > 0);
+
+ JNI::initSurface();
+
+ // Initialise OpenGLES context.
+ GLESTexture::initGLExtensions();
+
+ if (_game_texture)
+ _game_texture->reinit();
+
+ if (_overlay_texture) {
+ _overlay_texture->reinit();
+ initOverlay();
+ }
+
+ if (_mouse_texture)
+ _mouse_texture->reinit();
+}
+
+void OSystem_Android::deinitSurface() {
+ if (!JNI::haveSurface())
+ return;
+
+ LOGD("deinitializing surface");
+
+ _screen_changeid = JNI::surface_changeid;
+ _egl_surface_width = 0;
+ _egl_surface_height = 0;
+
+ // release texture resources
+ if (_game_texture)
+ _game_texture->release();
+
+ if (_overlay_texture)
+ _overlay_texture->release();
+
+ if (_mouse_texture)
+ _mouse_texture->release();
+
+ JNI::deinitSurface();
+}
+
+void OSystem_Android::initViewport() {
+ LOGD("initializing viewport");
+
+ assert(JNI::haveSurface());
+
+ // Turn off anything that looks like 3D ;)
+ GLCALL(glDisable(GL_CULL_FACE));
+ GLCALL(glDisable(GL_DEPTH_TEST));
+ GLCALL(glDisable(GL_LIGHTING));
+ GLCALL(glDisable(GL_FOG));
+ GLCALL(glDisable(GL_DITHER));
+
+ GLCALL(glShadeModel(GL_FLAT));
+ GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
+
+ GLCALL(glEnable(GL_BLEND));
+ GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+
+ GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
+ GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
+
+ GLCALL(glEnable(GL_TEXTURE_2D));
+
+ GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
+
+ GLCALL(glMatrixMode(GL_PROJECTION));
+ GLCALL(glLoadIdentity());
+ GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1));
+ GLCALL(glMatrixMode(GL_MODELVIEW));
+ GLCALL(glLoadIdentity());
+
+ clearFocusRectangle();
+}
+
+void OSystem_Android::initOverlay() {
+ // minimum of 320x200
+ // (surface can get smaller when opening the virtual keyboard on *QVGA*)
+ int overlay_width = MAX(_egl_surface_width, 320);
+ int overlay_height = MAX(_egl_surface_height, 200);
+
+ // the 'normal' theme layout uses a max height of 400 pixels. if the
+ // surface is too big we use only a quarter of the size so that the widgets
+ // don't get too small. if the surface height has less than 800 pixels, this
+ // enforces the 'lowres' layout, which will be scaled back up by factor 2x,
+ // but this looks way better than the 'normal' layout scaled by some
+ // calculated factors
+ while (overlay_height > 480) {
+ overlay_width /= 2;
+ overlay_height /= 2;
+ }
+
+ LOGI("overlay size is %ux%u", overlay_width, overlay_height);
+
+ _overlay_texture->allocBuffer(overlay_width, overlay_height);
+ _overlay_texture->setDrawRect(0, 0,
+ _egl_surface_width, _egl_surface_height);
+}
+
+void OSystem_Android::initSize(uint width, uint height,
+ const Graphics::PixelFormat *format) {
+ ENTER("%d, %d, %p", width, height, format);
+
+ GLTHREADCHECK;
+
+#ifdef USE_RGB_COLOR
+ initTexture(&_game_texture, width, height, format);
+#else
+ _game_texture->allocBuffer(width, height);
+#endif
+
+ updateScreenRect();
+ updateEventScale();
+
+ // Don't know mouse size yet - it gets reallocated in
+ // setMouseCursor. We need the palette allocated before
+ // setMouseCursor however, so just take a guess at the desired
+ // size (it's small).
+ _mouse_texture_palette->allocBuffer(20, 20);
+
+ clearScreen(kClear);
+}
+
+void OSystem_Android::clearScreen(FixupType type, byte count) {
+ assert(count > 0);
+
+ bool sm = _show_mouse;
+ _show_mouse = false;
+
+ GLCALL(glDisable(GL_SCISSOR_TEST));
+
+ for (byte i = 0; i < count; ++i) {
+ // clear screen
+ GLCALL(glClearColorx(0, 0, 0, 1 << 16));
+ GLCALL(glClear(GL_COLOR_BUFFER_BIT));
+
+ switch (type) {
+ case kClear:
+ break;
+
+ case kClearSwap:
+ JNI::swapBuffers();
+ break;
+
+ case kClearUpdate:
+ _force_redraw = true;
+ updateScreen();
+ break;
+ }
+ }
+
+ if (!_show_overlay)
+ GLCALL(glEnable(GL_SCISSOR_TEST));
+
+ _show_mouse = sm;
+ _force_redraw = true;
+}
+
+void OSystem_Android::updateScreenRect() {
+ Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height);
+
+ _overlay_texture->setDrawRect(rect);
+
+ uint16 w = _game_texture->width();
+ uint16 h = _game_texture->height();
+
+ if (w && h && !_fullscreen) {
+ if (_ar_correction && w == 320 && h == 200)
+ h = 240;
+
+ float dpi[2];
+ JNI::getDPI(dpi);
+
+ float screen_ar;
+ if (dpi[0] != 0.0 && dpi[1] != 0.0) {
+ // horizontal orientation
+ screen_ar = (dpi[1] * _egl_surface_width) /
+ (dpi[0] * _egl_surface_height);
+ } else {
+ screen_ar = float(_egl_surface_width) / float(_egl_surface_height);
+ }
+
+ float game_ar = float(w) / float(h);
+
+ if (screen_ar > game_ar) {
+ rect.setWidth(round(_egl_surface_height * game_ar));
+ rect.moveTo((_egl_surface_width - rect.width()) / 2, 0);
+ } else {
+ rect.setHeight(round(_egl_surface_width / game_ar));
+ rect.moveTo((_egl_surface_height - rect.height()) / 2, 0);
+ }
+ }
+
+ glScissor(rect.left, rect.top, rect.width(), rect.height());
+
+ _game_texture->setDrawRect(rect);
+}
+
+int OSystem_Android::getScreenChangeID() const {
+ return _screen_changeid;
+}
+
+int16 OSystem_Android::getHeight() {
+ return _game_texture->height();
+}
+
+int16 OSystem_Android::getWidth() {
+ return _game_texture->width();
+}
+
+void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
+ ENTER("%p, %u, %u", colors, start, num);
+
+#ifdef USE_RGB_COLOR
+ assert(_game_texture->hasPalette());
+#endif
+
+ GLTHREADCHECK;
+
+ if (!_use_mouse_palette)
+ setCursorPaletteInternal(colors, start, num);
+
+ const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
+ byte *p = _game_texture->palette() + start * 2;
+
+ for (uint i = 0; i < num; ++i, colors += 3, p += 2)
+ WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
+}
+
+void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
+ ENTER("%p, %u, %u", colors, start, num);
+
+#ifdef USE_RGB_COLOR
+ assert(_game_texture->hasPalette());
+#endif
+
+ GLTHREADCHECK;
+
+ const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
+ const byte *p = _game_texture->palette_const() + start * 2;
+
+ for (uint i = 0; i < num; ++i, colors += 3, p += 2)
+ pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]);
+}
+
+void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
+ int x, int y, int w, int h) {
+ ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
+
+ GLTHREADCHECK;
+
+ _game_texture->updateBuffer(x, y, w, h, buf, pitch);
+}
+
+void OSystem_Android::updateScreen() {
+ //ENTER();
+
+ GLTHREADCHECK;
+
+ if (!JNI::haveSurface())
+ return;
+
+ if (!_force_redraw &&
+ !_game_texture->dirty() &&
+ !_overlay_texture->dirty() &&
+ !_mouse_texture->dirty())
+ return;
+
+ _force_redraw = false;
+
+ // clear pointer leftovers in dead areas
+ // also, HTC's GLES drivers are made of fail and don't preserve the buffer
+ // ( http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html )
+ if ((_show_overlay || _htc_fail) && !_fullscreen)
+ clearScreen(kClear);
+
+ GLCALL(glPushMatrix());
+
+ if (_shake_offset != 0 ||
+ (!_focus_rect.isEmpty() &&
+ !Common::Rect(_game_texture->width(),
+ _game_texture->height()).contains(_focus_rect))) {
+ // These are the only cases where _game_texture doesn't
+ // cover the entire screen.
+ clearScreen(kClear);
+
+ // Move everything up by _shake_offset (game) pixels
+ GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
+ }
+
+// TODO this doesnt work on those sucky drivers, do it differently
+// if (_show_overlay)
+// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f));
+
+ if (_focus_rect.isEmpty()) {
+ _game_texture->drawTextureRect();
+ } else {
+ GLCALL(glPushMatrix());
+
+ GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
+ xdiv(_egl_surface_height, _focus_rect.height()),
+ 1 << 16));
+ GLCALL(glTranslatex(-_focus_rect.left << 16,
+ -_focus_rect.top << 16, 0));
+ GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width),
+ xdiv(_game_texture->height(), _egl_surface_height),
+ 1 << 16));
+
+ _game_texture->drawTextureRect();
+
+ GLCALL(glPopMatrix());
+ }
+
+ int cs = _mouse_targetscale;
+
+ if (_show_overlay) {
+// TODO see above
+// GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
+
+ // ugly, but the modern theme sets a wacko factor, only god knows why
+ cs = 1;
+
+ GLCALL(_overlay_texture->drawTextureRect());
+ }
+
+ if (_show_mouse && !_mouse_texture->isEmpty()) {
+ GLCALL(glPushMatrix());
+
+ const Common::Point &mouse = getEventManager()->getMousePos();
+
+ // Scale up ScummVM -> OpenGL (pixel) coordinates
+ if (_show_overlay) {
+ GLCALL(glScalex(xdiv(_egl_surface_width,
+ _overlay_texture->width()),
+ xdiv(_egl_surface_height,
+ _overlay_texture->height()),
+ 1 << 16));
+ } else {
+ const Common::Rect &r = _game_texture->getDrawRect();
+
+ GLCALL(glTranslatex(r.left << 16,
+ r.top << 16,
+ 0));
+ GLCALL(glScalex(xdiv(r.width(), _game_texture->width()),
+ xdiv(r.height(), _game_texture->height()),
+ 1 << 16));
+ }
+
+ GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
+ (-_mouse_hotspot.y * cs) << 16,
+ 0));
+
+ // Note the extra half texel to position the mouse in
+ // the middle of the x,y square:
+ GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
+ (mouse.y << 16) | 1 << 15, 0));
+
+ GLCALL(glScalex(cs << 16, cs << 16, 1 << 16));
+
+ _mouse_texture->drawTextureOrigin();
+
+ GLCALL(glPopMatrix());
+ }
+
+ GLCALL(glPopMatrix());
+
+ if (!JNI::swapBuffers())
+ LOGW("swapBuffers failed: 0x%x", glGetError());
+}
+
+Graphics::Surface *OSystem_Android::lockScreen() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ Graphics::Surface *surface = _game_texture->surface();
+ assert(surface->pixels);
+
+ return surface;
+}
+
+void OSystem_Android::unlockScreen() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ assert(_game_texture->dirty());
+}
+
+void OSystem_Android::setShakePos(int shake_offset) {
+ ENTER("%d", shake_offset);
+
+ if (_shake_offset != shake_offset) {
+ _shake_offset = shake_offset;
+ _force_redraw = true;
+ }
+}
+
+void OSystem_Android::fillScreen(uint32 col) {
+ ENTER("%u", col);
+
+ GLTHREADCHECK;
+
+ _game_texture->fillBuffer(col);
+}
+
+void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
+ ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom);
+
+ if (_enable_zoning) {
+ _focus_rect = rect;
+ _force_redraw = true;
+ }
+}
+
+void OSystem_Android::clearFocusRectangle() {
+ ENTER();
+
+ if (_enable_zoning) {
+ _focus_rect = Common::Rect();
+ _force_redraw = true;
+ }
+}
+
+void OSystem_Android::showOverlay() {
+ ENTER();
+
+ _show_overlay = true;
+ _force_redraw = true;
+
+ updateEventScale();
+
+ warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2);
+
+ GLCALL(glDisable(GL_SCISSOR_TEST));
+}
+
+void OSystem_Android::hideOverlay() {
+ ENTER();
+
+ _show_overlay = false;
+
+ updateEventScale();
+
+ warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
+
+ // double buffered, flip twice
+ clearScreen(kClearUpdate, 2);
+
+ GLCALL(glEnable(GL_SCISSOR_TEST));
+}
+
+void OSystem_Android::clearOverlay() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ _overlay_texture->fillBuffer(0);
+}
+
+void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
+ ENTER("%p, %d", buf, pitch);
+
+ GLTHREADCHECK;
+
+ const Graphics::Surface *surface = _overlay_texture->surface_const();
+ assert(surface->bytesPerPixel == sizeof(buf[0]));
+
+ const byte *src = (const byte *)surface->pixels;
+ uint h = surface->h;
+
+ do {
+ memcpy(buf, src, surface->w * surface->bytesPerPixel);
+ src += surface->pitch;
+ // This 'pitch' is pixels not bytes
+ buf += pitch;
+ } while (--h);
+}
+
+void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
+ int x, int y, int w, int h) {
+ ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
+
+ GLTHREADCHECK;
+
+ // This 'pitch' is pixels not bytes
+ _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
+}
+
+int16 OSystem_Android::getOverlayHeight() {
+ return _overlay_texture->height();
+}
+
+int16 OSystem_Android::getOverlayWidth() {
+ return _overlay_texture->width();
+}
+
+Graphics::PixelFormat OSystem_Android::getOverlayFormat() const {
+ return _overlay_texture->getPixelFormat();
+}
+
+bool OSystem_Android::showMouse(bool visible) {
+ ENTER("%d", visible);
+
+ _show_mouse = visible;
+
+ return true;
+}
+
+void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
+ int hotspotX, int hotspotY,
+ uint32 keycolor, int cursorTargetScale,
+ const Graphics::PixelFormat *format) {
+ ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
+ keycolor, cursorTargetScale, format);
+
+ GLTHREADCHECK;
+
+#ifdef USE_RGB_COLOR
+ if (format && format->bytesPerPixel > 1) {
+ if (_mouse_texture != _mouse_texture_rgb) {
+ LOGD("switching to rgb mouse cursor");
+
+ assert(!_mouse_texture_rgb);
+ _mouse_texture_rgb = new GLES5551Texture();
+ _mouse_texture_rgb->setLinearFilter(_graphicsMode == 1);
+ }
+
+ _mouse_texture = _mouse_texture_rgb;
+ } else {
+ if (_mouse_texture != _mouse_texture_palette)
+ LOGD("switching to paletted mouse cursor");
+
+ _mouse_texture = _mouse_texture_palette;
+
+ delete _mouse_texture_rgb;
+ _mouse_texture_rgb = 0;
+ }
+#endif
+
+ _mouse_texture->allocBuffer(w, h);
+
+ if (_mouse_texture == _mouse_texture_palette) {
+ assert(keycolor < 256);
+
+ byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) | 1);
+
+ _mouse_keycolor = keycolor;
+
+ p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) & ~1);
+ }
+
+ if (w == 0 || h == 0)
+ return;
+
+ if (_mouse_texture == _mouse_texture_palette) {
+ _mouse_texture->updateBuffer(0, 0, w, h, buf, w);
+ } else {
+ uint16 pitch = _mouse_texture->pitch();
+
+ byte *tmp = new byte[pitch * h];
+
+ // meh, a 16bit cursor without alpha bits... this is so silly
+ if (!crossBlit(tmp, buf, pitch, w * 2, w, h,
+ _mouse_texture->getPixelFormat(),
+ *format)) {
+ LOGE("crossblit failed");
+
+ delete[] tmp;
+
+ _mouse_texture->allocBuffer(0, 0);
+
+ return;
+ }
+
+ uint16 *s = (uint16 *)buf;
+ uint16 *d = (uint16 *)tmp;
+ for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w)
+ for (uint16 x = 0; x < w; ++x, d++)
+ if (*s++ != (keycolor & 0xffff))
+ *d |= 1;
+
+ _mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch);
+
+ delete[] tmp;
+ }
+
+ _mouse_hotspot = Common::Point(hotspotX, hotspotY);
+ _mouse_targetscale = cursorTargetScale;
+}
+
+void OSystem_Android::setCursorPaletteInternal(const byte *colors,
+ uint start, uint num) {
+ const Graphics::PixelFormat &pf =
+ _mouse_texture_palette->getPalettePixelFormat();
+ byte *p = _mouse_texture_palette->palette() + start * 2;
+
+ for (uint i = 0; i < num; ++i, colors += 3, p += 2)
+ WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
+
+ p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) & ~1);
+}
+
+void OSystem_Android::setCursorPalette(const byte *colors,
+ uint start, uint num) {
+ ENTER("%p, %u, %u", colors, start, num);
+
+ GLTHREADCHECK;
+
+ if (!_mouse_texture->hasPalette()) {
+ LOGD("switching to paletted mouse cursor");
+
+ _mouse_texture = _mouse_texture_palette;
+
+ delete _mouse_texture_rgb;
+ _mouse_texture_rgb = 0;
+ }
+
+ setCursorPaletteInternal(colors, start, num);
+ _use_mouse_palette = true;
+}
+
+void OSystem_Android::disableCursorPalette(bool disable) {
+ ENTER("%d", disable);
+
+ // when disabling the cursor palette, and we're running a clut8 game,
+ // it expects the game palette to be used for the cursor
+ if (disable && _game_texture->hasPalette()) {
+ const byte *src = _game_texture->palette_const();
+ byte *dst = _mouse_texture_palette->palette();
+
+ const Graphics::PixelFormat &pf_src =
+ _game_texture->getPalettePixelFormat();
+ const Graphics::PixelFormat &pf_dst =
+ _mouse_texture_palette->getPalettePixelFormat();
+
+ uint8 r, g, b;
+
+ for (uint i = 0; i < 256; ++i, src += 2, dst += 2) {
+ pf_src.colorToRGB(READ_UINT16(src), r, g, b);
+ WRITE_UINT16(dst, pf_dst.RGBToColor(r, g, b));
+ }
+
+ byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) & ~1);
+ }
+
+ _use_mouse_palette = !disable;
+}
+
+#endif
+
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
new file mode 100644
index 0000000000..08a1491998
--- /dev/null
+++ b/backends/platform/android/jni.cpp
@@ -0,0 +1,605 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "base/main.h"
+#include "base/version.h"
+#include "common/config-manager.h"
+#include "engines/engine.h"
+
+#include "backends/platform/android/android.h"
+#include "backends/platform/android/asset-archive.h"
+#include "backends/platform/android/jni.h"
+
+__attribute__ ((visibility("default")))
+jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
+ return JNI::onLoad(vm);
+}
+
+JavaVM *JNI::_vm = 0;
+jobject JNI::_jobj = 0;
+jobject JNI::_jobj_audio_track = 0;
+jobject JNI::_jobj_egl = 0;
+jobject JNI::_jobj_egl_display = 0;
+jobject JNI::_jobj_egl_surface = 0;
+
+Common::Archive *JNI::_asset_archive = 0;
+OSystem_Android *JNI::_system = 0;
+
+bool JNI::pause = false;
+sem_t JNI::pause_sem = { 0 };
+
+int JNI::surface_changeid = 0;
+int JNI::egl_surface_width = 0;
+int JNI::egl_surface_height = 0;
+bool JNI::_ready_for_events = 0;
+
+jmethodID JNI::_MID_getDPI = 0;
+jmethodID JNI::_MID_displayMessageOnOSD = 0;
+jmethodID JNI::_MID_setWindowCaption = 0;
+jmethodID JNI::_MID_showVirtualKeyboard = 0;
+jmethodID JNI::_MID_getSysArchives = 0;
+jmethodID JNI::_MID_getPluginDirectories = 0;
+jmethodID JNI::_MID_initSurface = 0;
+jmethodID JNI::_MID_deinitSurface = 0;
+
+jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0;
+
+jmethodID JNI::_MID_AudioTrack_flush = 0;
+jmethodID JNI::_MID_AudioTrack_pause = 0;
+jmethodID JNI::_MID_AudioTrack_play = 0;
+jmethodID JNI::_MID_AudioTrack_stop = 0;
+jmethodID JNI::_MID_AudioTrack_write = 0;
+
+const JNINativeMethod JNI::_natives[] = {
+ { "create", "(Landroid/content/res/AssetManager;"
+ "Ljavax/microedition/khronos/egl/EGL10;"
+ "Ljavax/microedition/khronos/egl/EGLDisplay;"
+ "Landroid/media/AudioTrack;II)V",
+ (void *)JNI::create },
+ { "destroy", "()V",
+ (void *)JNI::destroy },
+ { "setSurface", "(II)V",
+ (void *)JNI::setSurface },
+ { "main", "([Ljava/lang/String;)I",
+ (void *)JNI::main },
+ { "pushEvent", "(IIIIII)V",
+ (void *)JNI::pushEvent },
+ { "enableZoning", "(Z)V",
+ (void *)JNI::enableZoning },
+ { "setPause", "(Z)V",
+ (void *)JNI::setPause }
+};
+
+JNI::JNI() {
+}
+
+JNI::~JNI() {
+}
+
+jint JNI::onLoad(JavaVM *vm) {
+ _vm = vm;
+
+ JNIEnv *env;
+
+ if (_vm->GetEnv((void **)&env, JNI_VERSION_1_2))
+ return JNI_ERR;
+
+ jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
+ if (cls == 0)
+ return JNI_ERR;
+
+ if (env->RegisterNatives(cls, _natives, ARRAYSIZE(_natives)) < 0)
+ return JNI_ERR;
+
+ return JNI_VERSION_1_2;
+}
+
+JNIEnv *JNI::getEnv() {
+ JNIEnv *env = 0;
+
+ jint res = _vm->GetEnv((void **)&env, JNI_VERSION_1_2);
+
+ if (res != JNI_OK) {
+ LOGE("GetEnv() failed: %d", res);
+ abort();
+ }
+
+ return env;
+}
+
+void JNI::attachThread() {
+ JNIEnv *env = 0;
+
+ jint res = _vm->AttachCurrentThread(&env, 0);
+
+ if (res != JNI_OK) {
+ LOGE("AttachCurrentThread() failed: %d", res);
+ abort();
+ }
+}
+
+void JNI::detachThread() {
+ jint res = _vm->DetachCurrentThread();
+
+ if (res != JNI_OK) {
+ LOGE("DetachCurrentThread() failed: %d", res);
+ abort();
+ }
+}
+
+void JNI::setReadyForEvents(bool ready) {
+ _ready_for_events = ready;
+}
+
+void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
+ jclass cls = env->FindClass(name);
+
+ // if cls is 0, an exception has already been thrown
+ if (cls != 0)
+ env->ThrowNew(cls, msg);
+
+ env->DeleteLocalRef(cls);
+}
+
+void JNI::throwRuntimeException(JNIEnv *env, const char *msg) {
+ throwByName(env, "java/lang/RuntimeException", msg);
+}
+
+// calls to the dark side
+
+void JNI::getDPI(float *values) {
+ values[0] = 0.0;
+ values[1] = 0.0;
+
+ JNIEnv *env = JNI::getEnv();
+
+ jfloatArray array = env->NewFloatArray(2);
+
+ env->CallVoidMethod(_jobj, _MID_getDPI, array);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Failed to get DPIs");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ } else {
+ jfloat *res = env->GetFloatArrayElements(array, 0);
+
+ if (res) {
+ values[0] = res[0];
+ values[1] = res[1];
+
+ env->ReleaseFloatArrayElements(array, res, 0);
+ }
+ }
+
+ env->DeleteLocalRef(array);
+}
+
+void JNI::displayMessageOnOSD(const char *msg) {
+ JNIEnv *env = JNI::getEnv();
+ jstring java_msg = env->NewStringUTF(msg);
+
+ env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Failed to display OSD message");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->DeleteLocalRef(java_msg);
+}
+
+void JNI::setWindowCaption(const char *caption) {
+ JNIEnv *env = JNI::getEnv();
+ jstring java_caption = env->NewStringUTF(caption);
+
+ env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Failed to set window caption");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->DeleteLocalRef(java_caption);
+}
+
+void JNI::showVirtualKeyboard(bool enable) {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error trying to show virtual keyboard");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+ JNIEnv *env = JNI::getEnv();
+
+ s.add("ASSET", _asset_archive, priority, false);
+
+ jobjectArray array =
+ (jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error finding system archive path");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ return;
+ }
+
+ jsize size = env->GetArrayLength(array);
+ for (jsize i = 0; i < size; ++i) {
+ jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+ const char *path = env->GetStringUTFChars(path_obj, 0);
+
+ if (path != 0) {
+ s.addDirectory(path, path, priority);
+ env->ReleaseStringUTFChars(path_obj, path);
+ }
+
+ env->DeleteLocalRef(path_obj);
+ }
+}
+
+void JNI::getPluginDirectories(Common::FSList &dirs) {
+ JNIEnv *env = JNI::getEnv();
+
+ jobjectArray array =
+ (jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error finding plugin directories");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ return;
+ }
+
+ jsize size = env->GetArrayLength(array);
+ for (jsize i = 0; i < size; ++i) {
+ jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+
+ if (path_obj == 0)
+ continue;
+
+ const char *path = env->GetStringUTFChars(path_obj, 0);
+
+ if (path == 0) {
+ LOGE("Error getting string characters from plugin directory");
+
+ env->ExceptionClear();
+ env->DeleteLocalRef(path_obj);
+
+ continue;
+ }
+
+ dirs.push_back(Common::FSNode(path));
+
+ env->ReleaseStringUTFChars(path_obj, path);
+ env->DeleteLocalRef(path_obj);
+ }
+}
+
+bool JNI::initSurface() {
+ JNIEnv *env = JNI::getEnv();
+
+ jobject obj = env->CallObjectMethod(_jobj, _MID_initSurface);
+
+ if (!obj || env->ExceptionCheck()) {
+ LOGE("initSurface failed");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ return false;
+ }
+
+ _jobj_egl_surface = env->NewGlobalRef(obj);
+
+ return true;
+}
+
+void JNI::deinitSurface() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj, _MID_deinitSurface);
+
+ if (env->ExceptionCheck()) {
+ LOGE("deinitSurface failed");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->DeleteGlobalRef(_jobj_egl_surface);
+ _jobj_egl_surface = 0;
+}
+
+void JNI::setAudioPause() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_flush);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error flushing AudioTrack");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error setting AudioTrack: pause");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+void JNI::setAudioPlay() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_play);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error setting AudioTrack: play");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+void JNI::setAudioStop() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_stop);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error setting AudioTrack: stop");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+// natives for the dark side
+
+void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
+ jobject egl, jobject egl_display,
+ jobject at, jint audio_sample_rate, jint audio_buffer_size) {
+ LOGI(gScummVMFullVersion);
+
+ assert(!_system);
+
+ pause = false;
+ // initial value of zero!
+ sem_init(&pause_sem, 0, 0);
+
+ _asset_archive = new AndroidAssetArchive(asset_manager);
+ assert(_asset_archive);
+
+ _system = new OSystem_Android(audio_sample_rate, audio_buffer_size);
+ assert(_system);
+
+ // weak global ref to allow class to be unloaded
+ // ... except dalvik implements NewWeakGlobalRef only on froyo
+ //_jobj = env->NewWeakGlobalRef(self);
+
+ _jobj = env->NewGlobalRef(self);
+
+ jclass cls = env->GetObjectClass(_jobj);
+
+#define FIND_METHOD(prefix, name, signature) do { \
+ _MID_ ## prefix ## name = env->GetMethodID(cls, #name, signature); \
+ if (_MID_ ## prefix ## name == 0) \
+ return; \
+ } while (0)
+
+ FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V");
+ FIND_METHOD(, getDPI, "([F)V");
+ FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
+ FIND_METHOD(, showVirtualKeyboard, "(Z)V");
+ FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
+ FIND_METHOD(, getPluginDirectories, "()[Ljava/lang/String;");
+ FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
+ FIND_METHOD(, deinitSurface, "()V");
+
+ _jobj_egl = env->NewGlobalRef(egl);
+ _jobj_egl_display = env->NewGlobalRef(egl_display);
+
+ cls = env->GetObjectClass(_jobj_egl);
+
+ FIND_METHOD(EGL10_, eglSwapBuffers,
+ "(Ljavax/microedition/khronos/egl/EGLDisplay;"
+ "Ljavax/microedition/khronos/egl/EGLSurface;)Z");
+
+ _jobj_audio_track = env->NewGlobalRef(at);
+
+ cls = env->GetObjectClass(_jobj_audio_track);
+
+ FIND_METHOD(AudioTrack_, flush, "()V");
+ FIND_METHOD(AudioTrack_, pause, "()V");
+ FIND_METHOD(AudioTrack_, play, "()V");
+ FIND_METHOD(AudioTrack_, stop, "()V");
+ FIND_METHOD(AudioTrack_, write, "([BII)I");
+
+#undef FIND_METHOD
+
+ g_system = _system;
+}
+
+void JNI::destroy(JNIEnv *env, jobject self) {
+ delete _asset_archive;
+ _asset_archive = 0;
+
+ delete _system;
+ g_system = 0;
+ _system = 0;
+
+ sem_destroy(&pause_sem);
+
+ // see above
+ //JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
+
+ JNI::getEnv()->DeleteGlobalRef(_jobj_egl_display);
+ JNI::getEnv()->DeleteGlobalRef(_jobj_egl);
+ JNI::getEnv()->DeleteGlobalRef(_jobj_audio_track);
+ JNI::getEnv()->DeleteGlobalRef(_jobj);
+}
+
+void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height) {
+ egl_surface_width = width;
+ egl_surface_height = height;
+ surface_changeid++;
+}
+
+jint JNI::main(JNIEnv *env, jobject self, jobjectArray args) {
+ assert(_system);
+
+ const int MAX_NARGS = 32;
+ int res = -1;
+
+ int argc = env->GetArrayLength(args);
+ if (argc > MAX_NARGS) {
+ throwByName(env, "java/lang/IllegalArgumentException",
+ "too many arguments");
+ return 0;
+ }
+
+ char *argv[MAX_NARGS];
+
+ // note use in cleanup loop below
+ int nargs;
+
+ for (nargs = 0; nargs < argc; ++nargs) {
+ jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
+
+ if (arg == 0) {
+ argv[nargs] = 0;
+ } else {
+ const char *cstr = env->GetStringUTFChars(arg, 0);
+
+ argv[nargs] = const_cast<char *>(cstr);
+
+ // exception already thrown?
+ if (cstr == 0)
+ goto cleanup;
+ }
+
+ env->DeleteLocalRef(arg);
+ }
+
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new AndroidPluginProvider());
+#endif
+
+ LOGI("Entering scummvm_main with %d args", argc);
+
+ res = scummvm_main(argc, argv);
+
+ LOGI("scummvm_main exited with code %d", res);
+
+ _system->quit();
+
+cleanup:
+ nargs--;
+
+ for (int i = 0; i < nargs; ++i) {
+ if (argv[i] == 0)
+ continue;
+
+ jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
+
+ // Exception already thrown?
+ if (arg == 0)
+ return res;
+
+ env->ReleaseStringUTFChars(arg, argv[i]);
+ env->DeleteLocalRef(arg);
+ }
+
+ return res;
+}
+
+void JNI::pushEvent(JNIEnv *env, jobject self, int type, int arg1, int arg2,
+ int arg3, int arg4, int arg5) {
+ // drop events until we're ready and after we quit
+ if (!_ready_for_events) {
+ LOGW("dropping event");
+ return;
+ }
+
+ assert(_system);
+
+ _system->pushEvent(type, arg1, arg2, arg3, arg4, arg5);
+}
+
+void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
+ assert(_system);
+
+ _system->enableZoning(enable);
+}
+
+void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
+ if (!_system)
+ return;
+
+ if (g_engine) {
+ LOGD("pauseEngine: %d", value);
+
+ g_engine->pauseEngine(value);
+
+ if (value &&
+ g_engine->hasFeature(Engine::kSupportsSavingDuringRuntime) &&
+ g_engine->canSaveGameStateCurrently())
+ g_engine->saveGameState(0, "Android parachute");
+ }
+
+ pause = value;
+
+ if (!pause) {
+ // wake up all threads
+ for (uint i = 0; i < 3; ++i)
+ sem_post(&pause_sem);
+ }
+}
+
+#endif
+
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
new file mode 100644
index 0000000000..d029f1a2a8
--- /dev/null
+++ b/backends/platform/android/jni.h
@@ -0,0 +1,151 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef _ANDROID_JNI_H_
+#define _ANDROID_JNI_H_
+
+#if defined(__ANDROID__)
+
+#include <jni.h>
+#include <semaphore.h>
+
+#include "common/fs.h"
+#include "common/archive.h"
+
+class OSystem_Android;
+
+class JNI {
+private:
+ JNI();
+ virtual ~JNI();
+
+public:
+ static bool pause;
+ static sem_t pause_sem;
+
+ static int surface_changeid;
+ static int egl_surface_width;
+ static int egl_surface_height;
+
+ static jint onLoad(JavaVM *vm);
+
+ static JNIEnv *getEnv();
+
+ static void attachThread();
+ static void detachThread();
+
+ static void setReadyForEvents(bool ready);
+
+ static void getPluginDirectories(Common::FSList &dirs);
+ static void setWindowCaption(const char *caption);
+ static void getDPI(float *values);
+ static void displayMessageOnOSD(const char *msg);
+ static void showVirtualKeyboard(bool enable);
+ static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
+
+ static inline bool haveSurface();
+ static inline bool swapBuffers();
+ static bool initSurface();
+ static void deinitSurface();
+
+ static void setAudioPause();
+ static void setAudioPlay();
+ static void setAudioStop();
+
+ static inline int writeAudio(JNIEnv *env, jbyteArray &data, int offset,
+ int size);
+
+private:
+ static JavaVM *_vm;
+ // back pointer to (java) peer instance
+ static jobject _jobj;
+ static jobject _jobj_audio_track;
+ static jobject _jobj_egl;
+ static jobject _jobj_egl_display;
+ static jobject _jobj_egl_surface;
+
+ static Common::Archive *_asset_archive;
+ static OSystem_Android *_system;
+
+ static bool _ready_for_events;
+
+ static jmethodID _MID_getDPI;
+ static jmethodID _MID_displayMessageOnOSD;
+ static jmethodID _MID_setWindowCaption;
+ static jmethodID _MID_showVirtualKeyboard;
+ static jmethodID _MID_getSysArchives;
+ static jmethodID _MID_getPluginDirectories;
+ static jmethodID _MID_initSurface;
+ static jmethodID _MID_deinitSurface;
+
+ static jmethodID _MID_EGL10_eglSwapBuffers;
+
+ static jmethodID _MID_AudioTrack_flush;
+ static jmethodID _MID_AudioTrack_pause;
+ static jmethodID _MID_AudioTrack_play;
+ static jmethodID _MID_AudioTrack_stop;
+ static jmethodID _MID_AudioTrack_write;
+
+ static const JNINativeMethod _natives[];
+
+ static void throwByName(JNIEnv *env, const char *name, const char *msg);
+ static void throwRuntimeException(JNIEnv *env, const char *msg);
+
+ // natives for the dark side
+ static void create(JNIEnv *env, jobject self, jobject asset_manager,
+ jobject egl, jobject egl_display,
+ jobject at, jint audio_sample_rate,
+ jint audio_buffer_size);
+ static void destroy(JNIEnv *env, jobject self);
+
+ static void setSurface(JNIEnv *env, jobject self, jint width, jint height);
+ static jint main(JNIEnv *env, jobject self, jobjectArray args);
+
+ static void pushEvent(JNIEnv *env, jobject self, int type, int arg1,
+ int arg2, int arg3, int arg4, int arg5);
+ static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
+
+ static void setPause(JNIEnv *env, jobject self, jboolean value);
+};
+
+inline bool JNI::haveSurface() {
+ return _jobj_egl_surface != 0;
+}
+
+inline bool JNI::swapBuffers() {
+ JNIEnv *env = JNI::getEnv();
+
+ return env->CallBooleanMethod(_jobj_egl, _MID_EGL10_eglSwapBuffers,
+ _jobj_egl_display, _jobj_egl_surface);
+}
+
+inline int JNI::writeAudio(JNIEnv *env, jbyteArray &data, int offset, int size) {
+ return env->CallIntMethod(_jobj_audio_track, _MID_AudioTrack_write, data,
+ offset, size);
+}
+
+#endif
+#endif
+
diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk
index b457b388b1..2fe4b40585 100644
--- a/backends/platform/android/module.mk
+++ b/backends/platform/android/module.mk
@@ -1,84 +1,15 @@
MODULE := backends/platform/android
MODULE_OBJS := \
- android.o asset-archive.o video.o
+ jni.o \
+ texture.o \
+ asset-archive.o \
+ android.o \
+ gfx.o \
+ events.o
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
OBJS := $(MODULE_OBJS) $(OBJS)
MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
-JAVA_SRC = \
- $(MODULE)/org/inodes/gus/scummvm/ScummVM.java \
- $(MODULE)/org/inodes/gus/scummvm/ScummVMApplication.java \
- $(MODULE)/org/inodes/gus/scummvm/ScummVMActivity.java \
- $(MODULE)/org/inodes/gus/scummvm/EditableSurfaceView.java \
- $(MODULE)/org/inodes/gus/scummvm/Unpacker.java \
- $(MODULE)/org/inodes/gus/scummvm/Manifest.java \
- $(MODULE)/org/inodes/gus/scummvm/R.java
-
-JAVA_PLUGIN_SRC = \
- $(MODULE)/org/inodes/gus/scummvm/PluginProvider.java
-
-RESOURCES = \
- $(srcdir)/dists/android/res/values/strings.xml \
- $(srcdir)/dists/android/res/layout/main.xml \
- $(srcdir)/dists/android/res/layout/splash.xml \
- $(srcdir)/dists/android/res/drawable/gradient.xml \
- $(srcdir)/dists/android/res/drawable/scummvm.png \
- $(srcdir)/dists/android/res/drawable/scummvm_big.png
-
-ASSETS = $(DIST_FILES_ENGINEDATA) $(DIST_FILES_THEMES)
-
-PLUGIN_RESOURCES = \
- $(srcdir)/dists/android/res/values/strings.xml \
- $(srcdir)/dists/android/res/drawable/scummvm.png
-
-# These must be incremented for each market upload
-#ANDROID_VERSIONCODE = 6 Specified in dists/android/AndroidManifest.xml.in
-ANDROID_PLUGIN_VERSIONCODE = 6
-
-# This is a bit silly. I want to compile against the 1.6 android.jar,
-# to make the compiler check that I don't use something that requires
-# a newer Android. However, in order to use android:installLocation,
-# we need to give aapt a version >=8 android.jar - even though the
-# result will work ok on 1.5+.
-ANDROID_JAR = $(ANDROID_SDK)/platforms/android-1.5/android.jar
-ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
-
-# This library contains scummvm proper
-build.tmp/libscummvm.so: $(OBJS)
- @$(MKDIR) -p $(@D)
- $(QUIET_LINK)$(CXX) -shared $(LDFLAGS) -Wl,-Bsymbolic -Wl,-soname,$(@F) -Wl,--no-undefined -o $@ $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LIBS)
-
-
-backends/platform/android/org/inodes/gus/scummvm/R.java backends/platform/android/org/inodes/gus/scummvm/Manifest.java: $(srcdir)/dists/android/AndroidManifest.xml $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
- $(AAPT) package -m -J backends/platform/android -M $< -S $(srcdir)/dists/android/res -I $(ANDROID_JAR8)
-
-build.tmp/classes/%.class: $(srcdir)/backends/platform/android/%.java $(srcdir)/backends/platform/android/org/inodes/gus/scummvm/R.java
- @$(MKDIR) -p $(@D)
- $(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes -bootclasspath $(ANDROID_JAR) $<
-
-build.tmp/classes.plugin/%.class: $(srcdir)/backends/platform/android/%.java
- @$(MKDIR) -p $(@D)
- $(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes.plugin -bootclasspath $(ANDROID_JAR) $<
-
-classes.dex: $(JAVA_SRC:backends/platform/android/%.java=build.tmp/classes/%.class)
- $(DX) --dex --output=$@ build.tmp/classes
-
-build.tmp/plugins/classes.dex: $(JAVA_PLUGIN_SRC:backends/platform/android/%.java=build.tmp/classes.plugin/%.class)
- @$(MKDIR) -p $(@D)
- $(DX) --dex --output=$@ build.tmp/classes.plugin
-
-build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml: dists/android/mkmanifest.pl configure dists/android/AndroidManifest.xml
- dists/android/mkmanifest.pl --id=$* --configure=configure \
- --version-name=$(VERSION) \
- --version-code=$(ANDROID_PLUGIN_VERSIONCODE) \
- --stringres=build.stage/$*/res/values/strings.xml \
- --manifest=build.tmp/$*/AndroidManifest.xml \
- --master-manifest=dists/android/AndroidManifest.xml \
- --unpacklib=mylib/armeabi/lib$*.so
-
-build.stage/%/res/drawable/scummvm.png: dists/android/res/drawable/scummvm.png
- @$(MKDIR) -p $(@D)
- $(CP) $< $@
diff --git a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
index 5b71d4a3a5..cede7eedd4 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
@@ -19,13 +19,13 @@ public class EditableSurfaceView extends SurfaceView {
}
public EditableSurfaceView(Context context, AttributeSet attrs,
- int defStyle) {
+ int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onCheckIsTextEditor() {
- return true;
+ return false;
}
private class MyInputConnection extends BaseInputConnection {
@@ -40,7 +40,9 @@ public class EditableSurfaceView extends SurfaceView {
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
- return super.performEditorAction(actionCode); // Sends enter key
+
+ // Sends enter key
+ return super.performEditorAction(actionCode);
}
}
@@ -49,11 +51,12 @@ public class EditableSurfaceView extends SurfaceView {
outAttrs.initialCapsMode = 0;
outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
outAttrs.inputType = (InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_VARIATION_NORMAL |
- InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+ InputType.TYPE_TEXT_VARIATION_NORMAL |
+ InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
outAttrs.imeOptions = (EditorInfo.IME_ACTION_DONE |
- EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+ EditorInfo.IME_FLAG_NO_EXTRACT_UI);
return new MyInputConnection();
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Event.java b/backends/platform/android/org/inodes/gus/scummvm/Event.java
deleted file mode 100644
index f9c7aba93b..0000000000
--- a/backends/platform/android/org/inodes/gus/scummvm/Event.java
+++ /dev/null
@@ -1,330 +0,0 @@
-package org.inodes.gus.scummvm;
-
-import android.view.KeyEvent;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-public class Event {
- // Common::EventType enum.
- // Must be kept in sync with common/events.h
- public final static int EVENT_INVALID = 0;
- public final static int EVENT_KEYDOWN = 1;
- public final static int EVENT_KEYUP = 2;
- public final static int EVENT_MOUSEMOVE = 3;
- public final static int EVENT_LBUTTONDOWN = 4;
- public final static int EVENT_LBUTTONUP = 5;
- public final static int EVENT_RBUTTONDOWN = 6;
- public final static int EVENT_RBUTTONUP = 7;
- public final static int EVENT_WHEELUP = 8;
- public final static int EVENT_WHEELDOWN = 9;
- public final static int EVENT_QUIT = 10;
- public final static int EVENT_SCREEN_CHANGED = 11;
- public final static int EVENT_PREDICTIVE_DIALOG = 12;
- public final static int EVENT_MBUTTONDOWN = 13;
- public final static int EVENT_MBUTTONUP = 14;
- public final static int EVENT_MAINMENU = 15;
- public final static int EVENT_RTL = 16;
-
- // common/keyboard.h
- public final static int ASCII_F1 = 315;
- public final static int ASCII_F2 = 316;
- public final static int ASCII_F3 = 317;
- public final static int ASCII_F4 = 318;
- public final static int ASCII_F5 = 319;
- public final static int ASCII_F6 = 320;
- public final static int ASCII_F7 = 321;
- public final static int ASCII_F8 = 322;
- public final static int ASCII_F9 = 323;
- public final static int ASCII_F10 = 324;
- public final static int ASCII_F11 = 325;
- public final static int ASCII_F12 = 326;
- public final static int KBD_CTRL = 1 << 0;
- public final static int KBD_ALT = 1 << 1;
- public final static int KBD_SHIFT = 1 << 2;
-
- public final static int KEYCODE_INVALID = 0;
- public final static int KEYCODE_BACKSPACE = 8;
- public final static int KEYCODE_TAB = 9;
- public final static int KEYCODE_CLEAR = 12;
- public final static int KEYCODE_RETURN = 13;
- public final static int KEYCODE_PAUSE = 19;
- public final static int KEYCODE_ESCAPE = 27;
- public final static int KEYCODE_SPACE = 32;
- public final static int KEYCODE_EXCLAIM = 33;
- public final static int KEYCODE_QUOTEDBL = 34;
- public final static int KEYCODE_HASH = 35;
- public final static int KEYCODE_DOLLAR = 36;
- public final static int KEYCODE_AMPERSAND = 38;
- public final static int KEYCODE_QUOTE = 39;
- public final static int KEYCODE_LEFTPAREN = 40;
- public final static int KEYCODE_RIGHTPAREN = 41;
- public final static int KEYCODE_ASTERISK = 42;
- public final static int KEYCODE_PLUS = 43;
- public final static int KEYCODE_COMMA = 44;
- public final static int KEYCODE_MINUS = 45;
- public final static int KEYCODE_PERIOD = 46;
- public final static int KEYCODE_SLASH = 47;
- public final static int KEYCODE_0 = 48;
- public final static int KEYCODE_1 = 49;
- public final static int KEYCODE_2 = 50;
- public final static int KEYCODE_3 = 51;
- public final static int KEYCODE_4 = 52;
- public final static int KEYCODE_5 = 53;
- public final static int KEYCODE_6 = 54;
- public final static int KEYCODE_7 = 55;
- public final static int KEYCODE_8 = 56;
- public final static int KEYCODE_9 = 57;
- public final static int KEYCODE_COLON = 58;
- public final static int KEYCODE_SEMICOLON = 59;
- public final static int KEYCODE_LESS = 60;
- public final static int KEYCODE_EQUALS = 61;
- public final static int KEYCODE_GREATER = 62;
- public final static int KEYCODE_QUESTION = 63;
- public final static int KEYCODE_AT = 64;
- public final static int KEYCODE_LEFTBRACKET = 91;
- public final static int KEYCODE_BACKSLASH = 92;
- public final static int KEYCODE_RIGHTBRACKET = 93;
- public final static int KEYCODE_CARET = 94;
- public final static int KEYCODE_UNDERSCORE = 95;
- public final static int KEYCODE_BACKQUOTE = 96;
- public final static int KEYCODE_a = 97;
- public final static int KEYCODE_b = 98;
- public final static int KEYCODE_c = 99;
- public final static int KEYCODE_d = 100;
- public final static int KEYCODE_e = 101;
- public final static int KEYCODE_f = 102;
- public final static int KEYCODE_g = 103;
- public final static int KEYCODE_h = 104;
- public final static int KEYCODE_i = 105;
- public final static int KEYCODE_j = 106;
- public final static int KEYCODE_k = 107;
- public final static int KEYCODE_l = 108;
- public final static int KEYCODE_m = 109;
- public final static int KEYCODE_n = 110;
- public final static int KEYCODE_o = 111;
- public final static int KEYCODE_p = 112;
- public final static int KEYCODE_q = 113;
- public final static int KEYCODE_r = 114;
- public final static int KEYCODE_s = 115;
- public final static int KEYCODE_t = 116;
- public final static int KEYCODE_u = 117;
- public final static int KEYCODE_v = 118;
- public final static int KEYCODE_w = 119;
- public final static int KEYCODE_x = 120;
- public final static int KEYCODE_y = 121;
- public final static int KEYCODE_z = 122;
- public final static int KEYCODE_DELETE = 127;
- // Numeric keypad
- public final static int KEYCODE_KP0 = 256;
- public final static int KEYCODE_KP1 = 257;
- public final static int KEYCODE_KP2 = 258;
- public final static int KEYCODE_KP3 = 259;
- public final static int KEYCODE_KP4 = 260;
- public final static int KEYCODE_KP5 = 261;
- public final static int KEYCODE_KP6 = 262;
- public final static int KEYCODE_KP7 = 263;
- public final static int KEYCODE_KP8 = 264;
- public final static int KEYCODE_KP9 = 265;
- public final static int KEYCODE_KP_PERIOD = 266;
- public final static int KEYCODE_KP_DIVIDE = 267;
- public final static int KEYCODE_KP_MULTIPLY = 268;
- public final static int KEYCODE_KP_MINUS = 269;
- public final static int KEYCODE_KP_PLUS = 270;
- public final static int KEYCODE_KP_ENTER = 271;
- public final static int KEYCODE_KP_EQUALS = 272;
- // Arrows + Home/End pad
- public final static int KEYCODE_UP = 273;
- public final static int KEYCODE_DOWN = 274;
- public final static int KEYCODE_RIGHT = 275;
- public final static int KEYCODE_LEFT = 276;
- public final static int KEYCODE_INSERT = 277;
- public final static int KEYCODE_HOME = 278;
- public final static int KEYCODE_END = 279;
- public final static int KEYCODE_PAGEUP = 280;
- public final static int KEYCODE_PAGEDOWN = 281;
- // Function keys
- public final static int KEYCODE_F1 = 282;
- public final static int KEYCODE_F2 = 283;
- public final static int KEYCODE_F3 = 284;
- public final static int KEYCODE_F4 = 285;
- public final static int KEYCODE_F5 = 286;
- public final static int KEYCODE_F6 = 287;
- public final static int KEYCODE_F7 = 288;
- public final static int KEYCODE_F8 = 289;
- public final static int KEYCODE_F9 = 290;
- public final static int KEYCODE_F10 = 291;
- public final static int KEYCODE_F11 = 292;
- public final static int KEYCODE_F12 = 293;
- public final static int KEYCODE_F13 = 294;
- public final static int KEYCODE_F14 = 295;
- public final static int KEYCODE_F15 = 296;
- // Key state modifier keys
- public final static int KEYCODE_NUMLOCK = 300;
- public final static int KEYCODE_CAPSLOCK = 301;
- public final static int KEYCODE_SCROLLOCK = 302;
- public final static int KEYCODE_RSHIFT = 303;
- public final static int KEYCODE_LSHIFT = 304;
- public final static int KEYCODE_RCTRL = 305;
- public final static int KEYCODE_LCTRL = 306;
- public final static int KEYCODE_RALT = 307;
- public final static int KEYCODE_LALT = 308;
- public final static int KEYCODE_RMETA = 309;
- public final static int KEYCODE_LMETA = 310;
- public final static int KEYCODE_LSUPER = 311; // Left "Windows" key
- public final static int KEYCODE_RSUPER = 312; // Right "Windows" key
- public final static int KEYCODE_MODE = 313; // "Alt Gr" key
- public final static int KEYCODE_COMPOSE = 314; // Multi-key compose key
- // Miscellaneous function keys
- public final static int KEYCODE_HELP = 315;
- public final static int KEYCODE_PRINT = 316;
- public final static int KEYCODE_SYSREQ = 317;
- public final static int KEYCODE_BREAK = 318;
- public final static int KEYCODE_MENU = 319;
- public final static int KEYCODE_POWER = 320; // Power Macintosh power key
- public final static int KEYCODE_EURO = 321; // Some european keyboards
- public final static int KEYCODE_UNDO = 322; // Atari keyboard has Undo
-
- // Android KeyEvent keycode -> ScummVM keycode
- public final static Map<Integer, Integer> androidKeyMap;
- static {
- Map<Integer, Integer> map = new HashMap<Integer, Integer>();
-
- map.put(KeyEvent.KEYCODE_DEL, KEYCODE_BACKSPACE);
- map.put(KeyEvent.KEYCODE_TAB, KEYCODE_TAB);
- map.put(KeyEvent.KEYCODE_CLEAR, KEYCODE_CLEAR);
- map.put(KeyEvent.KEYCODE_ENTER, KEYCODE_RETURN);
- //map.put(??, KEYCODE_PAUSE);
- map.put(KeyEvent.KEYCODE_BACK, KEYCODE_ESCAPE);
- map.put(KeyEvent.KEYCODE_SPACE, KEYCODE_SPACE);
- //map.put(??, KEYCODE_EXCLAIM);
- //map.put(??, KEYCODE_QUOTEDBL);
- map.put(KeyEvent.KEYCODE_POUND, KEYCODE_HASH);
- //map.put(??, KEYCODE_DOLLAR);
- //map.put(??, KEYCODE_AMPERSAND);
- map.put(KeyEvent.KEYCODE_APOSTROPHE, KEYCODE_QUOTE);
- //map.put(??, KEYCODE_LEFTPAREN);
- //map.put(??, KEYCODE_RIGHTPAREN);
- //map.put(??, KEYCODE_ASTERISK);
- map.put(KeyEvent.KEYCODE_PLUS, KEYCODE_PLUS);
- map.put(KeyEvent.KEYCODE_COMMA, KEYCODE_COMMA);
- map.put(KeyEvent.KEYCODE_MINUS, KEYCODE_MINUS);
- map.put(KeyEvent.KEYCODE_PERIOD, KEYCODE_PERIOD);
- map.put(KeyEvent.KEYCODE_SLASH, KEYCODE_SLASH);
- map.put(KeyEvent.KEYCODE_0, KEYCODE_0);
- map.put(KeyEvent.KEYCODE_1, KEYCODE_1);
- map.put(KeyEvent.KEYCODE_2, KEYCODE_2);
- map.put(KeyEvent.KEYCODE_3, KEYCODE_3);
- map.put(KeyEvent.KEYCODE_4, KEYCODE_4);
- map.put(KeyEvent.KEYCODE_5, KEYCODE_5);
- map.put(KeyEvent.KEYCODE_6, KEYCODE_6);
- map.put(KeyEvent.KEYCODE_7, KEYCODE_7);
- map.put(KeyEvent.KEYCODE_8, KEYCODE_8);
- map.put(KeyEvent.KEYCODE_9, KEYCODE_9);
- //map.put(??, KEYCODE_COLON);
- map.put(KeyEvent.KEYCODE_SEMICOLON, KEYCODE_SEMICOLON);
- //map.put(??, KEYCODE_LESS);
- map.put(KeyEvent.KEYCODE_EQUALS, KEYCODE_EQUALS);
- //map.put(??, KEYCODE_GREATER);
- //map.put(??, KEYCODE_QUESTION);
- map.put(KeyEvent.KEYCODE_AT, KEYCODE_AT);
- map.put(KeyEvent.KEYCODE_LEFT_BRACKET, KEYCODE_LEFTBRACKET);
- map.put(KeyEvent.KEYCODE_BACKSLASH, KEYCODE_BACKSLASH);
- map.put(KeyEvent.KEYCODE_RIGHT_BRACKET, KEYCODE_RIGHTBRACKET);
- //map.put(??, KEYCODE_CARET);
- //map.put(??, KEYCODE_UNDERSCORE);
- //map.put(??, KEYCODE_BACKQUOTE);
- map.put(KeyEvent.KEYCODE_A, KEYCODE_a);
- map.put(KeyEvent.KEYCODE_B, KEYCODE_b);
- map.put(KeyEvent.KEYCODE_C, KEYCODE_c);
- map.put(KeyEvent.KEYCODE_D, KEYCODE_d);
- map.put(KeyEvent.KEYCODE_E, KEYCODE_e);
- map.put(KeyEvent.KEYCODE_F, KEYCODE_f);
- map.put(KeyEvent.KEYCODE_G, KEYCODE_g);
- map.put(KeyEvent.KEYCODE_H, KEYCODE_h);
- map.put(KeyEvent.KEYCODE_I, KEYCODE_i);
- map.put(KeyEvent.KEYCODE_J, KEYCODE_j);
- map.put(KeyEvent.KEYCODE_K, KEYCODE_k);
- map.put(KeyEvent.KEYCODE_L, KEYCODE_l);
- map.put(KeyEvent.KEYCODE_M, KEYCODE_m);
- map.put(KeyEvent.KEYCODE_N, KEYCODE_n);
- map.put(KeyEvent.KEYCODE_O, KEYCODE_o);
- map.put(KeyEvent.KEYCODE_P, KEYCODE_p);
- map.put(KeyEvent.KEYCODE_Q, KEYCODE_q);
- map.put(KeyEvent.KEYCODE_R, KEYCODE_r);
- map.put(KeyEvent.KEYCODE_S, KEYCODE_s);
- map.put(KeyEvent.KEYCODE_T, KEYCODE_t);
- map.put(KeyEvent.KEYCODE_U, KEYCODE_u);
- map.put(KeyEvent.KEYCODE_V, KEYCODE_v);
- map.put(KeyEvent.KEYCODE_W, KEYCODE_w);
- map.put(KeyEvent.KEYCODE_X, KEYCODE_x);
- map.put(KeyEvent.KEYCODE_Y, KEYCODE_y);
- map.put(KeyEvent.KEYCODE_Z, KEYCODE_z);
- //map.put(KeyEvent.KEYCODE_DEL, KEYCODE_DELETE); use BACKSPACE instead
- //map.put(??, KEYCODE_KP_*);
- map.put(KeyEvent.KEYCODE_DPAD_UP, KEYCODE_UP);
- map.put(KeyEvent.KEYCODE_DPAD_DOWN, KEYCODE_DOWN);
- map.put(KeyEvent.KEYCODE_DPAD_RIGHT, KEYCODE_RIGHT);
- map.put(KeyEvent.KEYCODE_DPAD_LEFT, KEYCODE_LEFT);
- //map.put(??, KEYCODE_INSERT);
- //map.put(??, KEYCODE_HOME);
- //map.put(??, KEYCODE_END);
- //map.put(??, KEYCODE_PAGEUP);
- //map.put(??, KEYCODE_PAGEDOWN);
- //map.put(??, KEYCODE_F{1-15});
- map.put(KeyEvent.KEYCODE_NUM, KEYCODE_NUMLOCK);
- //map.put(??, KEYCODE_CAPSLOCK);
- //map.put(??, KEYCODE_SCROLLLOCK);
- map.put(KeyEvent.KEYCODE_SHIFT_RIGHT, KEYCODE_RSHIFT);
- map.put(KeyEvent.KEYCODE_SHIFT_LEFT, KEYCODE_LSHIFT);
- //map.put(??, KEYCODE_RCTRL);
- //map.put(??, KEYCODE_LCTRL);
- map.put(KeyEvent.KEYCODE_ALT_RIGHT, KEYCODE_RALT);
- map.put(KeyEvent.KEYCODE_ALT_LEFT, KEYCODE_LALT);
- // ?? META, SUPER
- // ?? MODE, COMPOSE
- // ?? HELP, PRINT, SYSREQ, BREAK, EURO, UNDO
- map.put(KeyEvent.KEYCODE_MENU, KEYCODE_MENU);
- map.put(KeyEvent.KEYCODE_POWER, KEYCODE_POWER);
-
- androidKeyMap = Collections.unmodifiableMap(map);
- }
-
- public int type;
- public boolean synthetic;
- public int kbd_keycode;
- public int kbd_ascii;
- public int kbd_flags;
- public int mouse_x;
- public int mouse_y;
- public boolean mouse_relative; // Used for trackball events
-
- public Event() {
- type = EVENT_INVALID;
- synthetic = false;
- }
-
- public Event(int type) {
- this.type = type;
- synthetic = false;
- }
-
- public static Event KeyboardEvent(int type, int keycode, int ascii,
- int flags) {
- Event e = new Event();
- e.type = type;
- e.kbd_keycode = keycode;
- e.kbd_ascii = ascii;
- e.kbd_flags = flags;
- return e;
- }
-
- public static Event MouseEvent(int type, int x, int y) {
- Event e = new Event();
- e.type = type;
- e.mouse_x = x;
- e.mouse_y = y;
- return e;
- }
-}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
index 840f3440d5..3c91d9f5dc 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
@@ -13,6 +13,8 @@ import android.util.Log;
import java.util.ArrayList;
public class PluginProvider extends BroadcastReceiver {
+ private final static String LOG_TAG = "ScummVM";
+
public final static String META_UNPACK_LIB =
"org.inodes.gus.scummvm.meta.UNPACK_LIB";
@@ -26,9 +28,9 @@ public class PluginProvider extends BroadcastReceiver {
try {
info = context.getPackageManager()
.getReceiverInfo(new ComponentName(context, this.getClass()),
- PackageManager.GET_META_DATA);
+ PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
- Log.e(this.toString(), "Error finding my own info?", e);
+ Log.e(LOG_TAG, "Error finding my own info?", e);
return;
}
@@ -36,17 +38,17 @@ public class PluginProvider extends BroadcastReceiver {
if (mylib != null) {
ArrayList<String> all_libs =
extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
-
all_libs.add(new Uri.Builder()
- .scheme("plugin")
- .authority(context.getPackageName())
- .path(mylib)
- .toString());
+ .scheme("plugin")
+ .authority(context.getPackageName())
+ .path(mylib)
+ .toString());
extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
- all_libs);
+ all_libs);
}
setResultExtras(extras);
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index 6986f3988d..8bf40ac553 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -1,450 +1,435 @@
package org.inodes.gus.scummvm;
-import android.content.Context;
+import android.util.Log;
import android.content.res.AssetManager;
+import android.view.SurfaceHolder;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import java.io.File;
-import java.util.concurrent.Semaphore;
-import java.util.Map;
import java.util.LinkedHashMap;
+public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
+ final protected static String LOG_TAG = "ScummVM";
+ final private AssetManager _asset_manager;
+ final private Object _sem_surface;
+
+ private EGL10 _egl;
+ private EGLDisplay _egl_display = EGL10.EGL_NO_DISPLAY;
+ private EGLConfig _egl_config;
+ private EGLContext _egl_context = EGL10.EGL_NO_CONTEXT;
+ private EGLSurface _egl_surface = EGL10.EGL_NO_SURFACE;
+
+ private SurfaceHolder _surface_holder;
+ private AudioTrack _audio_track;
+ private int _sample_rate = 0;
+ private int _buffer_size = 0;
+
+ private String[] _args;
+
+ final private native void create(AssetManager _asset_manager,
+ EGL10 egl, EGLDisplay egl_display,
+ AudioTrack audio_track,
+ int sample_rate, int buffer_size);
+ final private native void destroy();
+ final private native void setSurface(int width, int height);
+ final private native int main(String[] args);
+
+ // pause the engine and all native threads
+ final public native void setPause(boolean pause);
+ final public native void enableZoning(boolean enable);
+ // Feed an event to ScummVM. Safe to call from other threads.
+ final public native void pushEvent(int type, int arg1, int arg2, int arg3,
+ int arg4, int arg5);
-// At least in Android 2.1, eglCreateWindowSurface() requires an
-// EGLNativeWindowSurface object, which is hidden deep in the bowels
-// of libui. Until EGL is properly exposed, it's probably safer to
-// use the Java versions of most EGL functions :(
-
-public class ScummVM implements SurfaceHolder.Callback {
- private final static String LOG_TAG = "ScummVM.java";
+ // Callbacks from C++ peer instance
+ abstract protected void getDPI(float[] values);
+ abstract protected void displayMessageOnOSD(String msg);
+ abstract protected void setWindowCaption(String caption);
+ abstract protected String[] getPluginDirectories();
+ abstract protected void showVirtualKeyboard(boolean enable);
+ abstract protected String[] getSysArchives();
- private final int AUDIO_FRAME_SIZE = 2 * 2; // bytes. 16bit audio * stereo
- public static class AudioSetupException extends Exception {}
+ public ScummVM(AssetManager asset_manager, SurfaceHolder holder) {
+ _asset_manager = asset_manager;
+ _sem_surface = new Object();
- private long nativeScummVM; // native code hangs itself here
- boolean scummVMRunning = false;
+ holder.addCallback(this);
+ }
- private native void create(AssetManager am);
+ // SurfaceHolder callback
+ final public void surfaceCreated(SurfaceHolder holder) {
+ Log.d(LOG_TAG, "surfaceCreated");
- public ScummVM(Context context) {
- create(context.getAssets()); // Init C++ code, set nativeScummVM
+ // no need to do anything, surfaceChanged() will be called in any case
}
- private native void nativeDestroy();
+ // SurfaceHolder callback
+ final public void surfaceChanged(SurfaceHolder holder, int format,
+ int width, int height) {
+ // the orientation may reset on standby mode and the theme manager
+ // could assert when using a portrait resolution. so lets not do that.
+ if (height > width) {
+ Log.d(LOG_TAG, String.format("Ignoring surfaceChanged: %dx%d (%d)",
+ width, height, format));
+ return;
+ }
+
+ Log.d(LOG_TAG, String.format("surfaceChanged: %dx%d (%d)",
+ width, height, format));
- public synchronized void destroy() {
- if (nativeScummVM != 0) {
- nativeDestroy();
- nativeScummVM = 0;
+ synchronized(_sem_surface) {
+ _surface_holder = holder;
+ _sem_surface.notifyAll();
}
- }
- protected void finalize() {
- destroy();
- }
- // Surface creation:
- // GUI thread: create surface, release lock
- // ScummVM thread: acquire lock (block), read surface
- //
- // Surface deletion:
- // GUI thread: post event, acquire lock (block), return
- // ScummVM thread: read event, free surface, release lock
- //
- // In other words, ScummVM thread does this:
- // acquire lock
- // setup surface
- // when SCREEN_CHANGED arrives:
- // destroy surface
- // release lock
- // back to acquire lock
- static final int configSpec[] = {
- EGL10.EGL_RED_SIZE, 5,
- EGL10.EGL_GREEN_SIZE, 5,
- EGL10.EGL_BLUE_SIZE, 5,
- EGL10.EGL_DEPTH_SIZE, 0,
- EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
- EGL10.EGL_NONE,
- };
- EGL10 egl;
- EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
- EGLConfig eglConfig;
- EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
- EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
- Semaphore surfaceLock = new Semaphore(0, true);
- SurfaceHolder nativeSurface;
-
- public void surfaceCreated(SurfaceHolder holder) {
- nativeSurface = holder;
- surfaceLock.release();
+ // store values for the native code
+ setSurface(width, height);
}
- public void surfaceChanged(SurfaceHolder holder, int format,
- int width, int height) {
- // Disabled while I debug GL problems
- //pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
- }
+ // SurfaceHolder callback
+ final public void surfaceDestroyed(SurfaceHolder holder) {
+ Log.d(LOG_TAG, "surfaceDestroyed");
- public void surfaceDestroyed(SurfaceHolder holder) {
- pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
- try {
- surfaceLock.acquire();
- } catch (InterruptedException e) {
- Log.e(this.toString(),
- "Interrupted while waiting for surface lock", e);
+ synchronized(_sem_surface) {
+ _surface_holder = null;
+ _sem_surface.notifyAll();
}
+
+ // clear values for the native code
+ setSurface(0, 0);
}
- // For debugging
- private static final Map<String, Integer> attribs;
- static {
- attribs = new LinkedHashMap<String, Integer>();
- attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID);
- attribs.put("BUFFER_SIZE", EGL10.EGL_BUFFER_SIZE);
- attribs.put("RED_SIZE", EGL10.EGL_RED_SIZE);
- attribs.put("GREEN_SIZE", EGL10.EGL_GREEN_SIZE);
- attribs.put("BLUE_SIZE", EGL10.EGL_BLUE_SIZE);
- attribs.put("ALPHA_SIZE", EGL10.EGL_ALPHA_SIZE);
- //attribs.put("BIND_TO_RGB", EGL10.EGL_BIND_TO_TEXTURE_RGB);
- //attribs.put("BIND_TO_RGBA", EGL10.EGL_BIND_TO_TEXTURE_RGBA);
- attribs.put("CONFIG_CAVEAT", EGL10.EGL_CONFIG_CAVEAT);
- attribs.put("DEPTH_SIZE", EGL10.EGL_DEPTH_SIZE);
- attribs.put("LEVEL", EGL10.EGL_LEVEL);
- attribs.put("MAX_PBUFFER_WIDTH", EGL10.EGL_MAX_PBUFFER_WIDTH);
- attribs.put("MAX_PBUFFER_HEIGHT", EGL10.EGL_MAX_PBUFFER_HEIGHT);
- attribs.put("MAX_PBUFFER_PIXELS", EGL10.EGL_MAX_PBUFFER_PIXELS);
- //attribs.put("MAX_SWAP_INTERVAL", EGL10.EGL_MAX_SWAP_INTERVAL);
- //attribs.put("MIN_SWAP_INTERVAL", EGL10.EGL_MIN_SWAP_INTERVAL);
- attribs.put("NATIVE_RENDERABLE", EGL10.EGL_NATIVE_RENDERABLE);
- attribs.put("NATIVE_VISUAL_ID", EGL10.EGL_NATIVE_VISUAL_ID);
- attribs.put("NATIVE_VISUAL_TYPE", EGL10.EGL_NATIVE_VISUAL_TYPE);
- attribs.put("SAMPLE_BUFFERS", EGL10.EGL_SAMPLE_BUFFERS);
- attribs.put("SAMPLES", EGL10.EGL_SAMPLES);
- attribs.put("STENCIL_SIZE", EGL10.EGL_STENCIL_SIZE);
- attribs.put("SURFACE_TYPE", EGL10.EGL_SURFACE_TYPE);
- attribs.put("TRANSPARENT_TYPE", EGL10.EGL_TRANSPARENT_TYPE);
- attribs.put("TRANSPARENT_RED_VALUE", EGL10.EGL_TRANSPARENT_RED_VALUE);
- attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE);
- attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE);
+ final public void setArgs(String[] args) {
+ _args = args;
}
- private void dumpEglConfig(EGLConfig config) {
- int[] value = new int[1];
- for (Map.Entry<String, Integer> entry : attribs.entrySet()) {
- egl.eglGetConfigAttrib(eglDisplay, config,
- entry.getValue(), value);
- if (value[0] == EGL10.EGL_NONE)
- Log.d(LOG_TAG, entry.getKey() + ": NONE");
- else
- Log.d(LOG_TAG, String.format("%s: %d",
- entry.getKey(), value[0]));
+
+ final public void run() {
+ try {
+ initAudio();
+ initEGL();
+
+ // wait for the surfaceChanged callback
+ synchronized(_sem_surface) {
+ while (_surface_holder == null)
+ _sem_surface.wait();
+ }
+ } catch (Exception e) {
+ deinitEGL();
+ deinitAudio();
+
+ throw new RuntimeException("Error preparing the ScummVM thread", e);
}
+
+ create(_asset_manager, _egl, _egl_display,
+ _audio_track, _sample_rate, _buffer_size);
+
+ int res = main(_args);
+
+ destroy();
+
+ deinitEGL();
+ deinitAudio();
+
+ // On exit, tear everything down for a fresh restart next time.
+ System.exit(res);
}
- // Called by ScummVM thread (from initBackend)
- private void createScummVMGLContext() {
- egl = (EGL10)EGLContext.getEGL();
- eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ final private void initEGL() throws Exception {
+ _egl = (EGL10)EGLContext.getEGL();
+ _egl_display = _egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
int[] version = new int[2];
- egl.eglInitialize(eglDisplay, version);
+ _egl.eglInitialize(_egl_display, version);
+
int[] num_config = new int[1];
- egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
+ _egl.eglGetConfigs(_egl_display, null, 0, num_config);
final int numConfigs = num_config[0];
+
if (numConfigs <= 0)
- throw new IllegalArgumentException("No configs match configSpec");
+ throw new IllegalArgumentException("No EGL configs");
EGLConfig[] configs = new EGLConfig[numConfigs];
- egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
- num_config);
-
- if (false) {
- Log.d(LOG_TAG,
- String.format("Found %d EGL configurations.", numConfigs));
- for (EGLConfig config : configs)
- dumpEglConfig(config);
- }
+ _egl.eglGetConfigs(_egl_display, configs, numConfigs, num_config);
// Android's eglChooseConfig is busted in several versions and
- // devices so we have to filter/rank the configs again ourselves.
- eglConfig = chooseEglConfig(configs);
- if (false) {
- Log.d(LOG_TAG,
- String.format("Chose EGL config from %d possibilities.", numConfigs));
- dumpEglConfig(eglConfig);
- }
+ // devices so we have to filter/rank the configs ourselves.
+ _egl_config = chooseEglConfig(configs);
+
+ _egl_context = _egl.eglCreateContext(_egl_display, _egl_config,
+ EGL10.EGL_NO_CONTEXT, null);
- eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
- EGL10.EGL_NO_CONTEXT, null);
- if (eglContext == EGL10.EGL_NO_CONTEXT)
- throw new RuntimeException("Failed to create context");
+ if (_egl_context == EGL10.EGL_NO_CONTEXT)
+ throw new Exception(String.format("Failed to create context: 0x%x",
+ _egl.eglGetError()));
}
- private EGLConfig chooseEglConfig(EGLConfig[] configs) {
- int best = 0;
- int bestScore = -1;
- int[] value = new int[1];
- for (int i = 0; i < configs.length; i++) {
- EGLConfig config = configs[i];
- int score = 10000;
- egl.eglGetConfigAttrib(eglDisplay, config,
- EGL10.EGL_SURFACE_TYPE, value);
- if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0)
- continue; // must have
-
- egl.eglGetConfigAttrib(eglDisplay, config,
- EGL10.EGL_CONFIG_CAVEAT, value);
- if (value[0] != EGL10.EGL_NONE)
- score -= 1000;
+ // Callback from C++ peer instance
+ final protected EGLSurface initSurface() throws Exception {
+ _egl_surface = _egl.eglCreateWindowSurface(_egl_display, _egl_config,
+ _surface_holder, null);
- // Must be at least 555, but then smaller is better
- final int[] colorBits = {EGL10.EGL_RED_SIZE,
- EGL10.EGL_GREEN_SIZE,
- EGL10.EGL_BLUE_SIZE,
- EGL10.EGL_ALPHA_SIZE};
- for (int component : colorBits) {
- egl.eglGetConfigAttrib(eglDisplay, config,
- component, value);
- if (value[0] >= 5)
- score += 10; // boost if >5 bits accuracy
- score -= value[0]; // penalize for wasted bits
- }
+ if (_egl_surface == EGL10.EGL_NO_SURFACE)
+ throw new Exception(String.format(
+ "eglCreateWindowSurface failed: 0x%x", _egl.eglGetError()));
- egl.eglGetConfigAttrib(eglDisplay, config,
- EGL10.EGL_DEPTH_SIZE, value);
- score -= value[0]; // penalize for wasted bits
+ _egl.eglMakeCurrent(_egl_display, _egl_surface, _egl_surface,
+ _egl_context);
- if (score > bestScore) {
- best = i;
- bestScore = score;
- }
- }
+ GL10 gl = (GL10)_egl_context.getGL();
- if (bestScore < 0) {
- Log.e(LOG_TAG, "Unable to find an acceptable EGL config, expect badness.");
- return configs[0];
- }
+ Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
+ _egl.eglQueryString(_egl_display, EGL10.EGL_VERSION),
+ _egl.eglQueryString(_egl_display, EGL10.EGL_VENDOR),
+ gl.glGetString(GL10.GL_VERSION),
+ gl.glGetString(GL10.GL_RENDERER),
+ gl.glGetString(GL10.GL_VENDOR)));
- return configs[best];
+ return _egl_surface;
}
- // Called by ScummVM thread
- static private boolean _log_version = true;
- protected void setupScummVMSurface() {
- try {
- surfaceLock.acquire();
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e);
- return;
- }
- eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
- nativeSurface, null);
- if (eglSurface == EGL10.EGL_NO_SURFACE)
- Log.e(LOG_TAG, "CreateWindowSurface failed!");
- egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
-
- GL10 gl = (GL10)eglContext.getGL();
-
- if (_log_version) {
- Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
- egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
- egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
- gl.glGetString(GL10.GL_VERSION),
- gl.glGetString(GL10.GL_RENDERER),
- gl.glGetString(GL10.GL_VENDOR)));
- _log_version = false; // only log this once
+ // Callback from C++ peer instance
+ final protected void deinitSurface() {
+ if (_egl_display != EGL10.EGL_NO_DISPLAY) {
+ _egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+
+ if (_egl_surface != EGL10.EGL_NO_SURFACE)
+ _egl.eglDestroySurface(_egl_display, _egl_surface);
}
- int[] value = new int[1];
- egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value);
- int width = value[0];
- egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value);
- int height = value[0];
- Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height));
- setSurfaceSize(width, height);
+ _egl_surface = EGL10.EGL_NO_SURFACE;
}
- // Called by ScummVM thread
- protected void destroyScummVMSurface() {
- if (eglSurface != null) {
- egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- egl.eglDestroySurface(eglDisplay, eglSurface);
- eglSurface = EGL10.EGL_NO_SURFACE;
+ final private void deinitEGL() {
+ if (_egl_display != EGL10.EGL_NO_DISPLAY) {
+ _egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+
+ if (_egl_surface != EGL10.EGL_NO_SURFACE)
+ _egl.eglDestroySurface(_egl_display, _egl_surface);
+
+ if (_egl_context != EGL10.EGL_NO_CONTEXT)
+ _egl.eglDestroyContext(_egl_display, _egl_context);
+
+ _egl.eglTerminate(_egl_display);
}
- surfaceLock.release();
+ _egl_surface = EGL10.EGL_NO_SURFACE;
+ _egl_context = EGL10.EGL_NO_CONTEXT;
+ _egl_config = null;
+ _egl_display = EGL10.EGL_NO_DISPLAY;
+ _egl = null;
}
- public void setSurface(SurfaceHolder holder) {
- holder.addCallback(this);
- }
+ final private void initAudio() throws Exception {
+ _sample_rate = AudioTrack.getNativeOutputSampleRate(
+ AudioManager.STREAM_MUSIC);
+ _buffer_size = AudioTrack.getMinBufferSize(_sample_rate,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT);
+
+ // ~50ms
+ int buffer_size_want = (_sample_rate * 2 * 2 / 20) & ~1023;
+
+ if (_buffer_size < buffer_size_want) {
+ Log.w(LOG_TAG, String.format(
+ "adjusting audio buffer size (was: %d)", _buffer_size));
- final public boolean swapBuffers() {
- if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) {
- int error = egl.eglGetError();
- Log.w(LOG_TAG, String.format("eglSwapBuffers exited with error 0x%x", error));
- if (error == EGL11.EGL_CONTEXT_LOST)
- return false;
+ _buffer_size = buffer_size_want;
}
- return true;
- }
- // Set scummvm config options
- final public native static void loadConfigFile(String path);
- final public native static void setConfMan(String key, int value);
- final public native static void setConfMan(String key, String value);
- final public native void enableZoning(boolean enable);
- final public native void setSurfaceSize(int width, int height);
+ Log.i(LOG_TAG, String.format("Using %d bytes buffer for %dHz audio",
+ _buffer_size, _sample_rate));
- // Feed an event to ScummVM. Safe to call from other threads.
- final public native void pushEvent(Event e);
+ _audio_track = new AudioTrack(AudioManager.STREAM_MUSIC,
+ _sample_rate,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ _buffer_size,
+ AudioTrack.MODE_STREAM);
- final private native void audioMixCallback(byte[] buf);
+ if (_audio_track.getState() != AudioTrack.STATE_INITIALIZED)
+ throw new Exception(
+ String.format("Error initialising AudioTrack: %d",
+ _audio_track.getState()));
+ }
- // Runs the actual ScummVM program and returns when it does.
- // This should not be called from multiple threads simultaneously...
- final public native int scummVMMain(String[] argv);
+ final private void deinitAudio() {
+ if (_audio_track != null)
+ _audio_track.stop();
- // Callbacks from C++ peer instance
- //protected GraphicsMode[] getSupportedGraphicsModes() {}
- protected void displayMessageOnOSD(String msg) {}
- protected void setWindowCaption(String caption) {}
- protected void showVirtualKeyboard(boolean enable) {}
- protected String[] getSysArchives() { return new String[0]; }
- protected String[] getPluginDirectories() { return new String[0]; }
- protected void initBackend() throws AudioSetupException {
- createScummVMGLContext();
- initAudio();
+ _audio_track = null;
+ _buffer_size = 0;
+ _sample_rate = 0;
}
- private static class AudioThread extends Thread {
- final private int buf_size;
- private boolean is_paused = false;
- final private ScummVM scummvm;
- final private AudioTrack audio_track;
-
- AudioThread(ScummVM scummvm, AudioTrack audio_track, int buf_size) {
- super("AudioThread");
- this.scummvm = scummvm;
- this.audio_track = audio_track;
- this.buf_size = buf_size;
- setPriority(Thread.MAX_PRIORITY);
- setDaemon(true);
- }
+ private static final int[] s_eglAttribs = {
+ EGL10.EGL_CONFIG_ID,
+ EGL10.EGL_BUFFER_SIZE,
+ EGL10.EGL_RED_SIZE,
+ EGL10.EGL_GREEN_SIZE,
+ EGL10.EGL_BLUE_SIZE,
+ EGL10.EGL_ALPHA_SIZE,
+ EGL10.EGL_CONFIG_CAVEAT,
+ EGL10.EGL_DEPTH_SIZE,
+ EGL10.EGL_LEVEL,
+ EGL10.EGL_MAX_PBUFFER_WIDTH,
+ EGL10.EGL_MAX_PBUFFER_HEIGHT,
+ EGL10.EGL_MAX_PBUFFER_PIXELS,
+ EGL10.EGL_NATIVE_RENDERABLE,
+ EGL10.EGL_NATIVE_VISUAL_ID,
+ EGL10.EGL_NATIVE_VISUAL_TYPE,
+ EGL10.EGL_SAMPLE_BUFFERS,
+ EGL10.EGL_SAMPLES,
+ EGL10.EGL_STENCIL_SIZE,
+ EGL10.EGL_SURFACE_TYPE,
+ EGL10.EGL_TRANSPARENT_TYPE,
+ EGL10.EGL_TRANSPARENT_RED_VALUE,
+ EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+ EGL10.EGL_TRANSPARENT_BLUE_VALUE
+ };
- public void pauseAudio() {
- synchronized (this) {
- is_paused = true;
+ final private class EglAttribs extends LinkedHashMap<Integer, Integer> {
+ public EglAttribs(EGLConfig config) {
+ super(s_eglAttribs.length);
+
+ int[] value = new int[1];
+
+ for (int i : s_eglAttribs) {
+ _egl.eglGetConfigAttrib(_egl_display, config, i, value);
+
+ put(i, value[0]);
}
- audio_track.pause();
}
- public void resumeAudio() {
- synchronized (this) {
- is_paused = false;
- notifyAll();
- }
- audio_track.play();
+ private int weightBits(int attr, int size) {
+ final int value = get(attr);
+
+ int score = 0;
+
+ if (value == size || (size > 0 && value > size))
+ score += 10;
+
+ // penalize for wasted bits
+ score -= value - size;
+
+ return score;
}
- public void run() {
- byte[] buf = new byte[buf_size];
- audio_track.play();
- int offset = 0;
- try {
- while (true) {
- synchronized (this) {
- while (is_paused)
- wait();
- }
-
- if (offset == buf.length) {
- // Grab new audio data
- scummvm.audioMixCallback(buf);
- offset = 0;
- }
- int len = buf.length - offset;
- int ret = audio_track.write(buf, offset, len);
- if (ret < 0) {
- Log.w(LOG_TAG, String.format(
- "AudioTrack.write(%dB) returned error %d",
- buf.length, ret));
- break;
- } else if (ret != len) {
- Log.w(LOG_TAG, String.format(
- "Short audio write. Wrote %dB, not %dB",
- ret, buf.length));
- // Buffer is full, so yield cpu for a while
- Thread.sleep(100);
- }
- offset += ret;
- }
- } catch (InterruptedException e) {
- Log.e(this.toString(), "Audio thread interrupted", e);
- }
+ public int weight() {
+ int score = 10000;
+
+ if (get(EGL10.EGL_CONFIG_CAVEAT) != EGL10.EGL_NONE)
+ score -= 1000;
+
+ // less MSAA is better
+ score -= get(EGL10.EGL_SAMPLES) * 100;
+
+ // Must be at least 565, but then smaller is better
+ score += weightBits(EGL10.EGL_RED_SIZE, 5);
+ score += weightBits(EGL10.EGL_GREEN_SIZE, 6);
+ score += weightBits(EGL10.EGL_BLUE_SIZE, 5);
+ score += weightBits(EGL10.EGL_ALPHA_SIZE, 0);
+ score += weightBits(EGL10.EGL_DEPTH_SIZE, 0);
+ score += weightBits(EGL10.EGL_STENCIL_SIZE, 0);
+
+ return score;
}
- }
- private AudioThread audio_thread;
- final public int audioSampleRate() {
- return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
- }
+ public String toString() {
+ String s;
- private void initAudio() throws AudioSetupException {
- int sample_rate = audioSampleRate();
- int buf_size =
- AudioTrack.getMinBufferSize(sample_rate,
- AudioFormat.CHANNEL_CONFIGURATION_STEREO,
- AudioFormat.ENCODING_PCM_16BIT);
- if (buf_size < 0) {
- int guess = AUDIO_FRAME_SIZE * sample_rate / 100; // 10ms of audio
- Log.w(LOG_TAG, String.format(
- "Unable to get min audio buffer size (error %d). Guessing %dB.",
- buf_size, guess));
- buf_size = guess;
+ if (get(EGL10.EGL_ALPHA_SIZE) > 0)
+ s = String.format("[%d] RGBA%d%d%d%d",
+ get(EGL10.EGL_CONFIG_ID),
+ get(EGL10.EGL_RED_SIZE),
+ get(EGL10.EGL_GREEN_SIZE),
+ get(EGL10.EGL_BLUE_SIZE),
+ get(EGL10.EGL_ALPHA_SIZE));
+ else
+ s = String.format("[%d] RGB%d%d%d",
+ get(EGL10.EGL_CONFIG_ID),
+ get(EGL10.EGL_RED_SIZE),
+ get(EGL10.EGL_GREEN_SIZE),
+ get(EGL10.EGL_BLUE_SIZE));
+
+ if (get(EGL10.EGL_DEPTH_SIZE) > 0)
+ s += String.format(" D%d", get(EGL10.EGL_DEPTH_SIZE));
+
+ if (get(EGL10.EGL_STENCIL_SIZE) > 0)
+ s += String.format(" S%d", get(EGL10.EGL_STENCIL_SIZE));
+
+ if (get(EGL10.EGL_SAMPLES) > 0)
+ s += String.format(" MSAAx%d", get(EGL10.EGL_SAMPLES));
+
+ if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) > 0)
+ s += " W";
+ if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_PBUFFER_BIT) > 0)
+ s += " P";
+ if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_PIXMAP_BIT) > 0)
+ s += " X";
+
+ switch (get(EGL10.EGL_CONFIG_CAVEAT)) {
+ case EGL10.EGL_NONE:
+ break;
+
+ case EGL10.EGL_SLOW_CONFIG:
+ s += " SLOW";
+ break;
+
+ case EGL10.EGL_NON_CONFORMANT_CONFIG:
+ s += " NON_CONFORMANT";
+
+ default:
+ s += String.format(" unknown CAVEAT 0x%x",
+ get(EGL10.EGL_CONFIG_CAVEAT));
+ }
+
+ return s;
}
- Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",
- buf_size, sample_rate));
- AudioTrack audio_track =
- new AudioTrack(AudioManager.STREAM_MUSIC,
- sample_rate,
- AudioFormat.CHANNEL_CONFIGURATION_STEREO,
- AudioFormat.ENCODING_PCM_16BIT,
- buf_size,
- AudioTrack.MODE_STREAM);
- if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) {
- Log.e(LOG_TAG, "Error initialising Android audio system.");
- throw new AudioSetupException();
+ };
+
+ final private EGLConfig chooseEglConfig(EGLConfig[] configs) {
+ EGLConfig res = configs[0];
+ int bestScore = -1;
+
+ Log.d(LOG_TAG, "EGL configs:");
+
+ for (EGLConfig config : configs) {
+ EglAttribs attr = new EglAttribs(config);
+
+ // must have
+ if ((attr.get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) == 0)
+ continue;
+
+ int score = attr.weight();
+
+ Log.d(LOG_TAG, String.format("%s (%d)", attr.toString(), score));
+
+ if (score > bestScore) {
+ res = config;
+ bestScore = score;
+ }
}
- audio_thread = new AudioThread(this, audio_track, buf_size);
- audio_thread.start();
- }
+ if (bestScore < 0)
+ Log.e(LOG_TAG,
+ "Unable to find an acceptable EGL config, expect badness.");
- public void pause() {
- audio_thread.pauseAudio();
- // TODO: need to pause engine too
- }
+ Log.d(LOG_TAG, String.format("Chosen EGL config: %s",
+ new EglAttribs(res).toString()));
- public void resume() {
- // TODO: need to resume engine too
- audio_thread.resumeAudio();
+ return res;
}
static {
@@ -452,15 +437,16 @@ public class ScummVM implements SurfaceHolder.Callback {
final boolean sleep_for_debugger = false;
if (sleep_for_debugger) {
try {
- Thread.sleep(20*1000);
+ Thread.sleep(20 * 1000);
} catch (InterruptedException e) {
}
}
- //System.loadLibrary("scummvm");
File cache_dir = ScummVMApplication.getLastCacheDir();
String libname = System.mapLibraryName("scummvm");
File libpath = new File(cache_dir, libname);
+
System.load(libpath.getPath());
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index b37b2b8a52..1978b690d0 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -3,41 +3,27 @@ package org.inodes.gus.scummvm;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
-import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
-import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.SurfaceView;
-import android.view.View;
-import android.view.ViewConfiguration;
+import android.view.SurfaceHolder;
+import android.view.MotionEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
-import java.io.IOException;
-
public class ScummVMActivity extends Activity {
- private boolean _do_right_click;
- private boolean _last_click_was_right;
-
- // game pixels to move per trackball/dpad event.
- // FIXME: replace this with proper mouse acceleration
- private final static int TRACKBALL_SCALE = 2;
private class MyScummVM extends ScummVM {
- private boolean scummvmRunning = false;
-
private boolean usingSmallScreen() {
// Multiple screen sizes came in with Android 1.6. Have
// to use reflection in order to continue supporting 1.5
// devices :(
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
try {
// This 'density' term is very confusing.
int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null);
@@ -48,32 +34,27 @@ public class ScummVMActivity extends Activity {
}
}
- public MyScummVM() {
- super(ScummVMActivity.this);
+ public MyScummVM(SurfaceHolder holder) {
+ super(ScummVMActivity.this.getAssets(), holder);
// Enable ScummVM zoning on 'small' screens.
- enableZoning(usingSmallScreen());
+ // FIXME make this optional for the user
+ // disabled for now since it crops too much
+ //enableZoning(usingSmallScreen());
}
@Override
- protected void initBackend() throws ScummVM.AudioSetupException {
- synchronized (this) {
- scummvmRunning = true;
- notifyAll();
- }
- super.initBackend();
- }
+ protected void getDPI(float[] values) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
- public void waitUntilRunning() throws InterruptedException {
- synchronized (this) {
- while (!scummvmRunning)
- wait();
- }
+ values[0] = metrics.xdpi;
+ values[1] = metrics.ydpi;
}
@Override
protected void displayMessageOnOSD(String msg) {
- Log.i(this.toString(), "OSD: " + msg);
+ Log.i(LOG_TAG, "OSD: " + msg);
Toast.makeText(ScummVMActivity.this, msg, Toast.LENGTH_LONG).show();
}
@@ -95,24 +76,28 @@ public class ScummVMActivity extends Activity {
@Override
protected void showVirtualKeyboard(final boolean enable) {
- if (getResources().getConfiguration().keyboard ==
- Configuration.KEYBOARD_NOKEYS) {
- runOnUiThread(new Runnable() {
- public void run() {
- showKeyboard(enable);
- }
- });
- }
+ runOnUiThread(new Runnable() {
+ public void run() {
+ showKeyboard(enable);
+ }
+ });
}
+
+ @Override
+ protected String[] getSysArchives() {
+ return new String[0];
+ }
+
}
- private MyScummVM scummvm;
- private Thread scummvm_thread;
+
+ private MyScummVM _scummvm;
+ private ScummVMEvents _events;
+ private Thread _scummvm_thread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- _do_right_click = false;
setVolumeControlStream(AudioManager.STREAM_MUSIC);
setContentView(R.layout.main);
@@ -126,337 +111,110 @@ public class ScummVMActivity extends Activity {
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.no_sdcard)
.setNegativeButton(R.string.quit,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog,
- int which) {
- finish();
- }
- })
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ finish();
+ }
+ })
.show();
+
return;
}
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
- main_surface.setOnTouchListener(new View.OnTouchListener() {
- public boolean onTouch(View v, MotionEvent event) {
- return onTouchEvent(event);
- }
- });
- main_surface.setOnKeyListener(new View.OnKeyListener() {
- public boolean onKey(View v, int code, KeyEvent ev) {
- return onKeyDown(code, ev);
- }
- });
+
main_surface.requestFocus();
- // Start ScummVM
- scummvm = new MyScummVM();
- scummvm_thread = new Thread(new Runnable() {
- public void run() {
- try {
- runScummVM();
- } catch (Exception e) {
- Log.e("ScummVM", "Fatal error in ScummVM thread", e);
- new AlertDialog.Builder(ScummVMActivity.this)
- .setTitle("Error")
- .setMessage(e.toString())
- .setIcon(android.R.drawable.ic_dialog_alert)
- .show();
- finish();
- }
- }
- }, "ScummVM");
- scummvm_thread.start();
-
- // Block UI thread until ScummVM has started. In particular,
- // this means that surface and event callbacks should be safe
- // after this point.
- try {
- scummvm.waitUntilRunning();
- } catch (InterruptedException e) {
- Log.e(this.toString(),
- "Interrupted while waiting for ScummVM.initBackend", e);
- finish();
- }
+ getFilesDir().mkdirs();
- scummvm.setSurface(main_surface.getHolder());
- }
+ // Start ScummVM
+ _scummvm = new MyScummVM(main_surface.getHolder());
- // Runs in another thread
- private void runScummVM() throws IOException {
- getFilesDir().mkdirs();
- String[] args = {
- "ScummVM-lib",
+ _scummvm.setArgs(new String[] {
+ "ScummVM",
"--config=" + getFileStreamPath("scummvmrc").getPath(),
"--path=" + Environment.getExternalStorageDirectory().getPath(),
"--gui-theme=scummmodern",
- "--savepath=" + getDir("saves", 0).getPath(),
- };
+ "--savepath=" + getDir("saves", 0).getPath()
+ });
- int ret = scummvm.scummVMMain(args);
+ _events = new ScummVMEvents(this, _scummvm);
- // On exit, tear everything down for a fresh
- // restart next time.
- System.exit(ret);
- }
+ main_surface.setOnKeyListener(_events);
+ main_surface.setOnTouchListener(_events);
- private boolean was_paused = false;
+ _scummvm_thread = new Thread(_scummvm, "ScummVM");
+ _scummvm_thread.start();
+ }
@Override
- public void onPause() {
- if (scummvm != null) {
- was_paused = true;
- scummvm.pause();
- }
- super.onPause();
+ public void onStart() {
+ Log.d(ScummVM.LOG_TAG, "onStart");
+
+ super.onStart();
}
@Override
public void onResume() {
+ Log.d(ScummVM.LOG_TAG, "onResume");
+
super.onResume();
- if (scummvm != null && was_paused)
- scummvm.resume();
- was_paused = false;
+
+ if (_scummvm != null)
+ _scummvm.setPause(false);
}
@Override
- public void onStop() {
- if (scummvm != null) {
- scummvm.pushEvent(new Event(Event.EVENT_QUIT));
- try {
- scummvm_thread.join(1000); // 1s timeout
- } catch (InterruptedException e) {
- Log.i(this.toString(),
- "Error while joining ScummVM thread", e);
- }
- }
- super.onStop();
- }
+ public void onPause() {
+ Log.d(ScummVM.LOG_TAG, "onPause");
- static final int MSG_MENU_LONG_PRESS = 1;
- private final Handler keycodeMenuTimeoutHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_MENU_LONG_PRESS) {
- InputMethodManager imm = (InputMethodManager)
- getSystemService(INPUT_METHOD_SERVICE);
- if (imm != null)
- imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
- }
- }
- };
+ super.onPause();
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent kevent) {
- return onKeyDown(keyCode, kevent);
+ if (_scummvm != null)
+ _scummvm.setPause(true);
}
@Override
- public boolean onKeyMultiple(int keyCode, int repeatCount,
- KeyEvent kevent) {
- return onKeyDown(keyCode, kevent);
+ public void onStop() {
+ Log.d(ScummVM.LOG_TAG, "onStop");
+
+ super.onStop();
}
@Override
- public boolean onKeyDown(int keyCode, KeyEvent kevent) {
- // Filter out "special" keys
- switch (keyCode) {
- case KeyEvent.KEYCODE_MENU:
- // Have to reimplement hold-down-menu-brings-up-softkeybd
- // ourselves, since we are otherwise hijacking the menu
- // key :(
- // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
- // for the usual Android implementation of this feature.
- if (kevent.getRepeatCount() > 0)
- // Ignore keyrepeat for menu
- return false;
- boolean timeout_fired = false;
- if (getResources().getConfiguration().keyboard ==
- Configuration.KEYBOARD_NOKEYS) {
- timeout_fired = !keycodeMenuTimeoutHandler.hasMessages(MSG_MENU_LONG_PRESS);
- keycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
- if (kevent.getAction() == KeyEvent.ACTION_DOWN) {
- keycodeMenuTimeoutHandler.sendMessageDelayed(
- keycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
- ViewConfiguration.getLongPressTimeout());
- return true;
- }
- }
- if (kevent.getAction() == KeyEvent.ACTION_UP) {
- if (!timeout_fired)
- scummvm.pushEvent(new Event(Event.EVENT_MAINMENU));
- return true;
- }
- return false;
- case KeyEvent.KEYCODE_CAMERA:
- case KeyEvent.KEYCODE_SEARCH:
- _do_right_click = (kevent.getAction() == KeyEvent.ACTION_DOWN);
- return true;
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT: {
- // HTC Hero doesn't seem to generate
- // MotionEvent.ACTION_DOWN events on trackball press :(
- // We'll have to just fake one here.
- // Some other handsets lack a trackball, so the DPAD is
- // the only way of moving the cursor.
- int motion_action;
- // FIXME: this logic is a mess.
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- switch (kevent.getAction()) {
- case KeyEvent.ACTION_DOWN:
- motion_action = MotionEvent.ACTION_DOWN;
- break;
- case KeyEvent.ACTION_UP:
- motion_action = MotionEvent.ACTION_UP;
- break;
- default: // ACTION_MULTIPLE
- return false;
- }
- } else
- motion_action = MotionEvent.ACTION_MOVE;
-
- Event e = new Event(getEventType(motion_action));
- e.mouse_x = 0;
- e.mouse_y = 0;
- e.mouse_relative = true;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- e.mouse_y = -TRACKBALL_SCALE;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- e.mouse_y = TRACKBALL_SCALE;
- break;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- e.mouse_x = -TRACKBALL_SCALE;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- e.mouse_x = TRACKBALL_SCALE;
- break;
- }
- scummvm.pushEvent(e);
- return true;
- }
- case KeyEvent.KEYCODE_BACK:
- // skip isSystem() check and fall through to main code
- break;
- default:
- if (kevent.isSystem())
- return false;
- }
+ public void onDestroy() {
+ Log.d(ScummVM.LOG_TAG, "onDestroy");
- // FIXME: what do I need to do for composed characters?
-
- Event e = new Event();
-
- switch (kevent.getAction()) {
- case KeyEvent.ACTION_DOWN:
- e.type = Event.EVENT_KEYDOWN;
- e.synthetic = false;
- break;
- case KeyEvent.ACTION_UP:
- e.type = Event.EVENT_KEYUP;
- e.synthetic = false;
- break;
- case KeyEvent.ACTION_MULTIPLE:
- // e.type is handled below
- e.synthetic = true;
- break;
- default:
- return false;
- }
+ super.onDestroy();
- e.kbd_keycode = Event.androidKeyMap.containsKey(keyCode) ?
- Event.androidKeyMap.get(keyCode) : Event.KEYCODE_INVALID;
- e.kbd_ascii = kevent.getUnicodeChar();
- if (e.kbd_ascii == 0)
- e.kbd_ascii = e.kbd_keycode; // scummvm keycodes are mostly ascii
-
-
- e.kbd_flags = 0;
- if (kevent.isAltPressed())
- e.kbd_flags |= Event.KBD_ALT;
- if (kevent.isSymPressed()) // no ctrl key in android, so use sym (?)
- e.kbd_flags |= Event.KBD_CTRL;
- if (kevent.isShiftPressed()) {
- if (keyCode >= KeyEvent.KEYCODE_0 &&
- keyCode <= KeyEvent.KEYCODE_9) {
- // Shift+number -> convert to F* key
- int offset = keyCode == KeyEvent.KEYCODE_0 ?
- 10 : keyCode - KeyEvent.KEYCODE_1; // turn 0 into 10
- e.kbd_keycode = Event.KEYCODE_F1 + offset;
- e.kbd_ascii = Event.ASCII_F1 + offset;
- } else
- e.kbd_flags |= Event.KBD_SHIFT;
- }
+ if (_events != null) {
+ _events.sendQuitEvent();
- if (kevent.getAction() == KeyEvent.ACTION_MULTIPLE) {
- for (int i = 0; i <= kevent.getRepeatCount(); i++) {
- e.type = Event.EVENT_KEYDOWN;
- scummvm.pushEvent(e);
- e.type = Event.EVENT_KEYUP;
- scummvm.pushEvent(e);
+ try {
+ // 1s timeout
+ _scummvm_thread.join(1000);
+ } catch (InterruptedException e) {
+ Log.i(ScummVM.LOG_TAG, "Error while joining ScummVM thread", e);
}
- } else
- scummvm.pushEvent(e);
-
- return true;
- }
- private int getEventType(int action) {
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- _last_click_was_right = _do_right_click;
- return _last_click_was_right ?
- Event.EVENT_RBUTTONDOWN : Event.EVENT_LBUTTONDOWN;
- case MotionEvent.ACTION_UP:
- return _last_click_was_right ?
- Event.EVENT_RBUTTONUP : Event.EVENT_LBUTTONUP;
- case MotionEvent.ACTION_MOVE:
- return Event.EVENT_MOUSEMOVE;
- default:
- return Event.EVENT_INVALID;
+ _scummvm = null;
}
}
@Override
- public boolean onTrackballEvent(MotionEvent event) {
- int type = getEventType(event.getAction());
- if (type == Event.EVENT_INVALID)
- return false;
-
- Event e = new Event(type);
- e.mouse_x =
- (int)(event.getX() * event.getXPrecision()) * TRACKBALL_SCALE;
- e.mouse_y =
- (int)(event.getY() * event.getYPrecision()) * TRACKBALL_SCALE;
- e.mouse_relative = true;
- scummvm.pushEvent(e);
-
- return true;
- }
+ public boolean onTrackballEvent(MotionEvent e) {
+ if (_events != null)
+ return _events.onTrackballEvent(e);
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int type = getEventType(event.getAction());
- if (type == Event.EVENT_INVALID)
- return false;
-
- Event e = new Event(type);
- e.mouse_x = (int)event.getX();
- e.mouse_y = (int)event.getY();
- e.mouse_relative = false;
- scummvm.pushEvent(e);
-
- return true;
+ return false;
}
private void showKeyboard(boolean show) {
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
InputMethodManager imm = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
+
if (show)
imm.showSoftInput(main_surface, InputMethodManager.SHOW_IMPLICIT);
else
@@ -464,3 +222,4 @@ public class ScummVMActivity extends Activity {
InputMethodManager.HIDE_IMPLICIT_ONLY);
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
index 37a9d09e1a..f9eec72eac 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
@@ -8,22 +8,24 @@ public class ScummVMApplication extends Application {
public final static String ACTION_PLUGIN_QUERY = "org.inodes.gus.scummvm.action.PLUGIN_QUERY";
public final static String EXTRA_UNPACK_LIBS = "org.inodes.gus.scummvm.extra.UNPACK_LIBS";
- private static File cache_dir;
+ private static File _cache_dir;
@Override
public void onCreate() {
super.onCreate();
+
// This is still on /data :(
- cache_dir = getCacheDir();
+ _cache_dir = getCacheDir();
// This is mounted noexec :(
//cache_dir = new File(Environment.getExternalStorageDirectory(),
- // "/.ScummVM.tmp");
+ // "/.ScummVM.tmp");
// This is owned by download manager and requires special
// permissions to access :(
//cache_dir = Environment.getDownloadCacheDirectory();
}
public static File getLastCacheDir() {
- return cache_dir;
+ return _cache_dir;
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java
new file mode 100644
index 0000000000..2d5c100a1c
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java
@@ -0,0 +1,232 @@
+package org.inodes.gus.scummvm;
+
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.content.Context;
+import android.view.KeyEvent;
+import android.view.KeyCharacterMap;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.GestureDetector;
+import android.view.inputmethod.InputMethodManager;
+
+public class ScummVMEvents implements
+ android.view.View.OnKeyListener,
+ android.view.View.OnTouchListener,
+ android.view.GestureDetector.OnGestureListener,
+ android.view.GestureDetector.OnDoubleTapListener {
+
+ public static final int JE_SYS_KEY = 0;
+ public static final int JE_KEY = 1;
+ public static final int JE_DPAD = 2;
+ public static final int JE_DOWN = 3;
+ public static final int JE_SCROLL = 4;
+ public static final int JE_TAP = 5;
+ public static final int JE_DOUBLE_TAP = 6;
+ public static final int JE_MULTI = 7;
+ public static final int JE_BALL = 8;
+ public static final int JE_QUIT = 0x1000;
+
+ final protected Context _context;
+ final protected ScummVM _scummvm;
+ final protected GestureDetector _gd;
+ final protected int _longPress;
+
+ public ScummVMEvents(Context context, ScummVM scummvm) {
+ _context = context;
+ _scummvm = scummvm;
+
+ _gd = new GestureDetector(context, this);
+ _gd.setOnDoubleTapListener(this);
+ _gd.setIsLongpressEnabled(false);
+
+ _longPress = ViewConfiguration.getLongPressTimeout();
+ }
+
+ final public void sendQuitEvent() {
+ _scummvm.pushEvent(JE_QUIT, 0, 0, 0, 0, 0);
+ }
+
+ public boolean onTrackballEvent(MotionEvent e) {
+ _scummvm.pushEvent(JE_BALL, e.getAction(),
+ (int)(e.getX() * e.getXPrecision() * 100),
+ (int)(e.getY() * e.getYPrecision() * 100),
+ 0, 0);
+ return true;
+ }
+
+ final static int MSG_MENU_LONG_PRESS = 1;
+
+ final private Handler keyHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_MENU_LONG_PRESS) {
+ InputMethodManager imm = (InputMethodManager)
+ _context.getSystemService(_context.INPUT_METHOD_SERVICE);
+
+ if (imm != null)
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ }
+ }
+ };
+
+ // OnKeyListener
+ final public boolean onKey(View v, int keyCode, KeyEvent e) {
+ final int action = e.getAction();
+
+ if (e.isSystem()) {
+ // filter what we handle
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ case KeyEvent.KEYCODE_MENU:
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_SEARCH:
+ break;
+
+ default:
+ return false;
+ }
+
+ // no repeats for system keys
+ if (e.getRepeatCount() > 0)
+ return false;
+
+ // Have to reimplement hold-down-menu-brings-up-softkeybd
+ // ourselves, since we are otherwise hijacking the menu key :(
+ // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
+ // for the usual Android implementation of this feature.
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ final boolean fired =
+ !keyHandler.hasMessages(MSG_MENU_LONG_PRESS);
+
+ keyHandler.removeMessages(MSG_MENU_LONG_PRESS);
+
+ if (action == KeyEvent.ACTION_DOWN) {
+ keyHandler.sendMessageDelayed(keyHandler.obtainMessage(
+ MSG_MENU_LONG_PRESS), _longPress);
+ return true;
+ }
+
+ if (fired)
+ return true;
+
+ // only send up events of the menu button to the native side
+ if (action != KeyEvent.ACTION_UP)
+ return true;
+ }
+
+ _scummvm.pushEvent(JE_SYS_KEY, action, keyCode, 0, 0, 0);
+
+ return true;
+ }
+
+ // sequence of characters
+ if (action == KeyEvent.ACTION_MULTIPLE &&
+ keyCode == KeyEvent.KEYCODE_UNKNOWN) {
+ final KeyCharacterMap m = KeyCharacterMap.load(e.getDeviceId());
+ final KeyEvent[] es = m.getEvents(e.getCharacters().toCharArray());
+
+ if (es == null)
+ return true;
+
+ for (KeyEvent s : es) {
+ _scummvm.pushEvent(JE_KEY, s.getAction(), s.getKeyCode(),
+ s.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK,
+ s.getMetaState(), s.getRepeatCount());
+ }
+
+ return true;
+ }
+
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ _scummvm.pushEvent(JE_DPAD, action, keyCode,
+ (int)(e.getEventTime() - e.getDownTime()),
+ e.getRepeatCount(), 0);
+ return true;
+ }
+
+ _scummvm.pushEvent(JE_KEY, action, keyCode,
+ e.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK,
+ e.getMetaState(), e.getRepeatCount());
+
+ return true;
+ }
+
+ // OnTouchListener
+ final public boolean onTouch(View v, MotionEvent e) {
+ final int action = e.getAction();
+
+ // constants from APIv5:
+ // (action & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT
+ final int pointer = (action & 0xff00) >> 8;
+
+ if (pointer > 0) {
+ _scummvm.pushEvent(JE_MULTI, pointer, action & 0xff, // ACTION_MASK
+ (int)e.getX(), (int)e.getY(), 0);
+ return true;
+ }
+
+ return _gd.onTouchEvent(e);
+ }
+
+ // OnGestureListener
+ final public boolean onDown(MotionEvent e) {
+ _scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0);
+ return true;
+ }
+
+ final public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+ //Log.d(ScummVM.LOG_TAG, String.format("onFling: %s -> %s (%.3f %.3f)",
+ // e1.toString(), e2.toString(),
+ // velocityX, velocityY));
+
+ return true;
+ }
+
+ final public void onLongPress(MotionEvent e) {
+ // disabled, interferes with drag&drop
+ }
+
+ final public boolean onScroll(MotionEvent e1, MotionEvent e2,
+ float distanceX, float distanceY) {
+ _scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(),
+ (int)e2.getX(), (int)e2.getY(), 0);
+
+ return true;
+ }
+
+ final public void onShowPress(MotionEvent e) {
+ }
+
+ final public boolean onSingleTapUp(MotionEvent e) {
+ _scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(),
+ (int)(e.getEventTime() - e.getDownTime()), 0, 0);
+
+ return true;
+ }
+
+ // OnDoubleTapListener
+ final public boolean onDoubleTap(MotionEvent e) {
+ return true;
+ }
+
+ final public boolean onDoubleTapEvent(MotionEvent e) {
+ _scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(),
+ e.getAction(), 0, 0);
+
+ return true;
+ }
+
+ final public boolean onSingleTapConfirmed(MotionEvent e) {
+ return true;
+ }
+}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
index 7280aac7d4..c4b2ad7f5d 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
@@ -34,7 +34,9 @@ import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
public class Unpacker extends Activity {
- private final static boolean PLUGINS_ENABLED = true;
+ protected final static String LOG_TAG = "ScummVM";
+ // TODO don't hardcode this
+ private final static boolean PLUGINS_ENABLED = false;
private final static String META_NEXT_ACTIVITY =
"org.inodes.gus.unpacker.nextActivity";
private ProgressBar mProgress;
@@ -88,11 +90,11 @@ public class Unpacker extends Activity {
origIntent.getType());
//intent.fillIn(getIntent(), 0);
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
- Log.i(this.toString(),
+ Log.i(LOG_TAG,
"Starting next activity with intent " + intent);
startActivity(intent);
} else {
- Log.w(this.toString(),
+ Log.w(LOG_TAG,
"Unable to extract a component name from " + nextActivity);
}
}
@@ -128,12 +130,12 @@ public class Unpacker extends Activity {
new ZipFile(context.getPackageResourcePath());
job = new UnpackJob(zipfile, new HashSet<String>(1));
} catch (PackageManager.NameNotFoundException e) {
- Log.e(this.toString(), "Package " + pkg +
+ Log.e(LOG_TAG, "Package " + pkg +
" not found", e);
continue;
} catch (IOException e) {
// FIXME: show some sort of GUI error dialog
- Log.e(this.toString(),
+ Log.e(LOG_TAG,
"Error opening ZIP for package " + pkg, e);
continue;
}
@@ -145,7 +147,7 @@ public class Unpacker extends Activity {
// Delete stale filenames from mUnpackDest
for (File file: mUnpackDest.listFiles()) {
if (!all_files.contains(file.getName())) {
- Log.i(this.toString(),
+ Log.i(LOG_TAG,
"Deleting stale cached file " + file);
file.delete();
}
@@ -177,14 +179,14 @@ public class Unpacker extends Activity {
progress += zipentry.getSize();
} else {
if (dest.exists())
- Log.d(this.toString(),
+ Log.d(LOG_TAG,
"Replacing " + dest.getPath() +
" old.mtime=" + dest.lastModified() +
" new.mtime=" + zipentry.getTime() +
" old.size=" + dest.length() +
" new.size=" + zipentry.getSize());
else
- Log.i(this.toString(),
+ Log.i(LOG_TAG,
"Extracting " + zipentry.getName() +
" from " + zipfile.getName() +
" to " + dest.getPath());
@@ -215,12 +217,12 @@ public class Unpacker extends Activity {
zipfile.close();
} catch (IOException e) {
// FIXME: show some sort of GUI error dialog
- Log.e(this.toString(), "Error unpacking plugin", e);
+ Log.e(LOG_TAG, "Error unpacking plugin", e);
}
}
if (progress != total_size)
- Log.d(this.toString(), "Ended with progress " + progress +
+ Log.d(LOG_TAG, "Ended with progress " + progress +
" != total size " + total_size);
setResult(RESULT_OK);
@@ -234,7 +236,7 @@ public class Unpacker extends Activity {
public void onReceive(Context context, Intent intent) {
if (!intent.getAction()
.equals(ScummVMApplication.ACTION_PLUGIN_QUERY)) {
- Log.e(this.toString(),
+ Log.e(LOG_TAG,
"Received unexpected action " + intent.getAction());
return;
}
@@ -323,7 +325,7 @@ public class Unpacker extends Activity {
startActivityForResult(market_intent,
REQUEST_MARKET);
} catch (ActivityNotFoundException e) {
- Log.e(this.toString(),
+ Log.e(LOG_TAG,
"Error starting market", e);
}
}
@@ -351,7 +353,7 @@ public class Unpacker extends Activity {
switch (requestCode) {
case REQUEST_MARKET:
if (resultCode != RESULT_OK)
- Log.w(this.toString(), "Market returned " + resultCode);
+ Log.w(LOG_TAG, "Market returned " + resultCode);
tryUnpack();
break;
}
@@ -363,8 +365,9 @@ public class Unpacker extends Activity {
.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
return ai.metaData;
} catch (PackageManager.NameNotFoundException e) {
- Log.w(this.toString(), "Unable to find my own meta-data", e);
+ Log.w(LOG_TAG, "Unable to find my own meta-data", e);
return new Bundle();
}
}
}
+
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
new file mode 100644
index 0000000000..a6b28ca485
--- /dev/null
+++ b/backends/platform/android/texture.cpp
@@ -0,0 +1,477 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "base/main.h"
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+#include "common/util.h"
+#include "common/tokenizer.h"
+
+#include "backends/platform/android/texture.h"
+#include "backends/platform/android/android.h"
+
+// Supported GL extensions
+static bool npot_supported = false;
+#ifdef GL_OES_draw_texture
+static bool draw_tex_supported = false;
+#endif
+
+static inline GLfixed xdiv(int numerator, int denominator) {
+ assert(numerator < (1 << 16));
+ return (numerator << 16) / denominator;
+}
+
+template <class T>
+static T nextHigher2(T k) {
+ if (k == 0)
+ return 1;
+ --k;
+
+ for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1)
+ k = k | k >> i;
+
+ return k + 1;
+}
+
+void GLESBaseTexture::initGLExtensions() {
+ const char *ext_string =
+ reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
+
+ LOGI("Extensions: %s", ext_string);
+
+ Common::StringTokenizer tokenizer(ext_string, " ");
+ while (!tokenizer.empty()) {
+ Common::String token = tokenizer.nextToken();
+
+ if (token == "GL_ARB_texture_non_power_of_two")
+ npot_supported = true;
+
+#ifdef GL_OES_draw_texture
+ if (token == "GL_OES_draw_texture")
+ draw_tex_supported = true;
+#endif
+ }
+}
+
+GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat) :
+ _glFormat(glFormat),
+ _glType(glType),
+ _glFilter(GL_NEAREST),
+ _texture_name(0),
+ _surface(),
+ _texture_width(0),
+ _texture_height(0),
+ _draw_rect(),
+ _all_dirty(false),
+ _dirty_rect(),
+ _pixelFormat(pixelFormat),
+ _palettePixelFormat()
+{
+ GLCALL(glGenTextures(1, &_texture_name));
+}
+
+GLESBaseTexture::~GLESBaseTexture() {
+ release();
+}
+
+void GLESBaseTexture::release() {
+ if (_texture_name) {
+ LOGD("Destroying texture %u", _texture_name);
+
+ GLCALL(glDeleteTextures(1, &_texture_name));
+ _texture_name = 0;
+ }
+}
+
+void GLESBaseTexture::reinit() {
+ GLCALL(glGenTextures(1, &_texture_name));
+
+ initSize();
+
+ setDirty();
+}
+
+void GLESBaseTexture::initSize() {
+ // Allocate room for the texture now, but pixel data gets uploaded
+ // later (perhaps with multiple TexSubImage2D operations).
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+ GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glFormat,
+ _texture_width, _texture_height,
+ 0, _glFormat, _glType, 0));
+}
+
+void GLESBaseTexture::setLinearFilter(bool value) {
+ if (value)
+ _glFilter = GL_LINEAR;
+ else
+ _glFilter = GL_NEAREST;
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
+}
+
+void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) {
+ _surface.w = w;
+ _surface.h = h;
+ _surface.bytesPerPixel = _pixelFormat.bytesPerPixel;
+
+ if (w == _texture_width && h == _texture_height)
+ return;
+
+ if (npot_supported) {
+ _texture_width = _surface.w;
+ _texture_height = _surface.h;
+ } else {
+ _texture_width = nextHigher2(_surface.w);
+ _texture_height = nextHigher2(_surface.h);
+ }
+
+ initSize();
+}
+
+void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+#ifdef GL_OES_draw_texture
+ // Great extension, but only works under specific conditions.
+ // Still a work-in-progress - disabled for now.
+ if (false && draw_tex_supported && !hasPalette()) {
+ //GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
+ const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h };
+
+ GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop));
+
+ // Android GLES bug?
+ GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
+
+ GLCALL(glDrawTexiOES(x, y, 0, w, h));
+ } else
+#endif
+ {
+ const GLfixed tex_width = xdiv(_surface.w, _texture_width);
+ const GLfixed tex_height = xdiv(_surface.h, _texture_height);
+ const GLfixed texcoords[] = {
+ 0, 0,
+ tex_width, 0,
+ 0, tex_height,
+ tex_width, tex_height,
+ };
+
+ GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords));
+
+ const GLshort vertices[] = {
+ x, y,
+ x + w, y,
+ x, y + h,
+ x + w, y + h,
+ };
+
+ GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
+
+ assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
+ GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2));
+ }
+
+ clearDirty();
+}
+
+const Graphics::PixelFormat &GLESBaseTexture::getPixelFormat() const {
+ return _pixelFormat;
+}
+
+GLESTexture::GLESTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat) :
+ GLESBaseTexture(glFormat, glType, pixelFormat),
+ _pixels(0),
+ _buf(0) {
+}
+
+GLESTexture::~GLESTexture() {
+ delete[] _buf;
+ delete[] _pixels;
+}
+
+void GLESTexture::allocBuffer(GLuint w, GLuint h) {
+ GLuint oldw = _surface.w;
+ GLuint oldh = _surface.h;
+
+ GLESBaseTexture::allocBuffer(w, h);
+
+ _surface.pitch = w * _pixelFormat.bytesPerPixel;
+
+ if (_surface.w == oldw && _surface.h == oldh) {
+ fillBuffer(0);
+ return;
+ }
+
+ delete[] _buf;
+ delete[] _pixels;
+
+ _pixels = new byte[w * h * _surface.bytesPerPixel];
+ assert(_pixels);
+
+ _surface.pixels = _pixels;
+
+ fillBuffer(0);
+
+ _buf = new byte[w * h * _surface.bytesPerPixel];
+ assert(_buf);
+}
+
+void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
+ const void *buf, int pitch_buf) {
+ setDirtyRect(Common::Rect(x, y, x + w, y + h));
+
+ const byte *src = (const byte *)buf;
+ byte *dst = _pixels + y * _surface.pitch + x * _surface.bytesPerPixel;
+
+ do {
+ memcpy(dst, src, w * _surface.bytesPerPixel);
+ dst += _surface.pitch;
+ src += pitch_buf;
+ } while (--h);
+}
+
+void GLESTexture::fillBuffer(uint32 color) {
+ assert(_surface.pixels);
+
+ if (_pixelFormat.bytesPerPixel == 1 ||
+ ((color & 0xff) == ((color >> 8) & 0xff)))
+ memset(_pixels, color & 0xff, _surface.pitch * _surface.h);
+ else
+ Common::set_to(_pixels, _pixels + _surface.pitch * _surface.h,
+ (uint16)color);
+
+ setDirty();
+}
+
+void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+ if (_all_dirty) {
+ _dirty_rect.top = 0;
+ _dirty_rect.left = 0;
+ _dirty_rect.bottom = _surface.h;
+ _dirty_rect.right = _surface.w;
+
+ _all_dirty = false;
+ }
+
+ if (!_dirty_rect.isEmpty()) {
+ byte *_tex;
+
+ int16 dwidth = _dirty_rect.width();
+ int16 dheight = _dirty_rect.height();
+
+ if (dwidth == _surface.w) {
+ _tex = _pixels + _dirty_rect.top * _surface.pitch;
+ } else {
+ _tex = _buf;
+
+ byte *src = _pixels + _dirty_rect.top * _surface.pitch +
+ _dirty_rect.left * _surface.bytesPerPixel;
+ byte *dst = _buf;
+
+ uint16 l = dwidth * _surface.bytesPerPixel;
+
+ for (uint16 i = 0; i < dheight; ++i) {
+ memcpy(dst, src, l);
+ src += _surface.pitch;
+ dst += l;
+ }
+ }
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+ GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+
+ GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ _dirty_rect.left, _dirty_rect.top,
+ dwidth, dheight, _glFormat, _glType, _tex));
+ }
+
+ GLESBaseTexture::drawTexture(x, y, w, h);
+}
+
+GLES4444Texture::GLES4444Texture() :
+ GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {
+}
+
+GLES4444Texture::~GLES4444Texture() {
+}
+
+GLES5551Texture::GLES5551Texture() :
+ GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
+}
+
+GLES5551Texture::~GLES5551Texture() {
+}
+
+GLES565Texture::GLES565Texture() :
+ GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {
+}
+
+GLES565Texture::~GLES565Texture() {
+}
+
+GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat) :
+ GLESBaseTexture(glFormat, glType, pixelFormat),
+ _palette(0),
+ _pixels(0),
+ _buf(0)
+{
+ _palettePixelFormat = pixelFormat;
+ _fake_format = Graphics::PixelFormat::createFormatCLUT8();
+
+ _palette = new uint16[256];
+ assert(_palette);
+
+ memset(_palette, 0, 256 * 2);
+}
+
+GLESFakePaletteTexture::~GLESFakePaletteTexture() {
+ delete[] _buf;
+ delete[] _pixels;
+ delete[] _palette;
+}
+
+void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
+ GLuint oldw = _surface.w;
+ GLuint oldh = _surface.h;
+
+ GLESBaseTexture::allocBuffer(w, h);
+
+ _surface.bytesPerPixel = 1;
+ _surface.pitch = w;
+
+ if (_surface.w == oldw && _surface.h == oldh) {
+ fillBuffer(0);
+ return;
+ }
+
+ delete[] _buf;
+ delete[] _pixels;
+
+ _pixels = new byte[w * h];
+ assert(_pixels);
+
+ // fixup surface, for the outside this is a CLUT8 surface
+ _surface.pixels = _pixels;
+
+ fillBuffer(0);
+
+ _buf = new uint16[w * h];
+ assert(_buf);
+}
+
+void GLESFakePaletteTexture::fillBuffer(uint32 color) {
+ assert(_surface.pixels);
+ memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h);
+ setDirty();
+}
+
+void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w,
+ GLuint h, const void *buf,
+ int pitch_buf) {
+ setDirtyRect(Common::Rect(x, y, x + w, y + h));
+
+ const byte *src = (const byte *)buf;
+ byte *dst = _pixels + y * _surface.pitch + x;
+
+ do {
+ memcpy(dst, src, w);
+ dst += _surface.pitch;
+ src += pitch_buf;
+ } while (--h);
+}
+
+void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
+ GLshort h) {
+ if (_all_dirty) {
+ _dirty_rect.top = 0;
+ _dirty_rect.left = 0;
+ _dirty_rect.bottom = _surface.h;
+ _dirty_rect.right = _surface.w;
+
+ _all_dirty = false;
+ }
+
+ if (!_dirty_rect.isEmpty()) {
+ int16 dwidth = _dirty_rect.width();
+ int16 dheight = _dirty_rect.height();
+
+ byte *src = _pixels + _dirty_rect.top * _surface.pitch +
+ _dirty_rect.left;
+ uint16 *dst = _buf;
+ uint pitch_delta = _surface.pitch - dwidth;
+
+ for (uint16 j = 0; j < dheight; ++j) {
+ for (uint16 i = 0; i < dwidth; ++i)
+ *dst++ = _palette[*src++];
+ src += pitch_delta;
+ }
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+ GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ _dirty_rect.left, _dirty_rect.top,
+ dwidth, dheight, _glFormat, _glType, _buf));
+ }
+
+ GLESBaseTexture::drawTexture(x, y, w, h);
+}
+
+const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
+ return _fake_format;
+}
+
+GLESFakePalette565Texture::GLESFakePalette565Texture() :
+ GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+ GLES565Texture::pixelFormat()) {
+}
+
+GLESFakePalette565Texture::~GLESFakePalette565Texture() {
+}
+
+GLESFakePalette5551Texture::GLESFakePalette5551Texture() :
+ GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
+ GLES5551Texture::pixelFormat()) {
+}
+
+GLESFakePalette5551Texture::~GLESFakePalette5551Texture() {
+}
+
+#endif
+
diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h
new file mode 100644
index 0000000000..6344326259
--- /dev/null
+++ b/backends/platform/android/texture.h
@@ -0,0 +1,277 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef _ANDROID_TEXTURE_H_
+#define _ANDROID_TEXTURE_H_
+
+#if defined(__ANDROID__)
+
+#include <GLES/gl.h>
+
+#include "graphics/surface.h"
+#include "graphics/pixelformat.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+
+class GLESBaseTexture {
+public:
+ static void initGLExtensions();
+
+protected:
+ GLESBaseTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat);
+
+public:
+ virtual ~GLESBaseTexture();
+
+ void release();
+ void reinit();
+ void initSize();
+
+ void setLinearFilter(bool value);
+
+ virtual void allocBuffer(GLuint w, GLuint h);
+
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void *buf, int pitch_buf) = 0;
+ virtual void fillBuffer(uint32 color) = 0;
+
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+ inline void setDrawRect(const Common::Rect &rect) {
+ _draw_rect = rect;
+ }
+
+ inline void setDrawRect(int16 w, int16 h) {
+ _draw_rect = Common::Rect(w, h);
+ }
+
+ inline void setDrawRect(int16 x1, int16 y1, int16 x2, int16 y2) {
+ _draw_rect = Common::Rect(x1, y1, x2, y2);
+ }
+
+ inline const Common::Rect &getDrawRect() const {
+ return _draw_rect;
+ }
+
+ inline void drawTextureRect() {
+ drawTexture(_draw_rect.left, _draw_rect.top,
+ _draw_rect.width(), _draw_rect.height());
+ }
+
+ inline void drawTextureOrigin() {
+ drawTexture(0, 0, _surface.w, _surface.h);
+ }
+
+ inline GLuint width() const {
+ return _surface.w;
+ }
+
+ inline GLuint height() const {
+ return _surface.h;
+ }
+
+ inline uint16 pitch() const {
+ return _surface.pitch;
+ }
+
+ inline bool isEmpty() const {
+ return _surface.w == 0 || _surface.h == 0;
+ }
+
+ inline const Graphics::Surface *surface_const() const {
+ return &_surface;
+ }
+
+ inline Graphics::Surface *surface() {
+ setDirty();
+ return &_surface;
+ }
+
+ virtual const byte *palette_const() const {
+ return 0;
+ };
+
+ virtual byte *palette() {
+ return 0;
+ };
+
+ inline bool hasPalette() const {
+ return _palettePixelFormat.bytesPerPixel > 0;
+ }
+
+ inline bool dirty() const {
+ return _all_dirty || !_dirty_rect.isEmpty();
+ }
+
+ virtual const Graphics::PixelFormat &getPixelFormat() const;
+
+ inline const Graphics::PixelFormat &getPalettePixelFormat() const {
+ return _palettePixelFormat;
+ }
+
+protected:
+ inline void setDirty() {
+ _all_dirty = true;
+ }
+
+ inline void clearDirty() {
+ _all_dirty = false;
+ _dirty_rect.top = 0;
+ _dirty_rect.left = 0;
+ _dirty_rect.bottom = 0;
+ _dirty_rect.right = 0;
+ }
+
+ inline void setDirtyRect(const Common::Rect& r) {
+ if (!_all_dirty) {
+ if (_dirty_rect.isEmpty())
+ _dirty_rect = r;
+ else
+ _dirty_rect.extend(r);
+ }
+ }
+
+ GLenum _glFormat;
+ GLenum _glType;
+ GLint _glFilter;
+
+ GLuint _texture_name;
+ Graphics::Surface _surface;
+ GLuint _texture_width;
+ GLuint _texture_height;
+
+ Common::Rect _draw_rect;
+
+ bool _all_dirty;
+ Common::Rect _dirty_rect;
+
+ Graphics::PixelFormat _pixelFormat;
+ Graphics::PixelFormat _palettePixelFormat;
+};
+
+class GLESTexture : public GLESBaseTexture {
+protected:
+ GLESTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat);
+
+public:
+ virtual ~GLESTexture();
+
+ virtual void allocBuffer(GLuint w, GLuint h);
+
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void *buf, int pitch_buf);
+ virtual void fillBuffer(uint32 color);
+
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+protected:
+ byte *_pixels;
+ byte *_buf;
+};
+
+// RGBA4444 texture
+class GLES4444Texture : public GLESTexture {
+public:
+ GLES4444Texture();
+ virtual ~GLES4444Texture();
+
+ static Graphics::PixelFormat pixelFormat() {
+ return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
+ }
+};
+
+// RGBA5551 texture
+class GLES5551Texture : public GLESTexture {
+public:
+ GLES5551Texture();
+ virtual ~GLES5551Texture();
+
+ static inline Graphics::PixelFormat pixelFormat() {
+ return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
+ }
+};
+
+// RGB565 texture
+class GLES565Texture : public GLESTexture {
+public:
+ GLES565Texture();
+ virtual ~GLES565Texture();
+
+ static inline Graphics::PixelFormat pixelFormat() {
+ return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ }
+};
+
+class GLESFakePaletteTexture : public GLESBaseTexture {
+protected:
+ GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat);
+
+public:
+ virtual ~GLESFakePaletteTexture();
+
+ virtual void allocBuffer(GLuint w, GLuint h);
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void *buf, int pitch_buf);
+ virtual void fillBuffer(uint32 color);
+
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+ virtual const byte *palette_const() const {
+ return (byte *)_palette;
+ };
+
+ virtual byte *palette() {
+ setDirty();
+ return (byte *)_palette;
+ };
+
+ virtual const Graphics::PixelFormat &getPixelFormat() const;
+
+protected:
+ Graphics::PixelFormat _fake_format;
+ uint16 *_palette;
+ byte *_pixels;
+ uint16 *_buf;
+};
+
+class GLESFakePalette565Texture : public GLESFakePaletteTexture {
+public:
+ GLESFakePalette565Texture();
+ virtual ~GLESFakePalette565Texture();
+};
+
+class GLESFakePalette5551Texture : public GLESFakePaletteTexture {
+public:
+ GLESFakePalette5551Texture();
+ virtual ~GLESFakePalette5551Texture();
+};
+
+#endif
+#endif
+
diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp
deleted file mode 100644
index 3275335d97..0000000000
--- a/backends/platform/android/video.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "base/main.h"
-#include "graphics/surface.h"
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <android/log.h>
-
-#include "common/rect.h"
-#include "common/array.h"
-#include "common/util.h"
-#include "common/tokenizer.h"
-
-#include "backends/platform/android/video.h"
-
-// Unfortunately, Android devices are too varied to make broad assumptions :/
-#define TEXSUBIMAGE_IS_EXPENSIVE 0
-
-#undef LOG_TAG
-#define LOG_TAG "ScummVM-video"
-
-#if 0
-#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args)
-#else
-#define ENTER(args...) /**/
-#endif
-
-#if 0
-#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
-static const char* getGlErrStr(GLenum error) {
- switch (error) {
- case GL_NO_ERROR: return "GL_NO_ERROR";
- case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
- case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
- case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
- case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
- case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
- }
-
- static char buf[40];
- snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
- return buf;
-}
-static void checkGlError(const char* file, int line) {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR)
- warning("%s:%d: GL error: %s", file, line, getGlErrStr(error));
-}
-#else
-#define CHECK_GL_ERROR() do {} while (false)
-#endif
-
-// Supported GL extensions
-static bool npot_supported = false;
-#ifdef GL_OES_draw_texture
-static bool draw_tex_supported = false;
-#endif
-
-static inline GLfixed xdiv(int numerator, int denominator) {
- assert(numerator < (1<<16));
- return (numerator << 16) / denominator;
-}
-
-template <class T>
-static T nextHigher2(T k) {
- if (k == 0)
- return 1;
- --k;
- for (uint i = 1; i < sizeof(T)*CHAR_BIT; i <<= 1)
- k = k | k >> i;
- return k + 1;
-}
-
-void GLESTexture::initGLExtensions() {
- const char* ext_string =
- reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
- __android_log_print(ANDROID_LOG_INFO, LOG_TAG,
- "Extensions: %s", ext_string);
- Common::StringTokenizer tokenizer(ext_string, " ");
- while (!tokenizer.empty()) {
- Common::String token = tokenizer.nextToken();
- if (token == "GL_ARB_texture_non_power_of_two")
- npot_supported = true;
-#ifdef GL_OES_draw_texture
- if (token == "GL_OES_draw_texture")
- draw_tex_supported = true;
-#endif
- }
-}
-
-GLESTexture::GLESTexture() :
- _texture_width(0),
- _texture_height(0),
- _all_dirty(true)
-{
- glGenTextures(1, &_texture_name);
- // This all gets reset later in allocBuffer:
- _surface.w = 0;
- _surface.h = 0;
- _surface.pitch = _texture_width;
- _surface.pixels = NULL;
- _surface.bytesPerPixel = 0;
-}
-
-GLESTexture::~GLESTexture() {
- debug("Destroying texture %u", _texture_name);
- glDeleteTextures(1, &_texture_name);
-}
-
-void GLESTexture::reinitGL() {
- glGenTextures(1, &_texture_name);
- setDirty();
-}
-
-void GLESTexture::allocBuffer(GLuint w, GLuint h) {
- CHECK_GL_ERROR();
- int bpp = bytesPerPixel();
- _surface.w = w;
- _surface.h = h;
- _surface.bytesPerPixel = bpp;
-
- if (w <= _texture_width && h <= _texture_height)
- // Already allocated a sufficiently large buffer
- return;
-
- if (npot_supported) {
- _texture_width = _surface.w;
- _texture_height = _surface.h;
- } else {
- _texture_width = nextHigher2(_surface.w);
- _texture_height = nextHigher2(_surface.h);
- }
- _surface.pitch = _texture_width * bpp;
-
- // Allocate room for the texture now, but pixel data gets uploaded
- // later (perhaps with multiple TexSubImage2D operations).
- CHECK_GL_ERROR();
- glBindTexture(GL_TEXTURE_2D, _texture_name);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- CHECK_GL_ERROR();
- glTexImage2D(GL_TEXTURE_2D, 0, glFormat(),
- _texture_width, _texture_height,
- 0, glFormat(), glType(), NULL);
- CHECK_GL_ERROR();
-}
-
-void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
- const void* buf, int pitch) {
- ENTER("updateBuffer(%u, %u, %u, %u, %p, %d)", x, y, w, h, buf, pitch);
- glBindTexture(GL_TEXTURE_2D, _texture_name);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- setDirtyRect(Common::Rect(x, y, x+w, y+h));
-
- if (static_cast<int>(w) * bytesPerPixel() == pitch) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
- glFormat(), glType(), buf);
- } else {
- // GLES removed the ability to specify pitch, so we
- // have to do this ourselves.
- if (h == 0)
- return;
-
-#if TEXSUBIMAGE_IS_EXPENSIVE
- byte tmpbuf[w * h * bytesPerPixel()];
- const byte* src = static_cast<const byte*>(buf);
- byte* dst = tmpbuf;
- GLuint count = h;
- do {
- memcpy(dst, src, w * bytesPerPixel());
- dst += w * bytesPerPixel();
- src += pitch;
- } while (--count);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
- glFormat(), glType(), tmpbuf);
-#else
- // This version avoids the intermediate copy at the expense of
- // repeat glTexSubImage2D calls. On some devices this is worse.
- const byte* src = static_cast<const byte*>(buf);
- do {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
- w, 1, glFormat(), glType(), src);
- ++y;
- src += pitch;
- } while (--h);
-#endif
- }
-}
-
-void GLESTexture::fillBuffer(byte x) {
- int rowbytes = _surface.w * bytesPerPixel();
- byte tmpbuf[_surface.h * rowbytes];
- memset(tmpbuf, x, _surface.h * rowbytes);
- updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes);
-}
-
-void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
- glBindTexture(GL_TEXTURE_2D, _texture_name);
-
-#ifdef GL_OES_draw_texture
- // Great extension, but only works under specific conditions.
- // Still a work-in-progress - disabled for now.
- if (false && draw_tex_supported && paletteSize() == 0) {
- //glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- const GLint crop[4] = {0, _surface.h, _surface.w, -_surface.h};
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
- glColor4ub(0xff, 0xff, 0xff, 0xff); // Android GLES bug?
- glDrawTexiOES(x, y, 0, w, h);
- } else
-#endif
- {
- const GLfixed tex_width = xdiv(_surface.w, _texture_width);
- const GLfixed tex_height = xdiv(_surface.h, _texture_height);
- const GLfixed texcoords[] = {
- 0, 0,
- tex_width, 0,
- 0, tex_height,
- tex_width, tex_height,
- };
- glTexCoordPointer(2, GL_FIXED, 0, texcoords);
-
- const GLshort vertices[] = {
- x, y,
- x+w, y,
- x, y+h,
- x+w, y+h,
- };
- glVertexPointer(2, GL_SHORT, 0, vertices);
-
- assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
- glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices)/2);
- }
-
- _all_dirty = false;
- _dirty_rect = Common::Rect();
-}
-
-GLESPaletteTexture::GLESPaletteTexture() :
- GLESTexture(),
- _texture(NULL)
-{
-}
-
-GLESPaletteTexture::~GLESPaletteTexture() {
- delete[] _texture;
-}
-
-void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
- CHECK_GL_ERROR();
- int bpp = bytesPerPixel();
- _surface.w = w;
- _surface.h = h;
- _surface.bytesPerPixel = bpp;
-
- if (w <= _texture_width && h <= _texture_height)
- // Already allocated a sufficiently large buffer
- return;
-
- if (npot_supported) {
- _texture_width = _surface.w;
- _texture_height = _surface.h;
- } else {
- _texture_width = nextHigher2(_surface.w);
- _texture_height = nextHigher2(_surface.h);
- }
- _surface.pitch = _texture_width * bpp;
-
- // Texture gets uploaded later (from drawTexture())
-
- byte* new_buffer = new byte[paletteSize() +
- _texture_width * _texture_height * bytesPerPixel()];
- if (_texture) {
- memcpy(new_buffer, _texture, paletteSize()); // preserve palette
- delete[] _texture;
- }
- _texture = new_buffer;
- _surface.pixels = _texture + paletteSize();
-}
-
-void GLESPaletteTexture::fillBuffer(byte x) {
- assert(_surface.pixels);
- memset(_surface.pixels, x, _surface.pitch * _surface.h);
- setDirty();
-}
-
-void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y,
- GLuint w, GLuint h,
- const void* buf, int pitch) {
- _all_dirty = true;
-
- const byte* src = static_cast<const byte*>(buf);
- byte* dst = static_cast<byte*>(_surface.getBasePtr(x, y));
- do {
- memcpy(dst, src, w * bytesPerPixel());
- dst += _surface.pitch;
- src += pitch;
- } while (--h);
-}
-
-void GLESPaletteTexture::uploadTexture() const {
- const size_t texture_size =
- paletteSize() + _texture_width * _texture_height * bytesPerPixel();
- glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(),
- _texture_width, _texture_height,
- 0, texture_size, _texture);
- CHECK_GL_ERROR();
-}
-
-void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
- if (_all_dirty) {
- glBindTexture(GL_TEXTURE_2D, _texture_name);
- CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- CHECK_GL_ERROR();
- uploadTexture();
- _all_dirty = false;
- }
-
- GLESTexture::drawTexture(x, y, w, h);
-}
diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h
deleted file mode 100644
index 2ca07e0afd..0000000000
--- a/backends/platform/android/video.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#if defined(ANDROID)
-
-#include <GLES/gl.h>
-
-#include "graphics/surface.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-
-class GLESTexture {
-public:
- static void initGLExtensions();
-
- GLESTexture();
- virtual ~GLESTexture();
- virtual void reinitGL();
- virtual void allocBuffer(GLuint width, GLuint height);
- const Graphics::Surface* surface_const() const { return &_surface; }
- GLuint width() const { return _surface.w; }
- GLuint height() const { return _surface.h; }
- GLuint texture_name() const { return _texture_name; }
- bool dirty() const { return _all_dirty || !_dirty_rect.isEmpty(); }
- virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
- const void* buf, int pitch);
- virtual void fillBuffer(byte x);
- virtual void drawTexture() {
- drawTexture(0, 0, _surface.w, _surface.h);
- }
- virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
-protected:
- virtual byte bytesPerPixel() const = 0;
- virtual GLenum glFormat() const = 0;
- virtual GLenum glType() const = 0;
- virtual size_t paletteSize() const { return 0; };
- void setDirty() {
- _all_dirty = true;
- _dirty_rect = Common::Rect();
- }
- void setDirtyRect(const Common::Rect& r) {
- if (!_all_dirty) {
- if (_dirty_rect.isEmpty())
- _dirty_rect = r;
- else
- _dirty_rect.extend(r);
- }
- }
- GLuint _texture_name;
- Graphics::Surface _surface;
- GLuint _texture_width;
- GLuint _texture_height;
- bool _all_dirty;
- Common::Rect _dirty_rect; // Covers dirty area
-};
-
-// RGBA4444 texture
-class GLES4444Texture : public GLESTexture {
-protected:
- virtual byte bytesPerPixel() const { return 2; }
- virtual GLenum glFormat() const { return GL_RGBA; }
- virtual GLenum glType() const { return GL_UNSIGNED_SHORT_4_4_4_4; }
-};
-
-// RGB565 texture
-class GLES565Texture : public GLESTexture {
-protected:
- virtual byte bytesPerPixel() const { return 2; }
- virtual GLenum glFormat() const { return GL_RGB; }
- virtual GLenum glType() const { return GL_UNSIGNED_SHORT_5_6_5; }
-};
-
-// RGB888 256-entry paletted texture
-class GLESPaletteTexture : public GLESTexture {
-public:
- GLESPaletteTexture();
- virtual ~GLESPaletteTexture();
- virtual void allocBuffer(GLuint width, GLuint height);
- virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
- const void* buf, int pitch);
- Graphics::Surface* surface() {
- setDirty();
- return &_surface;
- }
- void* pixels() {
- setDirty();
- return _surface.pixels;
- }
- const byte* palette_const() const { return _texture; };
- byte* palette() {
- setDirty();
- return _texture;
- };
- virtual void drawTexture() {
- drawTexture(0, 0, _surface.w, _surface.h);
- }
- virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
- virtual void fillBuffer(byte x);
-protected:
- virtual byte bytesPerPixel() const { return 1; }
- virtual GLenum glFormat() const { return GL_RGB; }
- virtual GLenum glType() const { return GL_PALETTE8_RGB8_OES; }
- virtual size_t paletteSize() const { return 256 * 3; };
- virtual void uploadTexture() const;
- byte* _texture;
-};
-
-// RGBA8888 256-entry paletted texture
-class GLESPaletteATexture : public GLESPaletteTexture {
-protected:
- virtual GLenum glFormat() const { return GL_RGBA; }
- virtual GLenum glType() const { return GL_PALETTE8_RGBA8_OES; }
- virtual size_t paletteSize() const { return 256 * 4; };
-};
-
-#endif
diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp
index 53dbff333d..b297022775 100644
--- a/backends/platform/dc/display.cpp
+++ b/backends/platform/dc/display.cpp
@@ -156,7 +156,7 @@ void OSystem_Dreamcast::setPalette(const byte *colors, uint start, uint num)
*dst++ = ((colors[0]<<7)&0x7c00)|
((colors[1]<<2)&0x03e0)|
((colors[2]>>3)&0x001f);
- colors += 4;
+ colors += 3;
}
_screen_dirty = true;
}
@@ -169,7 +169,7 @@ void OSystem_Dreamcast::setCursorPalette(const byte *colors, uint start, uint nu
*dst++ = ((colors[0]<<7)&0x7c00)|
((colors[1]<<2)&0x03e0)|
((colors[2]>>3)&0x001f);
- colors += 4;
+ colors += 3;
}
_enable_cursor_palette = true;
}
@@ -188,8 +188,7 @@ void OSystem_Dreamcast::grabPalette(byte *colors, uint start, uint num)
colors[0] = ((p&0x7c00)>>7)|((p&0x7000)>>12);
colors[1] = ((p&0x03e0)>>2)|((p&0x0380)>>7);
colors[2] = ((p&0x001f)<<3)|((p&0x001c)>>2);
- colors[3] = 0xff;
- colors += 4;
+ colors += 3;
}
}
diff --git a/backends/platform/dc/dreamcast.mk b/backends/platform/dc/dreamcast.mk
index d53af90585..8651a2936c 100644
--- a/backends/platform/dc/dreamcast.mk
+++ b/backends/platform/dc/dreamcast.mk
@@ -29,7 +29,7 @@ IP.BIN : ip.txt
ip.txt : $(srcdir)/backends/platform/dc/ip.txt.in
if [ x"$(VER_EXTRA)" = xgit ]; then \
- if [ -z "$(VER_REV)" ]; then ver="GIT"; else ver="r$(VER_REV)"; fi; \
+ ver="GIT"; \
else ver="V$(VERSION)"; fi; \
if expr "$$ver" : V...... >/dev/null; then \
ver="V$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)"; fi; \
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index 55e3be6cca..3ad92b4355 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -204,7 +204,7 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
}
// if (num == 255) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
- colors += 4;
+ colors += 3;
}
}
@@ -235,7 +235,7 @@ void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
u16 paletteValue = red | (green << 5) | (blue << 10);
_cursorPalette[r] = paletteValue;
- colors += 4;
+ colors += 3;
}
_disableCursorPalette = false;
@@ -266,7 +266,6 @@ void OSystem_DS::grabPalette(unsigned char *colours, uint start, uint num) {
*colours++ = (BG_PALETTE[r] & 0x001F) << 3;
*colours++ = (BG_PALETTE[r] & 0x03E0) >> 5 << 3;
*colours++ = (BG_PALETTE[r] & 0x7C00) >> 10 << 3;
- colours++;
}
}
diff --git a/backends/platform/ds/build-ds.sh b/backends/platform/ds/build-ds.sh
index d56af5a092..8e0b0575f4 100755
--- a/backends/platform/ds/build-ds.sh
+++ b/backends/platform/ds/build-ds.sh
@@ -1,4 +1,8 @@
#!/bin/sh
+
+echo "FIXME: feature disabled in configure"
+exit 1
+
#
# build-ds.sh -- script for building a ds build with every usable dynamic engine plugin
diff --git a/backends/platform/gp2x/build/README-GP2X b/backends/platform/gp2x/build/README-GP2X
deleted file mode 100644
index 3c6591d369..0000000000
--- a/backends/platform/gp2x/build/README-GP2X
+++ /dev/null
@@ -1,54 +0,0 @@
-ScummVM - GP2X SPECIFIC README
-------------------------------------------------------------------------
-
-Contents:
-
- * About the backend/port <#About_the_backendport>
- * Supported audio options <#Supported_audio_options>
- * Credits <#Credits>
-
-------------------------------------------------------------------------
-
-Please refer to the:
-
-GP2X/GP2XWiz ScummVM Forum: <http://forums.scummvm.org/viewforum.php?f=14>
-WiKi: <http://wiki.scummvm.org/index.php/GP2X>
-
-for the most current information on the port and any updates to this
-documentation.
-
-The wiki includes detailed instructions on how to use the port and
-control information.
-
-------------------------------------------------------------------------
-About the backend/port
-
-This is the readme for the official GP2X ScummVM backend (also known as
-the GP2X port).
-
-This is an SVN test release of ScummVM for the GP2X, it would be
-appreciated if this SVN test distribution was not mirrored and that
-people be directed to http://scummvm.distant-earth.com/ instead for
-updated SVN builds.
-
-Full supported official releases of the GP2X ScummVM backend are made in
-line with main official releases and are avalalble from the ScummVM
-downloads page <http://www.scummvm.org/downloads.php>.
-
-------------------------------------------------------------------------
-Supported audio options
-
-Raw audio.
-MP3 audio.
-OGG Vorbis audio.
-
-FLAC audio is currently unsupported.
-
-For best results use uncompressed audio in games.
-
-------------------------------------------------------------------------
-Credits
-
-Core ScummVM code (c) The ScummVM Team
-Portions of the GP2X backend (c) John Willis
-Detailed (c) information can be found within the source code
diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh
deleted file mode 100755
index d17f8bd831..0000000000
--- a/backends/platform/gp2x/build/bundle.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-echo Quick script to make building a distribution of the GP2X port more consistent.
-
-cd ../../../..
-
-echo Building ScummVM for GP2X Wiz.
-
-make gp2x-bundle
-
diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h
index 4d2a9c33cc..2a06cab788 100644
--- a/backends/platform/gp2x/gp2x-common.h
+++ b/backends/platform/gp2x/gp2x-common.h
@@ -26,7 +26,11 @@
#ifndef PLATFORM_SDL_GP2X_H
#define PLATFORM_SDL_GP2X_H
+#include "backends/base-backend.h"
+#include "backends/platform/sdl/sdl.h"
#include "backends/platform/sdl/posix/posix.h"
+#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
+#include "backends/events/gp2xsdl/gp2xsdl-events.h"
#ifndef PATH_MAX
#define PATH_MAX 255
@@ -34,12 +38,15 @@
class OSystem_GP2X : public OSystem_POSIX {
public:
- virtual void initBackend();
- virtual void quit();
- virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+ OSystem_GP2X() {}
+
+ void initBackend();
+ void quit();
+ void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+ void initSDL();
protected:
- virtual void initSDL();
+
};
#endif
diff --git a/backends/platform/gp2x/gp2x-main.cpp b/backends/platform/gp2x/gp2x-main.cpp
index a194accd77..f1ee5ed5f3 100644
--- a/backends/platform/gp2x/gp2x-main.cpp
+++ b/backends/platform/gp2x/gp2x-main.cpp
@@ -18,15 +18,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
#include "backends/platform/gp2x/gp2x-common.h"
-#include "backends/plugins/posix/posix-provider.h"
+#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
+#if defined(GP2X)
int main(int argc, char *argv[]) {
// Create our OSystem instance
@@ -37,7 +35,7 @@ int main(int argc, char *argv[]) {
((OSystem_GP2X *)g_system)->init();
#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new POSIXPluginProvider());
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
@@ -48,3 +46,5 @@ int main(int argc, char *argv[]) {
return res;
}
+
+#endif
diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp
index 8ae54d679c..4cdb4cd0d5 100644
--- a/backends/platform/gp2x/gp2x.cpp
+++ b/backends/platform/gp2x/gp2x.cpp
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
/*
@@ -31,12 +28,11 @@
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "backends/platform/sdl/sdl-sys.h"
#include "backends/platform/gp2x/gp2x-common.h"
#include "backends/platform/gp2x/gp2x-hw.h"
#include "backends/platform/gp2x/gp2x-mem.h"
-#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
-#include "backends/events/gp2xsdl/gp2xsdl-events.h"
#include "backends/saves/default/default-saves.h"
#include "common/config-manager.h"
@@ -143,7 +139,7 @@ void OSystem_GP2X::initBackend() {
if (_graphicsManager == 0)
_graphicsManager = new GP2XSdlGraphicsManager(_eventSource);
- // Call parent implementation of this method
+ /* Pass to POSIX method to do the heavy lifting */
OSystem_POSIX::initBackend();
}
diff --git a/backends/platform/gph/caanoo/build.sh b/backends/platform/gph/build/caanoo-build.sh
index 8000d2595d..8000d2595d 100755..100644
--- a/backends/platform/gph/caanoo/build.sh
+++ b/backends/platform/gph/build/caanoo-build.sh
diff --git a/backends/platform/gph/caanoo/bundle-debug.sh b/backends/platform/gph/build/caanoo-bundle-debug.sh
index 2d5cefe80e..2d5cefe80e 100755..100644
--- a/backends/platform/gph/caanoo/bundle-debug.sh
+++ b/backends/platform/gph/build/caanoo-bundle-debug.sh
diff --git a/backends/platform/gph/caanoo/bundle.sh b/backends/platform/gph/build/caanoo-bundle.sh
index 76fd31cec6..76fd31cec6 100755..100644
--- a/backends/platform/gph/caanoo/bundle.sh
+++ b/backends/platform/gph/build/caanoo-bundle.sh
diff --git a/backends/platform/gph/caanoo/config-alleng.sh b/backends/platform/gph/build/caanoo-config-alleng.sh
index 97fed942fa..97fed942fa 100755..100644
--- a/backends/platform/gph/caanoo/config-alleng.sh
+++ b/backends/platform/gph/build/caanoo-config-alleng.sh
diff --git a/backends/platform/gph/caanoo/config.sh b/backends/platform/gph/build/caanoo-config.sh
index 11d597481a..11d597481a 100755..100644
--- a/backends/platform/gph/caanoo/config.sh
+++ b/backends/platform/gph/build/caanoo-config.sh
diff --git a/backends/platform/gph/build/clean.sh b/backends/platform/gph/build/clean.sh
index 5ec1b9e62c..6d58b7a975 100755
--- a/backends/platform/gph/build/clean.sh
+++ b/backends/platform/gph/build/clean.sh
@@ -4,5 +4,5 @@ echo Quick script to make building all the time less painful.
cd ../../../..
-echo Cleaning ScummVM for the GP2X Wiz.
+echo Cleaning ScummVM for the GPH devices.
make clean
diff --git a/backends/platform/gp2x/build/build.sh b/backends/platform/gph/build/gp2x-build.sh
index 1ea77f4937..1ea77f4937 100755..100644
--- a/backends/platform/gp2x/build/build.sh
+++ b/backends/platform/gph/build/gp2x-build.sh
diff --git a/backends/platform/gph/build/gp2x-bundle.sh b/backends/platform/gph/build/gp2x-bundle.sh
new file mode 100644
index 0000000000..c4fe63ed9e
--- /dev/null
+++ b/backends/platform/gph/build/gp2x-bundle.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+echo Quick script to make building a distribution of the GP2X port more consistent.
+
+# Set the paths up here to support the build.
+
+export PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin:$PATH
+export PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin:$PATH
+export CXX=arm-open2x-linux-g++
+export CC=arm-open2x-linux-gcc
+export CXXFLAGS=-march=armv4t
+export LDFLAGS=-static
+export ASFLAGS=-mfloat-abi=soft
+
+cd ../../../..
+
+echo Building ScummVM for GP2X Wiz.
+
+make gp2x-bundle
diff --git a/backends/platform/gp2x/build/config-alleng.sh b/backends/platform/gph/build/gp2x-config-alleng.sh
index 4a3526d50c..4a3526d50c 100755..100644
--- a/backends/platform/gp2x/build/config-alleng.sh
+++ b/backends/platform/gph/build/gp2x-config-alleng.sh
diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gph/build/gp2x-config.sh
index e0a1bf1209..9092b0b1ea 100755..100644
--- a/backends/platform/gp2x/build/config.sh
+++ b/backends/platform/gph/build/gp2x-config.sh
@@ -17,7 +17,7 @@ export DEFINES=-DNDEBUG
# Edit the configure line to suit.
cd ../../../..
-./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd
+./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd --enable-plugins --default-dynamic
# --disable-release --enable-debug
# --enable-plugins --default-dynamic
diff --git a/backends/platform/gph/build/build.sh b/backends/platform/gph/build/gp2xwiz-build.sh
index 876c3e378a..876c3e378a 100755..100644
--- a/backends/platform/gph/build/build.sh
+++ b/backends/platform/gph/build/gp2xwiz-build.sh
diff --git a/backends/platform/gph/build/bundle-debug.sh b/backends/platform/gph/build/gp2xwiz-bundle-debug.sh
index cd5145b31d..cd5145b31d 100755..100644
--- a/backends/platform/gph/build/bundle-debug.sh
+++ b/backends/platform/gph/build/gp2xwiz-bundle-debug.sh
diff --git a/backends/platform/gph/build/bundle.sh b/backends/platform/gph/build/gp2xwiz-bundle.sh
index 579e2dc77b..579e2dc77b 100755..100644
--- a/backends/platform/gph/build/bundle.sh
+++ b/backends/platform/gph/build/gp2xwiz-bundle.sh
diff --git a/backends/platform/gph/build/config-alleng.sh b/backends/platform/gph/build/gp2xwiz-config-alleng.sh
index 9ec8a09cd2..9ec8a09cd2 100755..100644
--- a/backends/platform/gph/build/config-alleng.sh
+++ b/backends/platform/gph/build/gp2xwiz-config-alleng.sh
diff --git a/backends/platform/gph/build/config.sh b/backends/platform/gph/build/gp2xwiz-config.sh
index ac7c34ad12..ac7c34ad12 100755..100644
--- a/backends/platform/gph/build/config.sh
+++ b/backends/platform/gph/build/gp2xwiz-config.sh
diff --git a/backends/platform/gph/build/scummvm.png b/backends/platform/gph/build/scummvm.png
deleted file mode 100644
index 128e59efc4..0000000000
--- a/backends/platform/gph/build/scummvm.png
+++ /dev/null
Binary files differ
diff --git a/backends/platform/gph/caanoo-bundle.mk b/backends/platform/gph/caanoo-bundle.mk
index b7b3c9e188..8aabca9028 100755
--- a/backends/platform/gph/caanoo-bundle.mk
+++ b/backends/platform/gph/caanoo-bundle.mk
@@ -14,11 +14,11 @@ caanoo-bundle: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm.gpe $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/caanoo/scummvm.gpe $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
@@ -45,11 +45,11 @@ caanoo-bundle-debug: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
diff --git a/backends/platform/gph/caanoo/clean.sh b/backends/platform/gph/caanoo/clean.sh
deleted file mode 100755
index 5ec1b9e62c..0000000000
--- a/backends/platform/gph/caanoo/clean.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-echo Quick script to make building all the time less painful.
-
-cd ../../../..
-
-echo Cleaning ScummVM for the GP2X Wiz.
-make clean
diff --git a/backends/platform/gph/build/scummvm-gdb.gpe b/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe
index 63ce193ca8..63ce193ca8 100755..100644
--- a/backends/platform/gph/build/scummvm-gdb.gpe
+++ b/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe
diff --git a/backends/platform/gph/caanoo/scummvm.gpe b/backends/platform/gph/devices/caanoo/scummvm.gpe
index 37d0f65d18..37d0f65d18 100755..100644
--- a/backends/platform/gph/caanoo/scummvm.gpe
+++ b/backends/platform/gph/devices/caanoo/scummvm.gpe
diff --git a/backends/platform/gph/build/README-GPH b/backends/platform/gph/devices/common/README-GPH
index 64b9fcb76b..ea196f6649 100644
--- a/backends/platform/gph/build/README-GPH
+++ b/backends/platform/gph/devices/common/README-GPH
@@ -1,4 +1,4 @@
-ScummVM - GPH SPECIFIC README
+ScummVM - GPH DEVICE SPECIFIC README
------------------------------------------------------------------------
Contents:
@@ -29,7 +29,7 @@ control information.
About the backend/port
This is the readme for the official GPH ScummVM backend (also known as
-the GP2X port/GP2XWiz port and Caanoo port).
+the GP2X port/GP2XWiz port or Caanoo port).
This is an SVN test release of ScummVM for GPH devices, it would be
appreciated if this SVN test distribution was not mirrored and that
diff --git a/backends/platform/gph/build/scummvm.ini b/backends/platform/gph/devices/common/scummvm.ini
index c9cce92379..c9cce92379 100644
--- a/backends/platform/gph/build/scummvm.ini
+++ b/backends/platform/gph/devices/common/scummvm.ini
diff --git a/backends/platform/gp2x/build/scummvm.png b/backends/platform/gph/devices/common/scummvm.png
index 128e59efc4..128e59efc4 100644
--- a/backends/platform/gp2x/build/scummvm.png
+++ b/backends/platform/gph/devices/common/scummvm.png
Binary files differ
diff --git a/backends/platform/gph/build/scummvmb.png b/backends/platform/gph/devices/common/scummvmb.png
index 24a27bc0e1..24a27bc0e1 100644
--- a/backends/platform/gph/build/scummvmb.png
+++ b/backends/platform/gph/devices/common/scummvmb.png
Binary files differ
diff --git a/backends/platform/gp2x/mmuhack/Makefile b/backends/platform/gph/devices/gp2x/mmuhack/Makefile
index a35d5c2a98..a35d5c2a98 100644
--- a/backends/platform/gp2x/mmuhack/Makefile
+++ b/backends/platform/gph/devices/gp2x/mmuhack/Makefile
diff --git a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.h b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h
index 520841ace7..520841ace7 100644
--- a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.h
+++ b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h
diff --git a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.s b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s
index 17628c156a..17628c156a 100644
--- a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.s
+++ b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s
diff --git a/backends/platform/gp2x/mmuhack/mmuhack.c b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c
index 7e27262e5f..7e27262e5f 100644
--- a/backends/platform/gp2x/mmuhack/mmuhack.c
+++ b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c
diff --git a/backends/platform/gp2x/build/mmuhack.o b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o
index 475f4a54ae..475f4a54ae 100644
--- a/backends/platform/gp2x/build/mmuhack.o
+++ b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o
Binary files differ
diff --git a/backends/platform/gp2x/mmuhack/readme.txt b/backends/platform/gph/devices/gp2x/mmuhack/readme.txt
index bea49d7d6d..bea49d7d6d 100644
--- a/backends/platform/gp2x/mmuhack/readme.txt
+++ b/backends/platform/gph/devices/gp2x/mmuhack/readme.txt
diff --git a/backends/platform/gp2x/build/scummvm.gpe b/backends/platform/gph/devices/gp2x/scummvm.gpe
index c6b051831c..e8983aa2ce 100755..100644
--- a/backends/platform/gp2x/build/scummvm.gpe
+++ b/backends/platform/gph/devices/gp2x/scummvm.gpe
@@ -3,6 +3,10 @@
# Remount SD with forced Sync, does this really work?
mount -o sync,remount /dev/mmcsd/disc0/part1 /mnt/sd/
+# Export the location of any libs ScummVM depends on
+# (to avoid installing to the NAND and overwriting the broken ones there).
+export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH
+
# Run ScummVM, important this bit.
./scummvm.gph
diff --git a/backends/platform/gph/caanoo/scummvm-gdb.gpe b/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe
index 63ce193ca8..63ce193ca8 100755..100644
--- a/backends/platform/gph/caanoo/scummvm-gdb.gpe
+++ b/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe
diff --git a/backends/platform/gph/build/scummvm.gpe b/backends/platform/gph/devices/gp2xwiz/scummvm.gpe
index 59ff562aeb..59ff562aeb 100755..100644
--- a/backends/platform/gph/build/scummvm.gpe
+++ b/backends/platform/gph/devices/gp2xwiz/scummvm.gpe
diff --git a/backends/platform/gp2x/gp2x-bundle.mk b/backends/platform/gph/gp2x-bundle.mk
index 67d22d1889..810ff8b8f0 100755..100644
--- a/backends/platform/gp2x/gp2x-bundle.mk
+++ b/backends/platform/gph/gp2x-bundle.mk
@@ -1,18 +1,21 @@
# Special target to create bundles for the GP2X.
bundle_name = release/scummvm-gp2x
+f=$(shell which $(STRIP))
+libloc = $(shell dirname $(f))
gp2x-bundle: $(EXECUTABLE)
$(MKDIR) "$(bundle_name)"
$(MKDIR) "$(bundle_name)/saves"
$(MKDIR) "$(bundle_name)/engine-data"
+ $(MKDIR) "$(bundle_name)/lib"
echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/scummvm.gpe $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/
@@ -27,6 +30,8 @@ ifdef DYNAMIC_MODULES
$(STRIP) $(bundle_name)/plugins/*
endif
+ $(CP) $(libloc)/../arm-open2x-linux/lib/libdl.so $(bundle_name)/lib/libdl.so
+
tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 .
rm -R ./$(bundle_name)
@@ -37,10 +42,10 @@ gp2x-bundle-debug: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/scummvm.gpe $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/
@@ -54,6 +59,8 @@ ifdef DYNAMIC_MODULES
$(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins"
endif
+ $(CP) $(libloc)/../arm-open2x-linux/lib/libdl.so $(bundle_name)/lib/libdl.so
+
tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 .
rm -R ./$(bundle_name)
diff --git a/backends/platform/gph/gp2xwiz-bundle.mk b/backends/platform/gph/gp2xwiz-bundle.mk
index df4cae7f4f..65e2952fde 100755
--- a/backends/platform/gph/gp2xwiz-bundle.mk
+++ b/backends/platform/gph/gp2xwiz-bundle.mk
@@ -1,6 +1,5 @@
# Special target to create bundles for the GP2X Wiz.
-#bundle_name = release/scummvm-wiz-`date '+%Y-%m-%d'`
bundle_name = release/scummvm-gp2xwiz
f=$(shell which $(STRIP))
libloc = $(shell dirname $(f))
@@ -14,11 +13,11 @@ gp2xwiz-bundle: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.gpe $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2xwiz/scummvm.gpe $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
@@ -48,11 +47,11 @@ gp2xwiz-bundle-debug: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
diff --git a/backends/platform/gph/gph-backend.cpp b/backends/platform/gph/gph-backend.cpp
new file mode 100644
index 0000000000..0432974246
--- /dev/null
+++ b/backends/platform/gph/gph-backend.cpp
@@ -0,0 +1,211 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/platform/sdl/sdl-sys.h"
+
+// #include "backends/platform/gph/gph-options.h"
+#include "backends/platform/gph/gph-sdl.h"
+#include "backends/platform/gph/gph-hw.h"
+#include "backends/plugins/posix/posix-provider.h"
+#include "base/main.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/util.h"
+
+#include "common/file.h"
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+
+#include "backends/timer/default/default-timer.h"
+#include "audio/mixer_intern.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <time.h> // for getTimeAndDate()
+
+/* Dump console info to files. */
+#define DUMP_STDOUT
+
+void OSystem_GPH::initBackend() {
+
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new GPHEventSource();
+
+ // Create the graphics manager
+ if (_graphicsManager == 0) {
+ _graphicsManager = new GPHGraphicsManager(_eventSource);
+ }
+
+ /* Setup default save path to be workingdir/saves */
+
+ char savePath[PATH_MAX+1];
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Could not obtain current working directory");
+ } else {
+ printf("Current working directory: %s\n", workDirName);
+ }
+
+ strcpy(savePath, workDirName);
+ strcat(savePath, "/saves");
+ printf("Current save directory: %s\n", savePath);
+ struct stat sb;
+ if (stat(savePath, &sb) == -1)
+ if (errno == ENOENT) // Create the dir if it does not exist
+ if (mkdir(savePath, 0755) != 0)
+ warning("mkdir for '%s' failed!", savePath);
+
+ _savefileManager = new DefaultSaveFileManager(savePath);
+
+ #ifdef DUMP_STDOUT
+ // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we
+ // output all our STDOUT and STDERR to files for debug purposes.
+ char STDOUT_FILE[PATH_MAX+1];
+ char STDERR_FILE[PATH_MAX+1];
+
+ strcpy(STDOUT_FILE, workDirName);
+ strcpy(STDERR_FILE, workDirName);
+ strcat(STDOUT_FILE, "/scummvm.stdout.txt");
+ strcat(STDERR_FILE, "/scummvm.stderr.txt");
+
+ // Flush the output in case anything is queued
+ fclose(stdout);
+ fclose(stderr);
+
+ // Redirect standard input and standard output
+ FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
+ if (newfp == NULL) {
+ #if !defined(stdout)
+ stdout = fopen(STDOUT_FILE, "w");
+ #else
+ newfp = fopen(STDOUT_FILE, "w");
+ if (newfp) {
+ *stdout = *newfp;
+ }
+ #endif
+ }
+
+ newfp = freopen(STDERR_FILE, "w", stderr);
+ if (newfp == NULL) {
+ #if !defined(stderr)
+ stderr = fopen(STDERR_FILE, "w");
+ #else
+ newfp = fopen(STDERR_FILE, "w");
+ if (newfp) {
+ *stderr = *newfp;
+ }
+ #endif
+ }
+
+ setbuf(stderr, NULL);
+ printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
+ #endif /* DUMP_STDOUT */
+
+ /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */
+ WIZ_HW::deviceInit();
+
+ /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */
+ WIZ_HW::mixerMoveVolume(0);
+
+ /* Up default volume values as we use a seperate system level volume anyway. */
+ ConfMan.registerDefault("music_volume", 192);
+ ConfMan.registerDefault("sfx_volume", 192);
+ ConfMan.registerDefault("speech_volume", 192);
+
+ /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */
+ ConfMan.registerDefault("autosave_period", 4 * 60);
+
+ /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */
+ ConfMan.registerDefault("aspect_ratio", true);
+
+ /* Make sure SDL knows that we have a joystick we want to use. */
+ ConfMan.setInt("joystick_num", 0);
+
+ /* Now setup any device specific user options (Left handed mode, that sort of thing). */
+ // GPH::setOptions();
+
+ printf("%s\n", "Passing to OSystem::SDL initBackend.");
+
+ /* Pass to POSIX method to do the heavy lifting */
+ OSystem_POSIX::initBackend();
+}
+
+void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+
+ /* Setup default extra data paths for engine data files and plugins */
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Error: Could not obtain current working directory");
+ }
+
+ Common::FSNode workdirNode(workDirName);
+ if (workdirNode.exists() && workdirNode.isDirectory()) {
+ s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority);
+ }
+
+ char enginedataPath[PATH_MAX+1];
+
+ strcpy(enginedataPath, workDirName);
+ strcat(enginedataPath, "/engine-data");
+
+ Common::FSNode engineNode(enginedataPath);
+ if (engineNode.exists() && engineNode.isDirectory()) {
+ s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
+ }
+
+ char pluginsPath[PATH_MAX+1];
+
+ strcpy(pluginsPath, workDirName);
+ strcat(pluginsPath, "/plugins");
+
+ Common::FSNode pluginsNode(pluginsPath);
+ if (pluginsNode.exists() && pluginsNode.isDirectory()) {
+ s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority);
+ }
+}
+
+void OSystem_GPH::quit() {
+
+ WIZ_HW::deviceDeinit();
+
+ #ifdef DUMP_STDOUT
+ printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
+ fclose(stdout);
+ fclose(stderr);
+ #endif /* DUMP_STDOUT */
+
+ OSystem_SDL::quit();
+}
diff --git a/backends/platform/gph/gph-main.cpp b/backends/platform/gph/gph-main.cpp
index e711135c15..f91ec8f478 100644
--- a/backends/platform/gph/gph-main.cpp
+++ b/backends/platform/gph/gph-main.cpp
@@ -18,199 +18,34 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
-#include "backends/platform/sdl/sdl-sys.h"
-
-// #include "backends/platform/gph/gph-options.h"
#include "backends/platform/gph/gph-sdl.h"
-#include "backends/platform/gph/gph-hw.h"
-#include "backends/plugins/posix/posix-provider.h"
+#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
-#include "common/archive.h"
-#include "common/config-manager.h"
-#include "common/debug.h"
-#include "common/events.h"
-#include "common/util.h"
-
-#include "common/file.h"
-#include "base/main.h"
-
-#include "backends/saves/default/default-saves.h"
-
-#include "backends/timer/default/default-timer.h"
-#include "audio/mixer_intern.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h> // for getTimeAndDate()
-
-/* Dump console info to files. */
-#define DUMP_STDOUT
+#if defined(GPH_DEVICE)
int main(int argc, char *argv[]) {
+
+ // Create our OSystem instance
g_system = new OSystem_GPH();
assert(g_system);
+
+ // Pre initialize the backend
+ ((OSystem_GPH *)g_system)->init();
+
#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new POSIXPluginProvider());
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
- g_system->quit();
-
- return res;
-}
-
-void OSystem_GPH::initBackend() {
-
- /* Setup default save path to be workingdir/saves */
-
- char savePath[PATH_MAX+1];
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Could not obtain current working directory");
- } else {
- printf("Current working directory: %s\n", workDirName);
- }
-
- strcpy(savePath, workDirName);
- strcat(savePath, "/saves");
- printf("Current save directory: %s\n", savePath);
- struct stat sb;
- if (stat(savePath, &sb) == -1)
- if (errno == ENOENT) // Create the dir if it does not exist
- if (mkdir(savePath, 0755) != 0)
- warning("mkdir for '%s' failed!", savePath);
-
- _savefile = new DefaultSaveFileManager(savePath);
-
- #ifdef DUMP_STDOUT
- // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we
- // output all our STDOUT and STDERR to files for debug purposes.
- char STDOUT_FILE[PATH_MAX+1];
- char STDERR_FILE[PATH_MAX+1];
-
- strcpy(STDOUT_FILE, workDirName);
- strcpy(STDERR_FILE, workDirName);
- strcat(STDOUT_FILE, "/scummvm.stdout.txt");
- strcat(STDERR_FILE, "/scummvm.stderr.txt");
-
- // Flush the output in case anything is queued
- fclose(stdout);
- fclose(stderr);
-
- // Redirect standard input and standard output
- FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
- if (newfp == NULL) {
- #if !defined(stdout)
- stdout = fopen(STDOUT_FILE, "w");
- #else
- newfp = fopen(STDOUT_FILE, "w");
- if (newfp) {
- *stdout = *newfp;
- }
- #endif
- }
-
- newfp = freopen(STDERR_FILE, "w", stderr);
- if (newfp == NULL) {
- #if !defined(stderr)
- stderr = fopen(STDERR_FILE, "w");
- #else
- newfp = fopen(STDERR_FILE, "w");
- if (newfp) {
- *stderr = *newfp;
- }
- #endif
- }
- setbuf(stderr, NULL);
- printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
- #endif /* DUMP_STDOUT */
+ // Free OSystem
+ delete (OSystem_GPH *)g_system;
- /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */
- WIZ_HW::deviceInit();
-
- /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */
- WIZ_HW::mixerMoveVolume(0);
-
- /* Up default volume values as we use a seperate system level volume anyway. */
- ConfMan.registerDefault("music_volume", 192);
- ConfMan.registerDefault("sfx_volume", 192);
- ConfMan.registerDefault("speech_volume", 192);
-
- /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */
- ConfMan.registerDefault("autosave_period", 4 * 60);
-
- /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */
- ConfMan.registerDefault("aspect_ratio", true);
-
- /* Make sure SDL knows that we have a joystick we want to use. */
- ConfMan.setInt("joystick_num", 0);
-
- /* Now setup any device specific user options (Left handed mode, that sort of thing). */
- // GPH::setOptions();
-
- printf("%s\n", "Passing to OSystem::SDL initBackend.");
-
- /* Pass to SDL backend to do the heavy lifting */
- OSystem_SDL::initBackend();
-}
-
-void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
-
- /* Setup default extra data paths for engine data files and plugins */
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Error: Could not obtain current working directory");
- }
-
- Common::FSNode workdirNode(workDirName);
- if (workdirNode.exists() && workdirNode.isDirectory()) {
- s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority);
- }
-
- char enginedataPath[PATH_MAX+1];
-
- strcpy(enginedataPath, workDirName);
- strcat(enginedataPath, "/engine-data");
-
- Common::FSNode engineNode(enginedataPath);
- if (engineNode.exists() && engineNode.isDirectory()) {
- s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
- }
-
- char pluginsPath[PATH_MAX+1];
-
- strcpy(pluginsPath, workDirName);
- strcat(pluginsPath, "/plugins");
-
- Common::FSNode pluginsNode(pluginsPath);
- if (pluginsNode.exists() && pluginsNode.isDirectory()) {
- s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority);
- }
+ return res;
}
-void OSystem_GPH::quit() {
-
- WIZ_HW::deviceDeinit();
-
- #ifdef DUMP_STDOUT
- printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
- fclose(stdout);
- fclose(stderr);
- #endif /* DUMP_STDOUT */
-
- OSystem_SDL::quit();
-}
+#endif
diff --git a/backends/platform/gph/gph-sdl.h b/backends/platform/gph/gph-sdl.h
index 136363f9a0..51c609d29e 100644
--- a/backends/platform/gph/gph-sdl.h
+++ b/backends/platform/gph/gph-sdl.h
@@ -18,20 +18,18 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
-#ifndef GPH_SDL_H
-#define GPH_SDL_H
+#ifndef GPH_H
+#define GPH_H
-#include "backends/platform/sdl/sdl.h"
+#if defined(GPH_DEVICE)
-// FIXME: For now keep hacks in this header to save polluting the SDL backend.
-enum {
- GFX_HALF = 12
-};
+#include "backends/base-backend.h"
+#include "backends/platform/sdl/sdl.h"
+#include "backends/platform/sdl/posix/posix.h"
+#include "backends/graphics/gph/gph-graphics.h"
+#include "backends/events/gph/gph-events.h"
#define __GP2XWIZ__
#define MIXER_DOUBLE_BUFFERING 1
@@ -40,42 +38,13 @@ enum {
#define PATH_MAX 255
#endif
-class OSystem_GPH : public OSystem_SDL {
+class OSystem_GPH : public OSystem_POSIX {
public:
- OSystem_GPH() {}
-
- /* Graphics */
- void initSize(uint w, uint h);
- void setGraphicsModeIntern();
- bool setGraphicsMode(int mode);
- void internUpdateScreen();
- const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
- bool setGraphicsMode(const char *name);
- int getDefaultGraphicsMode() const;
- bool loadGFXMode();
- void drawMouse();
- void undrawMouse();
- void showOverlay();
- void hideOverlay();
-
- /* Event Stuff */
- void moveStick();
- void fillMouseEvent(Common::Event&, int, int);
- void warpMouse(int, int);
- bool remapKey(SDL_Event&, Common::Event&);
-
/* Platform Setup Stuff */
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
void initBackend();
void quit();
-
-protected:
- bool _stickBtn[32];
-
- bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
- bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
- bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
- bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
};
-#endif //GPH_SDL_H
+#endif
+#endif //GPH_H
diff --git a/backends/platform/gph/module.mk b/backends/platform/gph/module.mk
index f5567f581e..a9951494d1 100644
--- a/backends/platform/gph/module.mk
+++ b/backends/platform/gph/module.mk
@@ -1,10 +1,9 @@
MODULE := backends/platform/gph
MODULE_OBJS := \
- gph-events.o \
- gph-graphics.o \
- gph-hw.o \
- gph-main.o
+ gph-main.o \
+ gph-backend.o \
+ gph-hw.o
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
diff --git a/backends/platform/iphone/osys_video.cpp b/backends/platform/iphone/osys_video.cpp
index ee27e4d87c..d67d38932a 100644
--- a/backends/platform/iphone/osys_video.cpp
+++ b/backends/platform/iphone/osys_video.cpp
@@ -102,7 +102,7 @@ void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) {
for (uint i = start; i < start + num; ++i) {
_palette[i] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(b[0], b[1], b[2]);
- b += 4;
+ b += 3;
}
dirtyFullScreen();
@@ -114,8 +114,7 @@ void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) {
for (uint i = start; i < start + num; ++i) {
Graphics::colorToRGB<Graphics::ColorMasks<565> >(_palette[i], b[0], b[1], b[2]);
- b[3] = 0xFF;
- b += 4;
+ b += 3;
}
}
diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h
index 5264a8a82e..2daa41a9f6 100644
--- a/backends/platform/n64/osys_n64.h
+++ b/backends/platform/n64/osys_n64.h
@@ -93,7 +93,7 @@ protected:
uint16 *_screenPalette; // Array for palette entries (256 colors max)
#ifndef N64_EXTREME_MEMORY_SAVING
- uint32 *_screenExactPalette; // Array for palette entries, as received by setPalette(), no precision loss
+ uint8 *_screenExactPalette; // Array for palette entries, as received by setPalette(), no precision loss
#endif
uint16 _cursorPalette[256]; // Palette entries for the cursor
@@ -111,7 +111,10 @@ protected:
bool _cursorPaletteDisabled;
bool _dirtyPalette;
- uint _cursorWidth, _cursorHeight;
+ // FIXME: This must be left as "int" for now, to fix the sign-comparison problem
+ // there is a little more work involved than an int->uint change
+ int _cursorWidth, _cursorHeight;
+
int _cursorKeycolor;
uint16 _overlayHeight, _overlayWidth;
diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp
index 1b9c704225..54eab0fd52 100644
--- a/backends/platform/n64/osys_n64_base.cpp
+++ b/backends/platform/n64/osys_n64_base.cpp
@@ -113,8 +113,8 @@ OSystem_N64::OSystem_N64() {
// Clear palette array
_screenPalette = (uint16*)memalign(8, 256 * sizeof(uint16));
#ifndef N64_EXTREME_MEMORY_SAVING
- _screenExactPalette = (uint32*)memalign(8, 256 * sizeof(uint32));
- memset(_screenExactPalette, 0, 256 * sizeof(uint32));
+ _screenExactPalette = (uint8*)memalign(8, 256 * 3);
+ memset(_screenExactPalette, 0, 256 * 3);
#endif
memset(_screenPalette, 0, 256 * sizeof(uint16));
memset(_cursorPalette, 0, 256 * sizeof(uint16));
@@ -350,12 +350,13 @@ int16 OSystem_N64::getWidth() {
}
void OSystem_N64::setPalette(const byte *colors, uint start, uint num) {
- for (uint i = 0; i < num; ++i) {
- _screenPalette[start + i] = colRGB888toBGR555(colors[2], colors[1], colors[0]);
#ifndef N64_EXTREME_MEMORY_SAVING
- _screenExactPalette[start + i] = *((uint32*)(colors));
+ memcpy(_screenExactPalette + start * 3, colors, num * 3);
#endif
- colors += 4;
+
+ for (uint i = 0; i < num; ++i) {
+ _screenPalette[start + i] = colRGB888toBGR555(colors[2], colors[1], colors[0]);
+ colors += 3;
}
// If cursor uses the game palette, we need to rebuild the hicolor buffer
@@ -413,10 +414,9 @@ void OSystem_N64::grabPalette(byte *colors, uint start, uint num) {
*colors++ = ((color & 0x1F) << 3);
*colors++ = (((color >> 5) & 0x1F) << 3);
*colors++ = (((color >> 10) & 0x1F) << 3);
- *colors++ = 0;
}
#else
- memcpy(colors, (uint8*)(_screenExactPalette + start), num * 4);
+ memcpy(colors, _screenExactPalette + start * 3, num * 3);
#endif
return;
@@ -425,7 +425,7 @@ void OSystem_N64::grabPalette(byte *colors, uint start, uint num) {
void OSystem_N64::setCursorPalette(const byte *colors, uint start, uint num) {
for (uint i = 0; i < num; ++i) {
_cursorPalette[start + i] = colRGB888toBGR555(colors[2], colors[1], colors[0]);
- colors += 4;
+ colors += 3;
}
_cursorPaletteDisabled = false;
diff --git a/backends/platform/n64/osys_n64_events.cpp b/backends/platform/n64/osys_n64_events.cpp
index 9a53051d3d..22b9addbfb 100644
--- a/backends/platform/n64/osys_n64_events.cpp
+++ b/backends/platform/n64/osys_n64_events.cpp
@@ -118,9 +118,9 @@ void OSystem_N64::readControllerAnalogInput(void) {
// Gamepad
if (abs(pad_analogX) > PAD_DEADZONE)
- mx += tan(pad_analogX * (PI / 140));
+ mx += tan(pad_analogX * (M_PI / 140));
if (abs(pad_analogY) > PAD_DEADZONE)
- my -= tan(pad_analogY * (PI / 140));
+ my -= tan(pad_analogY * (M_PI / 140));
// Mouse
if (abs(pad_mouseX) > MOUSE_DEADZONE)
diff --git a/backends/platform/openpandora/module.mk b/backends/platform/openpandora/module.mk
index 1e5f6bcd69..8e60b87aa6 100755
--- a/backends/platform/openpandora/module.mk
+++ b/backends/platform/openpandora/module.mk
@@ -1,9 +1,8 @@
MODULE := backends/platform/openpandora
MODULE_OBJS := \
- op-graphics.o \
- op-events.o \
op-options.o \
+ op-backend.o \
op-main.o
MODULE_DIRS += \
diff --git a/backends/platform/openpandora/op-backend.cpp b/backends/platform/openpandora/op-backend.cpp
new file mode 100644
index 0000000000..5b333929c9
--- /dev/null
+++ b/backends/platform/openpandora/op-backend.cpp
@@ -0,0 +1,273 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/platform/openpandora/op-sdl.h"
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/util.h"
+
+#include "common/file.h"
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+
+#include "backends/timer/default/default-timer.h"
+#include "audio/mixer_intern.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <time.h> // for getTimeAndDate()
+
+/* Dump console info to files. */
+#define DUMP_STDOUT
+
+static SDL_Cursor *hiddenCursor;
+
+static Uint32 timer_handler(Uint32 interval, void *param) {
+ ((DefaultTimerManager *)param)->handler();
+ return interval;
+}
+
+void OSystem_OP::initBackend() {
+
+ assert(!_inited);
+
+// int joystick_num = ConfMan.getInt("joystick_num");
+// uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
+//
+// if (ConfMan.hasKey("disable_sdl_parachute"))
+// sdlFlags |= SDL_INIT_NOPARACHUTE;
+//
+// if (joystick_num > -1)
+// sdlFlags |= SDL_INIT_JOYSTICK;
+//
+// if (SDL_Init(sdlFlags) == -1) {
+// error("Could not initialize SDL: %s", SDL_GetError());
+// }
+//
+
+ /* Setup default save path to be workingdir/saves */
+
+ char savePath[PATH_MAX+1];
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Could not obtain current working directory.");
+ } else {
+ printf("Current working directory: %s\n", workDirName);
+ }
+
+ strcpy(savePath, workDirName);
+ strcat(savePath, "/../saves");
+ printf("Current save directory: %s\n", savePath);
+ struct stat sb;
+ if (stat(savePath, &sb) == -1)
+ if (errno == ENOENT) // Create the dir if it does not exist
+ if (mkdir(savePath, 0755) != 0)
+ warning("mkdir for '%s' failed!", savePath);
+
+// _savefileManager = new DefaultSaveFileManager(savePath);
+
+ #ifdef DUMP_STDOUT
+ // The OpenPandora has a serial console on the EXT connection but most users do not use this so we
+ // output all our STDOUT and STDERR to files for debug purposes.
+ char STDOUT_FILE[PATH_MAX+1];
+ char STDERR_FILE[PATH_MAX+1];
+
+ strcpy(STDOUT_FILE, workDirName);
+ strcpy(STDERR_FILE, workDirName);
+ strcat(STDOUT_FILE, "/scummvm.stdout.txt");
+ strcat(STDERR_FILE, "/scummvm.stderr.txt");
+
+ // Flush the output in case anything is queued
+ fclose(stdout);
+ fclose(stderr);
+
+ // Redirect standard input and standard output
+ FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
+ if (newfp == NULL) {
+ #if !defined(stdout)
+ stdout = fopen(STDOUT_FILE, "w");
+ #else
+ newfp = fopen(STDOUT_FILE, "w");
+ if (newfp) {
+ *stdout = *newfp;
+ }
+ #endif
+ }
+
+ newfp = freopen(STDERR_FILE, "w", stderr);
+ if (newfp == NULL) {
+ #if !defined(stderr)
+ stderr = fopen(STDERR_FILE, "w");
+ #else
+ newfp = fopen(STDERR_FILE, "w");
+ if (newfp) {
+ *stderr = *newfp;
+ }
+ #endif
+ }
+
+ setbuf(stderr, NULL);
+ printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
+ #endif /* DUMP_STDOUT */
+
+ /* Trigger autosave every 4 minutes. */
+ ConfMan.registerDefault("autosave_period", 4 * 60);
+
+ ConfMan.registerDefault("fullscreen", true);
+
+ /* Make sure that aspect ratio correction is enabled on the 1st run to stop
+ users asking me what the 'wasted space' at the bottom is ;-). */
+ ConfMan.registerDefault("aspect_ratio", true);
+
+ /* Make sure SDL knows that we have a joystick we want to use. */
+ ConfMan.setInt("joystick_num", 0);
+
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new OPEventSource();
+
+ // Create the graphics manager
+ if (_graphicsManager == 0)
+ _graphicsManager = new OPGraphicsManager(_eventSource);
+
+// _graphicsMutex = createMutex();
+
+ // Invoke parent implementation of this method
+ OSystem_POSIX::initBackend();
+
+ _inited = true;
+}
+
+
+
+ // enable joystick
+// if (joystick_num > -1 && SDL_NumJoysticks() > 0) {
+// printf("Using joystick: %s\n", SDL_JoystickName(0));
+// _joystick = SDL_JoystickOpen(joystick_num);
+// }
+//
+// setupMixer();
+
+ // Note: We could implement a custom SDLTimerManager by using
+ // SDL_AddTimer. That might yield better timer resolution, but it would
+ // also change the semantics of a timer: Right now, ScummVM timers
+ // *never* run in parallel, due to the way they are implemented. If we
+ // switched to SDL_AddTimer, each timer might run in a separate thread.
+ // However, not all our code is prepared for that, so we can't just
+ // switch. Still, it's a potential future change to keep in mind.
+// _timer = new DefaultTimerManager();
+// _timerID = SDL_AddTimer(10, &timer_handler, _timer);
+
+void OSystem_OP::initSDL() {
+ // Check if SDL has not been initialized
+ if (!_initedSDL) {
+
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ if (ConfMan.hasKey("disable_sdl_parachute"))
+ sdlFlags |= SDL_INIT_NOPARACHUTE;
+
+ // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
+ if (SDL_Init(sdlFlags) == -1)
+ error("Could not initialize SDL: %s", SDL_GetError());
+
+ uint8_t hiddenCursorData = 0;
+
+ hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0);
+
+ /* On the OpenPandora we need to work around an SDL assumption that
+ returns relative mouse coordinates when you get to the screen
+ edges using the touchscreen. The workaround is to set a blank
+ SDL cursor and not disable it (Hackish I know).
+
+ The root issues likes in the Windows Manager GRAB code in SDL.
+ That is why the issue is not seen on framebuffer devices like the
+ GP2X (there is no X window manager ;)).
+ */
+ SDL_ShowCursor(SDL_ENABLE);
+ SDL_SetCursor(hiddenCursor);
+ SDL_EnableUNICODE(1);
+
+// memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
+// memset(&_videoMode, 0, sizeof(_videoMode));
+// memset(&_transactionDetails, 0, sizeof(_transactionDetails));
+
+// _videoMode.mode = GFX_DOUBLESIZE;
+// _videoMode.scaleFactor = 2;
+// _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
+// _scalerProc = Normal2x;
+// _scalerType = 0;
+
+// _videoMode.fullscreen = true;
+
+ _initedSDL = true;
+ }
+}
+
+void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+
+ /* Setup default extra data paths for engine data files and plugins */
+
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Error: Could not obtain current working directory.");
+ }
+
+ char enginedataPath[PATH_MAX+1];
+
+ strcpy(enginedataPath, workDirName);
+ strcat(enginedataPath, "/../data");
+ printf("Default engine data directory: %s\n", enginedataPath);
+
+ Common::FSNode engineNode(enginedataPath);
+ if (engineNode.exists() && engineNode.isDirectory()) {
+ s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
+ }
+}
+
+void OSystem_OP::quit() {
+
+ SDL_FreeCursor(hiddenCursor);
+
+ #ifdef DUMP_STDOUT
+ printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
+ fclose(stdout);
+ fclose(stderr);
+ #endif /* DUMP_STDOUT */
+
+ OSystem_POSIX::quit();
+}
diff --git a/backends/platform/openpandora/op-main.cpp b/backends/platform/openpandora/op-main.cpp
index 6e64baddc7..ab777fec8f 100644
--- a/backends/platform/openpandora/op-main.cpp
+++ b/backends/platform/openpandora/op-main.cpp
@@ -18,250 +18,36 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
-// Disable symbol overrides so that we can use system headers.
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/sdl-sys.h"
-
#include "backends/platform/openpandora/op-sdl.h"
#include "backends/plugins/posix/posix-provider.h"
#include "base/main.h"
-#include "common/archive.h"
-#include "common/config-manager.h"
-#include "common/debug.h"
-#include "common/events.h"
-#include "common/util.h"
-
-#include "common/file.h"
-#include "base/main.h"
-
-#include "backends/saves/default/default-saves.h"
-
-#include "backends/timer/default/default-timer.h"
-#include "audio/mixer_intern.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h> // for getTimeAndDate()
-
-/* Dump console info to files. */
-#define DUMP_STDOUT
-
-static SDL_Cursor *hiddenCursor;
+#if defined(OPENPANDORA)
int main(int argc, char *argv[]) {
+
+ // Create our OSystem instance
g_system = new OSystem_OP();
assert(g_system);
+ // Pre initialize the backend
+ //((OSystem_OP *)g_system)->init();
+
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new POSIXPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
- g_system->quit();
-
- return res;
-}
-
-static Uint32 timer_handler(Uint32 interval, void *param) {
- ((DefaultTimerManager *)param)->handler();
- return interval;
-}
-
-void OSystem_OP::initBackend() {
-
- assert(!_inited);
-
- uint8_t hiddenCursorData = 0;
-
- int joystick_num = ConfMan.getInt("joystick_num");
- uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
-
- if (ConfMan.hasKey("disable_sdl_parachute"))
- sdlFlags |= SDL_INIT_NOPARACHUTE;
-
- if (joystick_num > -1)
- sdlFlags |= SDL_INIT_JOYSTICK;
-
- if (SDL_Init(sdlFlags) == -1) {
- error("Could not initialize SDL: %s", SDL_GetError());
- }
-
- hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0);
-
- /* Setup default save path to be workingdir/saves */
-
- char savePath[PATH_MAX+1];
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Could not obtain current working directory.");
- } else {
- printf("Current working directory: %s\n", workDirName);
- }
-
- strcpy(savePath, workDirName);
- strcat(savePath, "/../saves");
- printf("Current save directory: %s\n", savePath);
- struct stat sb;
- if (stat(savePath, &sb) == -1)
- if (errno == ENOENT) // Create the dir if it does not exist
- if (mkdir(savePath, 0755) != 0)
- warning("mkdir for '%s' failed!", savePath);
-
- _savefile = new DefaultSaveFileManager(savePath);
-
- #ifdef DUMP_STDOUT
- // The OpenPandora has a serial console on the EXT connection but most users do not use this so we
- // output all our STDOUT and STDERR to files for debug purposes.
- char STDOUT_FILE[PATH_MAX+1];
- char STDERR_FILE[PATH_MAX+1];
-
- strcpy(STDOUT_FILE, workDirName);
- strcpy(STDERR_FILE, workDirName);
- strcat(STDOUT_FILE, "/scummvm.stdout.txt");
- strcat(STDERR_FILE, "/scummvm.stderr.txt");
-
- // Flush the output in case anything is queued
- fclose(stdout);
- fclose(stderr);
- // Redirect standard input and standard output
- FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
- if (newfp == NULL) {
- #if !defined(stdout)
- stdout = fopen(STDOUT_FILE, "w");
- #else
- newfp = fopen(STDOUT_FILE, "w");
- if (newfp) {
- *stdout = *newfp;
- }
- #endif
- }
+ // Free OSystem
+ delete (OSystem_OP *)g_system;
- newfp = freopen(STDERR_FILE, "w", stderr);
- if (newfp == NULL) {
- #if !defined(stderr)
- stderr = fopen(STDERR_FILE, "w");
- #else
- newfp = fopen(STDERR_FILE, "w");
- if (newfp) {
- *stderr = *newfp;
- }
- #endif
- }
-
- setbuf(stderr, NULL);
- printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
- #endif /* DUMP_STDOUT */
-
- /* Trigger autosave every 4 minutes. */
- ConfMan.registerDefault("autosave_period", 4 * 60);
-
- ConfMan.registerDefault("fullscreen", true);
-
- /* Make sure that aspect ratio correction is enabled on the 1st run to stop
- users asking me what the 'wasted space' at the bottom is ;-). */
- ConfMan.registerDefault("aspect_ratio", true);
-
- /* Make sure SDL knows that we have a joystick we want to use. */
- ConfMan.setInt("joystick_num", 0);
-
- _graphicsMutex = createMutex();
-
- /* On the OpenPandora we need to work around an SDL assumption that
- returns relative mouse coordinates when you get to the screen
- edges using the touchscreen. The workaround is to set a blank
- SDL cursor and not disable it (Hackish I know).
-
- The root issues likes in the Windows Manager GRAB code in SDL.
- That is why the issue is not seen on framebuffer devices like the
- GP2X (there is no X window manager ;)).
- */
- SDL_ShowCursor(SDL_ENABLE);
- SDL_SetCursor(hiddenCursor);
-
- // Enable unicode support if possible
- SDL_EnableUNICODE(1);
-
- memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
- memset(&_videoMode, 0, sizeof(_videoMode));
- memset(&_transactionDetails, 0, sizeof(_transactionDetails));
-
- _videoMode.mode = GFX_DOUBLESIZE;
- _videoMode.scaleFactor = 2;
- _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
- _scalerProc = Normal2x;
- _scalerType = 0;
-
- _videoMode.fullscreen = true;
-
- // enable joystick
- if (joystick_num > -1 && SDL_NumJoysticks() > 0) {
- printf("Using joystick: %s\n", SDL_JoystickName(0));
- _joystick = SDL_JoystickOpen(joystick_num);
- }
-
- setupMixer();
-
- // Note: We could implement a custom SDLTimerManager by using
- // SDL_AddTimer. That might yield better timer resolution, but it would
- // also change the semantics of a timer: Right now, ScummVM timers
- // *never* run in parallel, due to the way they are implemented. If we
- // switched to SDL_AddTimer, each timer might run in a separate thread.
- // However, not all our code is prepared for that, so we can't just
- // switch. Still, it's a potential future change to keep in mind.
- _timer = new DefaultTimerManager();
- _timerID = SDL_AddTimer(10, &timer_handler, _timer);
-
- // Invoke parent implementation of this method
- OSystem::initBackend();
-
- _inited = true;
-}
-
-void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
-
- /* Setup default extra data paths for engine data files and plugins */
-
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Error: Could not obtain current working directory.");
- }
-
- char enginedataPath[PATH_MAX+1];
-
- strcpy(enginedataPath, workDirName);
- strcat(enginedataPath, "/../data");
- printf("Default engine data directory: %s\n", enginedataPath);
-
- Common::FSNode engineNode(enginedataPath);
- if (engineNode.exists() && engineNode.isDirectory()) {
- s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
- }
+ return res;
}
-void OSystem_OP::quit() {
-
- SDL_FreeCursor(hiddenCursor);
-
- #ifdef DUMP_STDOUT
- printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
- fclose(stdout);
- fclose(stderr);
- #endif /* DUMP_STDOUT */
-
- OSystem_SDL::quit();
-}
+#endif
diff --git a/backends/platform/openpandora/op-sdl.h b/backends/platform/openpandora/op-sdl.h
index 8561b42498..93c82ca397 100644
--- a/backends/platform/openpandora/op-sdl.h
+++ b/backends/platform/openpandora/op-sdl.h
@@ -18,15 +18,18 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
- *
*/
#ifndef OP_SDL_H
#define OP_SDL_H
+#if defined(OPENPANDORA)
+
+#include "backends/base-backend.h"
#include "backends/platform/sdl/sdl.h"
+#include "backends/platform/sdl/posix/posix.h"
+#include "backends/events/openpandora/op-events.h"
+#include "backends/graphics/openpandora/op-graphics.h"
#define __OPENPANDORA__
#define MIXER_DOUBLE_BUFFERING 1
@@ -35,25 +38,18 @@
#define PATH_MAX 255
#endif
-class OSystem_OP : public OSystem_SDL {
+class OSystem_OP : public OSystem_POSIX {
public:
OSystem_OP() {}
- /* Events */
- bool handleKeyDown(SDL_Event &ev, Common::Event &event);
- bool handleKeyUp(SDL_Event &ev, Common::Event &event);
- bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
- bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
-
- /* Graphics */
- bool loadGFXMode();
-
/* Platform Setup Stuff */
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
void initBackend();
+ void initSDL();
void quit();
protected:
};
#endif
+#endif //OP_SDL_H
diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp
index c6318e73d0..a460b919fd 100644
--- a/backends/platform/ps2/Gs2dScreen.cpp
+++ b/backends/platform/ps2/Gs2dScreen.cpp
@@ -408,25 +408,33 @@ void Gs2dScreen::unlockScreen() {
SignalSema(g_DmacSema);
}
-void Gs2dScreen::setPalette(const uint32 *pal, uint8 start, uint16 num) {
+void Gs2dScreen::setPalette(const uint8 *pal, uint8 start, uint16 num) {
assert(start + num <= 256);
WaitSema(g_DmacSema);
for (uint16 cnt = 0; cnt < num; cnt++) {
uint16 dest = start + cnt;
dest = (dest & 0xE7) | ((dest & 0x8) << 1) | ((dest & 0x10) >> 1); // rearrange like the GS expects it
- _clut[dest] = pal[cnt] & 0xFFFFFF;
+
+ uint32 color = pal[0] | (pal[1] << 8) | (pal[2] << 16);
+ _clut[dest] = color;
+ pal += 3;
}
_clutChanged = true;
SignalSema(g_DmacSema);
}
-void Gs2dScreen::grabPalette(uint32 *pal, uint8 start, uint16 num) {
+void Gs2dScreen::grabPalette(uint8 *pal, uint8 start, uint16 num) {
assert(start + num <= 256);
for (uint16 cnt = 0; cnt < num; cnt++) {
uint16 src = start + cnt;
src = (src & 0xE7) | ((src & 0x8) << 1) | ((src & 0x10) >> 1);
- pal[cnt] = _clut[src];
+
+ uint32 color = _clut[src];
+ pal[0] = (color >> 0) & 0xFF;
+ pal[1] = (color >> 8) & 0xFF;
+ pal[2] = (color >> 16) & 0xFF;
+ pal += 3;
}
}
@@ -672,7 +680,7 @@ void Gs2dScreen::animThread(void) {
{ SCALE(1), SCALE(1) }, { SCALE(1), SCALE(14) },
{ SCALE(128), SCALE(1) }, { SCALE(128), SCALE(14) }
};
- float angleStep = ((2 * PI) / _tvHeight);
+ float angleStep = ((2 * M_PI) / _tvHeight);
while (!_systemQuit) {
do {
@@ -731,7 +739,7 @@ void Gs2dScreen::animThread(void) {
float z[4];
GsVertex nodes[4];
- float angle = PI / 2 + angleStep * drawY;
+ float angle = M_PI / 2 + angleStep * drawY;
float rotSin = sinf(angle);
float rotCos = cosf(angle);
for (int coord = 0; coord < 4; coord++) {
diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h
index 81f47d5f4a..358e717cbe 100644
--- a/backends/platform/ps2/Gs2dScreen.h
+++ b/backends/platform/ps2/Gs2dScreen.h
@@ -65,9 +65,9 @@ public:
void unlockScreen();
void copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w, int h);
- void setPalette(const uint32 *pal, uint8 start, uint16 num);
+ void setPalette(const uint8 *pal, uint8 start, uint16 num);
void updateScreen(void);
- void grabPalette(uint32 *pal, uint8 start, uint16 num);
+ void grabPalette(uint8 *pal, uint8 start, uint16 num);
void grabScreen(Graphics::Surface *surf);
//- overlay routines
void copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index ab7839e18f..77de74eb5b 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -544,11 +544,11 @@ void OSystem_PS2::initSize(uint width, uint height, const Graphics::PixelFormat
}
void OSystem_PS2::setPalette(const byte *colors, uint start, uint num) {
- _screen->setPalette((const uint32*)colors, (uint8)start, (uint16)num);
+ _screen->setPalette(colors, (uint8)start, (uint16)num);
}
void OSystem_PS2::grabPalette(byte *colors, uint start, uint num) {
- _screen->grabPalette((uint32*)colors, (uint8)start, (uint16)num);
+ _screen->grabPalette(colors, (uint8)start, (uint16)num);
}
void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP
index 7a3cce2b75..b520022033 100644
--- a/backends/platform/psp/README.PSP
+++ b/backends/platform/psp/README.PSP
@@ -1,4 +1,4 @@
-ScummVM-PSP 1.3.0svn README
+ScummVM-PSP 1.3.0git README
==============================================================================
Installation
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp
index 82e2d17d10..76b4a28e4a 100644
--- a/backends/platform/psp/display_client.cpp
+++ b/backends/platform/psp/display_client.cpp
@@ -110,7 +110,7 @@ void Palette::setPartial(const byte *colors, uint32 start, uint32 num, bool supp
for (uint32 i = 0; i < num; ++i) {
byte alphaVal = supportsAlpha ? src[3] : 0xFF;
*palette = (uint16)_pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal);
- src += 4;
+ src += 3;
palette++;
}
} else if (_pixelFormat.bitsPerPixel == 32) {
@@ -120,7 +120,7 @@ void Palette::setPartial(const byte *colors, uint32 start, uint32 num, bool supp
for (uint32 i = 0; i < num; ++i) {
byte alphaVal = supportsAlpha ? src[3] : 0xFF;
*palette = _pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal);
- src += 4;
+ src += 3;
palette++;
}
}
@@ -214,7 +214,6 @@ void Palette::getPartial(byte *colors, uint start, uint num) {
*colors++ = (byte)r;
*colors++ = (byte)g;
*colors++ = (byte)b;
- *colors++ = (byte)a;
palette++;
}
} else if (_pixelFormat.bitsPerPixel == 32) {
@@ -227,7 +226,6 @@ void Palette::getPartial(byte *colors, uint start, uint num) {
*colors++ = (byte)r;
*colors++ = (byte)g;
*colors++ = (byte)b;
- *colors++ = (byte)a;
palette++;
}
}
diff --git a/backends/platform/sdl/posix/posix-main.cpp b/backends/platform/sdl/posix/posix-main.cpp
index 10ed43f43f..9e778ab899 100644
--- a/backends/platform/sdl/posix/posix-main.cpp
+++ b/backends/platform/sdl/posix/posix-main.cpp
@@ -25,7 +25,7 @@
#include "common/scummsys.h"
-#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(LINUXMOTO) && !defined(GP2XWIZ) && !defined(GP2X) && !defined(DINGUX)
+#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA)
#include "backends/platform/sdl/posix/posix.h"
#include "backends/plugins/sdl/sdl-provider.h"
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index dc91bd9fe7..d6e79248f9 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -125,10 +125,10 @@ void OSystem_SDL::init() {
if (_timerManager == 0)
_timerManager = new SdlTimerManager();
- #ifdef USE_OPENGL
- // Setup a list with both SDL and OpenGL graphics modes
- setupGraphicsModes();
- #endif
+#ifdef USE_OPENGL
+ // Setup a list with both SDL and OpenGL graphics modes
+ setupGraphicsModes();
+#endif
}
void OSystem_SDL::initBackend() {
@@ -148,11 +148,15 @@ void OSystem_SDL::initBackend() {
Common::String gfxMode(ConfMan.get("gfx_mode"));
bool use_opengl = false;
const OSystem::GraphicsMode *mode = OpenGLSdlGraphicsManager::supportedGraphicsModes();
+ int i = 0;
while (mode->name) {
- if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0)
+ if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0) {
+ _graphicsMode = i + _sdlModesCount;
use_opengl = true;
+ }
mode++;
+ ++i;
}
// If the gfx_mode is from OpenGL, create the OpenGL graphics manager
@@ -210,6 +214,11 @@ void OSystem_SDL::initSDL() {
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
+#ifdef WEBOS
+ // WebOS needs this flag or otherwise the application won't start
+ sdlFlags |= SDL_INIT_VIDEO;
+#endif
+
// Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
if (SDL_Init(sdlFlags) == -1)
error("Could not initialize SDL: %s", SDL_GetError());
@@ -464,6 +473,7 @@ int OSystem_SDL::getDefaultGraphicsMode() const {
bool OSystem_SDL::setGraphicsMode(int mode) {
const OSystem::GraphicsMode *srcMode;
int i;
+
// Check if mode is from SDL or OpenGL
if (mode < _sdlModesCount) {
srcMode = SdlGraphicsManager::supportedGraphicsModes();
@@ -472,28 +482,34 @@ bool OSystem_SDL::setGraphicsMode(int mode) {
srcMode = OpenGLSdlGraphicsManager::supportedGraphicsModes();
i = _sdlModesCount;
}
+
// Loop through modes
while (srcMode->name) {
if (i == mode) {
// If the new mode and the current mode are not from the same graphics
// manager, delete and create the new mode graphics manager
if (_graphicsMode >= _sdlModesCount && mode < _sdlModesCount) {
+ debug(1, "switching to plain SDL graphics");
delete _graphicsManager;
_graphicsManager = new SdlGraphicsManager(_eventSource);
((SdlGraphicsManager *)_graphicsManager)->initEventObserver();
_graphicsManager->beginGFXTransaction();
} else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) {
+ debug(1, "switching to OpenGL graphics");
delete _graphicsManager;
_graphicsManager = new OpenGLSdlGraphicsManager();
((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver();
_graphicsManager->beginGFXTransaction();
}
+
_graphicsMode = mode;
return _graphicsManager->setGraphicsMode(srcMode->id);
}
+
i++;
srcMode++;
}
+
return false;
}
diff --git a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
index c7623d09a8..12b4cb3610 100644
--- a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
+++ b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
@@ -91,7 +91,7 @@ STATICLIBRARY esdl.lib
// *** Include paths
USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\engines
-USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\sound
+USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio
SYSTEMINCLUDE \epoc32\include\ESDL
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
index 6f14e858b0..9af6535b22 100644
--- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
+++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
@@ -91,7 +91,7 @@ STATICLIBRARY esdl.lib
// *** Include paths
USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\engines
-USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\sound
+USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio
SYSTEMINCLUDE \epoc32\include\ESDL
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
diff --git a/backends/platform/symbian/mmp/scummvm_agi.mmp.in b/backends/platform/symbian/mmp/scummvm_agi.mmp.in
index 044326405d..e2d98b9ae4 100644
--- a/backends/platform/symbian/mmp/scummvm_agi.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_agi.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\agi
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_agos.mmp.in b/backends/platform/symbian/mmp/scummvm_agos.mmp.in
index e2d1e5eff4..077111d783 100644
--- a/backends/platform/symbian/mmp/scummvm_agos.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_agos.mmp.in
@@ -65,6 +65,6 @@ SOURCEPATH ..\..\..\..\engines\agos
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in
index d25cef4ffe..b3bfbab530 100644
--- a/backends/platform/symbian/mmp/scummvm_base.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in
@@ -51,7 +51,7 @@ ALWAYS_BUILD_AS_ARM
// *** Include paths
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio
USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl
SYSTEMINCLUDE \epoc32\include\ESDL
@@ -95,7 +95,7 @@ SOURCEPATH ..\..\..\..\gui
//SOURCE KeysDialog.cpp
//SOURCE Actions.cpp
-SOURCEPATH ..\..\..\..\sound
+SOURCEPATH ..\..\..\..\audio
//START_AUTO_OBJECTS_SOUND_//
// empty base file, will be updated by Perl build scripts
@@ -110,6 +110,12 @@ SOURCE rate_arm.cpp // ARM version: add ASM .cpp wrapper
SOURCE rate_arm_asm.s // ARM version: add ASM routines
#endif
+SOURCEPATH ..\..\..\..\video
+//START_AUTO_OBJECTS_VIDEO_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_VIDEO_//
// add a few files manually, since they are not parsed from modules.mk files
SOURCEPATH ..\..\..\..
diff --git a/backends/platform/symbian/mmp/scummvm_cine.mmp.in b/backends/platform/symbian/mmp/scummvm_cine.mmp.in
index d114ec554b..2c8118ef13 100644
--- a/backends/platform/symbian/mmp/scummvm_cine.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_cine.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\cine
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in
index e4c836a68b..b43a867da3 100644
--- a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\cruise
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_draci.mmp.in b/backends/platform/symbian/mmp/scummvm_draci.mmp.in
index b10eb0b5a8..9f24927f27 100644
--- a/backends/platform/symbian/mmp/scummvm_draci.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_draci.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\draci
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in
index 529eeb9e0b..d8cc6da6ae 100644
--- a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\drascula
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_gob.mmp.in b/backends/platform/symbian/mmp/scummvm_gob.mmp.in
index fa2ce0dedf..ce94f85283 100644
--- a/backends/platform/symbian/mmp/scummvm_gob.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_gob.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\gob
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in
index 7a03cc1745..7229edf4aa 100644
--- a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\groovie
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in
index 301d23cab4..b3f9edd1e6 100644
--- a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\hugo
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
index 5fa5fdac6a..654632c229 100644
--- a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
@@ -65,5 +65,5 @@ SOURCEPATH ..\..\..\..\engines\kyra
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
index a297137f02..418730c064 100644
--- a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\lastexpress
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_lure.mmp.in b/backends/platform/symbian/mmp/scummvm_lure.mmp.in
index c4a3900a05..e1a63b602b 100644
--- a/backends/platform/symbian/mmp/scummvm_lure.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_lure.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\lure
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_m4.mmp.in b/backends/platform/symbian/mmp/scummvm_m4.mmp.in
index f4430f2e58..c2e1ce4e8b 100644
--- a/backends/platform/symbian/mmp/scummvm_m4.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_m4.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\m4
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_made.mmp.in b/backends/platform/symbian/mmp/scummvm_made.mmp.in
index bf50157224..91b9ca756d 100644
--- a/backends/platform/symbian/mmp/scummvm_made.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_made.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\made
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
index 78e931b06f..0edba5eb4d 100644
--- a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\mohawk
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
index e96ab907cd..744a756f4e 100644
--- a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\parallaction
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_queen.mmp.in b/backends/platform/symbian/mmp/scummvm_queen.mmp.in
index 4f9d9319e0..bf88744701 100644
--- a/backends/platform/symbian/mmp/scummvm_queen.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_queen.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\queen
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_saga.mmp.in b/backends/platform/symbian/mmp/scummvm_saga.mmp.in
index e5beefc0c5..a95ee1e7fd 100644
--- a/backends/platform/symbian/mmp/scummvm_saga.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_saga.mmp.in
@@ -71,5 +71,5 @@ SOURCEPATH ..\..\..\..\engines\saga
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
index eb0d1b020f..ca9e712f3f 100644
--- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\sci
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in
index 6b5d249422..0a3cd9bb7d 100644
--- a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in
@@ -82,7 +82,7 @@ SOURCE smush/codec47ARM.s // ARM version: add ASM routines
// *** Include paths
USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\scumm\smush ..\..\..\..\engines\scumm\insane
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include\libc
diff --git a/backends/platform/symbian/mmp/scummvm_sky.mmp.in b/backends/platform/symbian/mmp/scummvm_sky.mmp.in
index d1d222b1fa..1bc2301745 100644
--- a/backends/platform/symbian/mmp/scummvm_sky.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sky.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sky
// *** Include paths
USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\sky\music
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in
index 0aaf9d504b..6bf543070b 100644
--- a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sword1
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in
index 4a7181709f..cee4143f94 100644
--- a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sword2
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
index 7832fc4880..fa4ef79692 100644
--- a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\teenagent
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
index 6190ec8152..569b79ba3c 100644
--- a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\tinsel
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_toon.mmp.in b/backends/platform/symbian/mmp/scummvm_toon.mmp.in
index f2301c4ae2..f309e6d0fa 100644
--- a/backends/platform/symbian/mmp/scummvm_toon.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_toon.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\toon
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_touche.mmp.in b/backends/platform/symbian/mmp/scummvm_touche.mmp.in
index 9e4c3d0496..ab42afe304 100644
--- a/backends/platform/symbian/mmp/scummvm_touche.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_touche.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\touche
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in
index d193ac49a9..434072bc96 100644
--- a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\tucker
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/webos/main.cpp b/backends/platform/webos/main.cpp
new file mode 100644
index 0000000000..bbf55c6efd
--- /dev/null
+++ b/backends/platform/webos/main.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "backends/platform/webos/webos.h"
+#include "backends/plugins/sdl/sdl-provider.h"
+#include "base/main.h"
+
+#if defined(WEBOS)
+
+#include <unistd.h>
+
+int main(int argc, char* argv[]) {
+ g_system = new OSystem_SDL_WebOS();
+ assert(g_system);
+
+ ((OSystem_SDL_WebOS *)g_system)->init();
+
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
+#endif
+
+ // Invoke the actual ScummVM main entry point:
+ int res = scummvm_main(argc, argv);
+
+ // Free OSystem
+ delete (OSystem_SDL_WebOS *)g_system;
+
+ return res;
+}
+
+#endif
diff --git a/backends/platform/webos/module.mk b/backends/platform/webos/module.mk
new file mode 100644
index 0000000000..fe4ec1e079
--- /dev/null
+++ b/backends/platform/webos/module.mk
@@ -0,0 +1,10 @@
+MODULE := backends/platform/webos
+
+MODULE_OBJS := \
+ main.o \
+ webos.o
+
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/webos/webos.cpp b/backends/platform/webos/webos.cpp
new file mode 100644
index 0000000000..7db17f4b9f
--- /dev/null
+++ b/backends/platform/webos/webos.cpp
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "backends/platform/webos/webos.h"
+#include "backends/events/webossdl/webossdl-events.h"
+#include "backends/keymapper/keymapper.h"
+
+#if defined(WEBOS)
+
+using namespace Common;
+
+OSystem_SDL_WebOS::OSystem_SDL_WebOS()
+ :
+ OSystem_POSIX() {
+}
+
+/**
+ * Initializes the backend.
+ */
+void OSystem_SDL_WebOS::initBackend() {
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new WebOSSdlEventSource();
+
+ // Call parent implementation of this method
+ OSystem_SDL::initBackend();
+}
+
+/**
+ * Gets the original SDL hardware key set, adds WebOS specific keys and
+ * returns the new key set.
+ *
+ * @return The hardware key set with added webOS specific keys.
+ */
+HardwareKeySet *OSystem_SDL_WebOS::getHardwareKeySet() {
+#ifdef ENABLE_KEYMAPPER
+ // Get the original SDL hardware key set
+ HardwareKeySet *keySet = OSystem_SDL::getHardwareKeySet();
+
+ // Add WebOS specific keys
+ keySet->addHardwareKey(new HardwareKey("FORWARD",
+ KeyState((KeyCode) 229, 229, 0), "Forward", kActionKeyType));
+
+ // Return the modified hardware key set
+ return keySet;
+#else
+ return 0;
+#endif
+}
+
+#endif
diff --git a/backends/platform/webos/webos.h b/backends/platform/webos/webos.h
new file mode 100644
index 0000000000..1cdba703e0
--- /dev/null
+++ b/backends/platform/webos/webos.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef PLATFORM_SDL_WEBOS_H
+#define PLATFORM_SDL_WEBOS_H
+
+#include "common/system.h"
+#include "backends/platform/sdl/posix/posix.h"
+
+class OSystem_SDL_WebOS : public OSystem_POSIX {
+public:
+ OSystem_SDL_WebOS();
+
+ virtual void initBackend();
+ virtual Common::HardwareKeySet *getHardwareKeySet();
+};
+
+#endif
diff --git a/backends/platform/webos/webos.mk b/backends/platform/webos/webos.mk
new file mode 100644
index 0000000000..885c9eb90e
--- /dev/null
+++ b/backends/platform/webos/webos.mk
@@ -0,0 +1,23 @@
+# WebOS specific build targets
+
+PATH_DIST = $(srcdir)/dists/webos
+PATH_MOJO = $(PATH_DIST)/mojo
+
+STAGING_DIR=STAGING/org.scummvm.scummvm
+
+webosrelease:
+ rm -rf $(STAGING_DIR)
+ rm -f *.ipk
+ mkdir -p $(STAGING_DIR)
+ mkdir -p $(STAGING_DIR)/bin
+ mkdir -p $(STAGING_DIR)/lib
+ mkdir -p $(STAGING_DIR)/share/scummvm
+ cp -f $(PATH_MOJO)/* $(STAGING_DIR)
+ cp -f gui/themes/translations.dat $(STAGING_DIR)/share/scummvm
+ cp -f gui/themes/scummmodern.zip $(STAGING_DIR)/share/scummvm
+ cp -f scummvm $(STAGING_DIR)/bin
+ $(STRIP) $(STAGING_DIR)/bin/scummvm
+ $(WEBOS_SDK)/bin/palm-package $(STAGING_DIR)
+ rm -rf STAGING
+
+.PHONY: webosrelease
diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp
index 09575bb83d..cb9a8c72e9 100644
--- a/backends/platform/wii/osystem_gfx.cpp
+++ b/backends/platform/wii/osystem_gfx.cpp
@@ -326,23 +326,23 @@ void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) {
const byte *s = colors;
u16 *d = _texGame.palette;
- for (uint i = 0; i < num; ++i) {
+ for (uint i = 0; i < num; ++i, s +=3)
d[start + i] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(s[0], s[1], s[2]);
- s += 4;
- }
gfx_tex_flush_palette(&_texGame);
+ s = colors;
+ d = _cursorPalette;
+
+ for (uint i = 0; i < num; ++i, s += 3) {
+ d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
+ }
+
if (_cursorPaletteDisabled) {
assert(_texMouse.palette);
- s = colors;
- d = _texMouse.palette;
-
- for (uint i = 0; i < num; ++i) {
- d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
- s += 4;
- }
+ memcpy((u8 *)_texMouse.palette + start * 2,
+ (u8 *)_cursorPalette + start * 2, num * 2);
_cursorPaletteDirty = true;
}
@@ -357,13 +357,11 @@ void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) {
byte *d = colors;
u8 r, g, b;
- for (uint i = 0; i < num; ++i) {
+ for (uint i = 0; i < num; ++i, d += 3) {
Graphics::colorToRGB<Graphics::ColorMasks<565> >(s[start + i], r, g, b);
d[0] = r;
d[1] = g;
d[2] = b;
- d[3] = 0xff;
- d += 4;
}
}
@@ -388,10 +386,8 @@ void OSystem_Wii::setCursorPalette(const byte *colors, uint start, uint num) {
const byte *s = colors;
u16 *d = _texMouse.palette;
- for (uint i = 0; i < num; ++i) {
+ for (uint i = 0; i < num; ++i, s += 3)
d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
- s += 4;
- }
_cursorPaletteDirty = true;
}
diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp
index 99d0be2bdc..3895c7d6fa 100644
--- a/backends/platform/wince/CEActionsPocket.cpp
+++ b/backends/platform/wince/CEActionsPocket.cpp
@@ -38,7 +38,7 @@
#ifdef _WIN32_WCE
-#define KEY_ALL_SKIP 3457
+#define KEY_ALL_SKIP 3457
#endif
const Common::String pocketActionNames[] = {
@@ -85,14 +85,14 @@ int CEActionsPocket::version() {
}
CEActionsPocket::CEActionsPocket(const Common::String &gameid) :
-GUI::Actions() {
+ GUI::Actions() {
int i;
_right_click_needed = false;
_hide_toolbar_needed = false;
_zoom_needed = false;
- for (i=0; i<POCKET_ACTION_LAST; i++) {
+ for (i = 0; i < POCKET_ACTION_LAST; i++) {
_action_mapping[i] = 0;
_action_enabled[i] = false;
}
@@ -112,7 +112,7 @@ GUI::Actions() {
void CEActionsPocket::initInstanceMain(OSystem *mainSystem) {
// Nothing generic to do for Pocket PC
- _CESystem = static_cast<OSystem_WINCE3*>(mainSystem);
+ _CESystem = static_cast<OSystem_WINCE3 *>(mainSystem);
GUI_Actions::initInstanceMain(mainSystem);
}
@@ -126,7 +126,7 @@ void CEActionsPocket::initInstanceGame() {
bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0);
bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0);
bool is_saga = (gameid == "saga");
- bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0);
+ bool is_kyra = (strncmp(gameid.c_str(), "kyra", 4) == 0);
bool is_samnmax = (gameid == "samnmax");
bool is_cine = (gameid == "cine");
bool is_touche = (gameid == "touche");
@@ -134,7 +134,7 @@ void CEActionsPocket::initInstanceGame() {
bool is_parallaction = (gameid == "parallaction");
bool is_lure = (gameid == "lure");
bool is_feeble = (gameid == "feeble");
- bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0);
+ bool is_drascula = (strncmp(gameid.c_str(), "drascula", 8) == 0);
bool is_tucker = (gameid == "tucker");
bool is_groovie = (gameid == "groovie");
bool is_tinsel = (gameid == "tinsel");
@@ -145,7 +145,7 @@ void CEActionsPocket::initInstanceGame() {
// See if a right click mapping could be needed
if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_tinsel ||
- is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
+ is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
_right_click_needed = true;
// See if a "hide toolbar" mapping could be needed
@@ -187,7 +187,7 @@ void CEActionsPocket::initInstanceGame() {
if (!is_cine && !is_parallaction && !is_groovie && !is_cruise && !is_made)
_action_enabled[POCKET_ACTION_SKIP] = true;
if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_tinsel ||
- is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker)
+ is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker)
_key_action[POCKET_ACTION_SKIP].setKey(VK_ESCAPE);
else
_key_action[POCKET_ACTION_SKIP].setKey(KEY_ALL_SKIP);
@@ -239,10 +239,12 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
if (!pushed) {
switch (action) {
case POCKET_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(false);
+ //_CESystem->add_right_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(false);
return true;
case POCKET_ACTION_LEFTCLICK:
- _CESystem->add_left_click(false);
+ //_CESystem->add_left_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(false);
return true;
case POCKET_ACTION_PAUSE:
case POCKET_ACTION_SAVE:
@@ -272,43 +274,55 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
EventsBuffer::simulateKey(&_key_action[action], true);
return true;
case POCKET_ACTION_KEYBOARD:
- _CESystem->swap_panel();
+ //_CESystem->swap_panel();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_panel();
return true;
case POCKET_ACTION_HIDE:
- _CESystem->swap_panel_visibility();
+ //_CESystem->swap_panel_visibility();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_panel_visibility();
return true;
case POCKET_ACTION_SOUND:
_CESystem->swap_sound_master();
return true;
case POCKET_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(true);
+ //_CESystem->add_right_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(true);
return true;
case POCKET_ACTION_CURSOR:
- _CESystem->swap_mouse_visibility();
+ //_CESystem->swap_mouse_visibility();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_mouse_visibility();
return true;
case POCKET_ACTION_FREELOOK:
- _CESystem->swap_freeLook();
+ //_CESystem->swap_freeLook();
+ ((WINCESdlEventSource *)((OSystem_SDL *)g_system)->getEventManager())->swap_freeLook();
return true;
case POCKET_ACTION_ZOOM_UP:
- _CESystem->swap_zoom_up();
+ //_CESystem->swap_zoom_up();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_zoom_up();
return true;
case POCKET_ACTION_ZOOM_DOWN:
- _CESystem->swap_zoom_down();
+ //_CESystem->swap_zoom_down();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_zoom_down();
return true;
case POCKET_ACTION_LEFTCLICK:
- _CESystem->add_left_click(true);
+ //_CESystem->add_left_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(true);
return true;
case POCKET_ACTION_UP:
- _CESystem->move_cursor_up();
+ //_CESystem->move_cursor_up();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_up();
return true;
case POCKET_ACTION_DOWN:
- _CESystem->move_cursor_down();
+ //_CESystem->move_cursor_down();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_down();
return true;
case POCKET_ACTION_LEFT:
- _CESystem->move_cursor_left();
+ //_CESystem->move_cursor_left();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_left();
return true;
case POCKET_ACTION_RIGHT:
- _CESystem->move_cursor_right();
+ //_CESystem->move_cursor_right();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_right();
return true;
case POCKET_ACTION_QUIT:
if (!quitdialog) {
diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp
index 5c7feb4950..413c52af2b 100644
--- a/backends/platform/wince/CEActionsSmartphone.cpp
+++ b/backends/platform/wince/CEActionsSmartphone.cpp
@@ -36,7 +36,7 @@
#include "common/translation.h"
-#define KEY_ALL_SKIP 3457
+#define KEY_ALL_SKIP 3457
const String smartphoneActionNames[] = {
_s("Up"),
@@ -79,10 +79,10 @@ int CEActionsSmartphone::version() {
}
CEActionsSmartphone::CEActionsSmartphone()
-: GUI::Actions() {
+ : GUI::Actions() {
int i;
- for (i=0; i<SMARTPHONE_ACTION_LAST; i++) {
+ for (i = 0; i < SMARTPHONE_ACTION_LAST; i++) {
_action_mapping[i] = ACTIONS_SMARTPHONE_DEFAULT[i];
_action_enabled[i] = false;
}
@@ -90,7 +90,7 @@ CEActionsSmartphone::CEActionsSmartphone()
}
void CEActionsSmartphone::initInstanceMain(OSystem *mainSystem) {
- _CESystem = static_cast<OSystem_WINCE3*>(mainSystem);
+ _CESystem = static_cast<OSystem_WINCE3 *>(mainSystem);
GUI_Actions::initInstanceMain(mainSystem);
@@ -117,7 +117,7 @@ void CEActionsSmartphone::initInstanceGame() {
bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0);
bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0);
bool is_saga = (gameid == "saga");
- bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0);
+ bool is_kyra = (strncmp(gameid.c_str(), "kyra", 4) == 0);
bool is_samnmax = (gameid == "samnmax");
bool is_cine = (gameid == "cine");
bool is_touche = (gameid == "touche");
@@ -125,7 +125,7 @@ void CEActionsSmartphone::initInstanceGame() {
bool is_parallaction = (gameid == "parallaction");
bool is_lure = (gameid == "lure");
bool is_feeble = (gameid == "feeble");
- bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0);
+ bool is_drascula = (strncmp(gameid.c_str(), "drascula", 8) == 0);
bool is_tucker = (gameid == "tucker");
bool is_groovie = (gameid == "groovie");
bool is_tinsel = (gameid == "tinsel");
@@ -136,7 +136,7 @@ void CEActionsSmartphone::initInstanceGame() {
// See if a right click mapping could be needed
if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_tinsel ||
- is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
+ is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
_right_click_needed = true;
// Initialize keys for different actions
@@ -168,8 +168,8 @@ void CEActionsSmartphone::initInstanceGame() {
// Skip
_action_enabled[SMARTPHONE_ACTION_SKIP] = true;
if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_tinsel ||
- is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker ||
- is_groovie || is_cruise || is_made)
+ is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker ||
+ is_groovie || is_cruise || is_made)
_key_action[SMARTPHONE_ACTION_SKIP].setKey(VK_ESCAPE);
else
_key_action[SMARTPHONE_ACTION_SKIP].setKey(KEY_ALL_SKIP);
@@ -204,81 +204,92 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) {
if (!pushed) {
switch (action) {
- case SMARTPHONE_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(false);
- return true;
- case SMARTPHONE_ACTION_LEFTCLICK:
- _CESystem->add_left_click(false);
- return true;
- case SMARTPHONE_ACTION_SAVE:
- case SMARTPHONE_ACTION_SKIP:
- case SMARTPHONE_ACTION_MULTI:
- EventsBuffer::simulateKey(&_key_action[action], false);
- return true;
- }
- return false;
- }
-
- switch (action) {
- case SMARTPHONE_ACTION_SAVE:
- case SMARTPHONE_ACTION_SKIP:
- case SMARTPHONE_ACTION_MULTI:
- if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") {
- // FIXME: This is a temporary solution. The engine should handle its own menus.
- // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience
- GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save"));
- if (alert.runModal() == GUI::kMessageOK)
- _key_action[action].setKey(SDLK_l);
- else
- _key_action[action].setKey(SDLK_s);
- }
- EventsBuffer::simulateKey(&_key_action[action], true);
- return true;
case SMARTPHONE_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(true);
+ //_CESystem->add_right_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(false);
return true;
case SMARTPHONE_ACTION_LEFTCLICK:
- _CESystem->add_left_click(true);
- return true;
- case SMARTPHONE_ACTION_UP:
- _CESystem->move_cursor_up();
- return true;
- case SMARTPHONE_ACTION_DOWN:
- _CESystem->move_cursor_down();
- return true;
- case SMARTPHONE_ACTION_LEFT:
- _CESystem->move_cursor_left();
- return true;
- case SMARTPHONE_ACTION_RIGHT:
- _CESystem->move_cursor_right();
- return true;
- case SMARTPHONE_ACTION_ZONE:
- _CESystem->switch_zone();
+ //_CESystem->add_left_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(false);
return true;
- case SMARTPHONE_ACTION_BINDKEYS:
- if (!keydialogrunning) {
- keydialogrunning = true;
- GUI::KeysDialog *keysDialog = new GUI::KeysDialog();
- keysDialog->runModal();
- delete keysDialog;
- keydialogrunning = false;
- }
- return true;
- case SMARTPHONE_ACTION_KEYBOARD:
- _CESystem->swap_smartphone_keyboard();
- return true;
- case SMARTPHONE_ACTION_ROTATE:
- _CESystem->smartphone_rotate_display();
- return true;
- case SMARTPHONE_ACTION_QUIT:
- if (!quitdialog) {
- quitdialog = true;
- GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No"));
- if (alert.runModal() == GUI::kMessageOK)
- _mainSystem->quit();
- quitdialog = false;
- }
+ case SMARTPHONE_ACTION_SAVE:
+ case SMARTPHONE_ACTION_SKIP:
+ case SMARTPHONE_ACTION_MULTI:
+ EventsBuffer::simulateKey(&_key_action[action], false);
return true;
+ }
+ return false;
+ }
+
+ switch (action) {
+ case SMARTPHONE_ACTION_SAVE:
+ case SMARTPHONE_ACTION_SKIP:
+ case SMARTPHONE_ACTION_MULTI:
+ if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") {
+ // FIXME: This is a temporary solution. The engine should handle its own menus.
+ // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience
+ GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save"));
+ if (alert.runModal() == GUI::kMessageOK)
+ _key_action[action].setKey(SDLK_l);
+ else
+ _key_action[action].setKey(SDLK_s);
+ }
+ EventsBuffer::simulateKey(&_key_action[action], true);
+ return true;
+ case SMARTPHONE_ACTION_RIGHTCLICK:
+ //_CESystem->add_right_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(true);
+ return true;
+ case SMARTPHONE_ACTION_LEFTCLICK:
+ //_CESystem->add_left_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(true);
+ return true;
+ case SMARTPHONE_ACTION_UP:
+ //_CESystem->move_cursor_up();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_up();
+ return true;
+ case SMARTPHONE_ACTION_DOWN:
+ //_CESystem->move_cursor_down();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_down();
+ return true;
+ case SMARTPHONE_ACTION_LEFT:
+ //_CESystem->move_cursor_left();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_left();
+ return true;
+ case SMARTPHONE_ACTION_RIGHT:
+ //_CESystem->move_cursor_right();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_right();
+ return true;
+ case SMARTPHONE_ACTION_ZONE:
+ //_CESystem->switch_zone();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->switch_zone();
+ return true;
+ case SMARTPHONE_ACTION_BINDKEYS:
+ if (!keydialogrunning) {
+ keydialogrunning = true;
+ GUI::KeysDialog *keysDialog = new GUI::KeysDialog();
+ keysDialog->runModal();
+ delete keysDialog;
+ keydialogrunning = false;
+ }
+ return true;
+ case SMARTPHONE_ACTION_KEYBOARD:
+ //_CESystem->swap_smartphone_keyboard();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_smartphone_keyboard();
+ return true;
+ case SMARTPHONE_ACTION_ROTATE:
+ //_CESystem->smartphone_rotate_display();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->smartphone_rotate_display();
+ return true;
+ case SMARTPHONE_ACTION_QUIT:
+ if (!quitdialog) {
+ quitdialog = true;
+ GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No"));
+ if (alert.runModal() == GUI::kMessageOK)
+ _mainSystem->quit();
+ quitdialog = false;
+ }
+ return true;
}
return false;
diff --git a/backends/platform/wince/CEDevice.cpp b/backends/platform/wince/CEDevice.cpp
index d94ce6cde7..ffe2523b47 100644
--- a/backends/platform/wince/CEDevice.cpp
+++ b/backends/platform/wince/CEDevice.cpp
@@ -29,22 +29,22 @@
#include "backends/platform/wince/wince-sdl.h"
-static void (WINAPI* _SHIdleTimerReset)(void) = NULL;
-static HANDLE (WINAPI* _SetPowerRequirement)(PVOID,int,ULONG,PVOID,ULONG) = NULL;
-static DWORD (WINAPI* _ReleasePowerRequirement)(HANDLE) = NULL;
+static void (WINAPI *_SHIdleTimerReset)(void) = NULL;
+static HANDLE(WINAPI *_SetPowerRequirement)(PVOID, int, ULONG, PVOID, ULONG) = NULL;
+static DWORD (WINAPI *_ReleasePowerRequirement)(HANDLE) = NULL;
static HANDLE _hPowerManagement = NULL;
static DWORD _lastTime = 0;
static DWORD REG_bat = 0, REG_ac = 0, REG_disp = 0, bat_timeout = 0;
static bool REG_tampered = false;
#ifdef __GNUC__
extern "C" void WINAPI SystemIdleTimerReset(void);
-#define SPI_SETBATTERYIDLETIMEOUT 251
-#define SPI_GETBATTERYIDLETIMEOUT 252
+#define SPI_SETBATTERYIDLETIMEOUT 251
+#define SPI_GETBATTERYIDLETIMEOUT 252
#endif
#define TIMER_TRIGGER 9000
-DWORD CEDevice::reg_access(TCHAR *key, TCHAR *val, DWORD data) {
+DWORD CEDevice::reg_access(const TCHAR *key, const TCHAR *val, DWORD data) {
HKEY regkey;
DWORD tmpval, cbdata;
@@ -70,7 +70,7 @@ DWORD CEDevice::reg_access(TCHAR *key, TCHAR *val, DWORD data) {
void CEDevice::backlight_xchg() {
HANDLE h;
- REG_bat = reg_access(TEXT("ControlPanel\\BackLight"), TEXT("BatteryTimeout"), REG_bat);
+ REG_bat = reg_access(TEXT("ControlPanel\\BackLight"), (const TCHAR *)TEXT("BatteryTimeout"), REG_bat);
REG_ac = reg_access(TEXT("ControlPanel\\BackLight"), TEXT("ACTimeout"), REG_ac);
REG_disp = reg_access(TEXT("ControlPanel\\Power"), TEXT("Display"), REG_disp);
@@ -85,20 +85,19 @@ void CEDevice::init() {
// 2003+ power management code borrowed from MoDaCo & Betaplayer. Thanks !
HINSTANCE dll = LoadLibrary(TEXT("aygshell.dll"));
if (dll) {
- *(FARPROC*)&_SHIdleTimerReset = GetProcAddress(dll, MAKEINTRESOURCE(2006));
+ _SHIdleTimerReset = (void (*)())GetProcAddress(dll, MAKEINTRESOURCE(2006));
}
dll = LoadLibrary(TEXT("coredll.dll"));
if (dll) {
- *(FARPROC*)&_SetPowerRequirement = GetProcAddress(dll, TEXT("SetPowerRequirement"));
- *(FARPROC*)&_ReleasePowerRequirement = GetProcAddress(dll, TEXT("ReleasePowerRequirement"));
-
+ _SetPowerRequirement = (HANDLE (*)(PVOID, int, ULONG, PVOID, ULONG))GetProcAddress(dll, TEXT("SetPowerRequirement"));
+ _ReleasePowerRequirement = (DWORD (*)(HANDLE))GetProcAddress(dll, TEXT("ReleasePowerRequirement"));
}
if (_SetPowerRequirement)
_hPowerManagement = _SetPowerRequirement((PVOID) TEXT("BKL1:"), 0, 1, (PVOID) NULL, 0);
_lastTime = GetTickCount();
// older devices
- REG_bat = REG_ac = REG_disp = 2 * 60 * 60 * 1000; // 2hrs should do it
+ REG_bat = REG_ac = REG_disp = 2 * 60 * 60 * 1000; // 2hrs should do it
backlight_xchg();
REG_tampered = true;
SystemParametersInfo(SPI_GETBATTERYIDLETIMEOUT, 0, (void *) &bat_timeout, 0);
@@ -127,6 +126,10 @@ bool CEDevice::hasSquareQVGAResolution() {
return (OSystem_WINCE3::getScreenWidth() == 240 && OSystem_WINCE3::getScreenHeight() == 240);
}
+bool CEDevice::hasWideResolution() {
+ return (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640);
+}
+
bool CEDevice::hasPocketPCResolution() {
if (OSystem_WINCE3::isOzone() && hasWideResolution())
return true;
@@ -139,10 +142,6 @@ bool CEDevice::hasDesktopResolution() {
return (OSystem_WINCE3::getScreenWidth() > 320);
}
-bool CEDevice::hasWideResolution() {
- return (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640);
-}
-
bool CEDevice::hasSmartphoneResolution() {
return (OSystem_WINCE3::getScreenWidth() < 240);
}
diff --git a/backends/platform/wince/CEDevice.h b/backends/platform/wince/CEDevice.h
index b2b20d05ce..24dffca0b3 100644
--- a/backends/platform/wince/CEDevice.h
+++ b/backends/platform/wince/CEDevice.h
@@ -43,7 +43,7 @@ public:
static bool isSmartphone();
private:
- static DWORD reg_access(TCHAR *key, TCHAR *val, DWORD data);
+ static DWORD reg_access(const TCHAR *key, const TCHAR *val, DWORD data);
static void backlight_xchg();
};
diff --git a/backends/platform/wince/CEException.cpp b/backends/platform/wince/CEException.cpp
index 421db4960c..08a327136f 100644
--- a/backends/platform/wince/CEException.cpp
+++ b/backends/platform/wince/CEException.cpp
@@ -36,7 +36,7 @@ void CEException::writeBreak(HANDLE file) {
int i;
memset(tempo, 0, sizeof(tempo));
- for (i=0; i<40; i++)
+ for (i = 0; i < 40; i++)
tempo[i] = '-';
writeString(file, tempo);
}
@@ -51,23 +51,23 @@ void CEException::dumpContext(HANDLE file, HANDLE hProcess, CONTEXT *context) {
writeBreak(file);
writeString(file, "Context dump");
sprintf(tempo, "R0=%.8x R1=%.8x R2=%.8x R3=%.8x R4=%.8x", context->R0, context->R1,
- context->R2, context->R3, context->R4);
+ context->R2, context->R3, context->R4);
writeString(file, tempo);
sprintf(tempo, "R5=%.8x R6=%.8x R7=%.8x R8=%.8x R9=%.8x", context->R5, context->R6,
- context->R7, context->R8, context->R9);
+ context->R7, context->R8, context->R9);
writeString(file, tempo);
sprintf(tempo, "R10=%.8x R11=%.8x R12=%.8x", context->R10, context->R11,
- context->R12);
+ context->R12);
writeString(file, tempo);
sprintf(tempo, "Sp=%.8x Lr=%.8x Pc=%.8x Psr=%.8x", context->Sp, context->Lr,
- context->Pc, context->Psr);
+ context->Pc, context->Psr);
writeString(file, tempo);
writeBreak(file);
sprintf(tempo, "Memory dump at %.8x", context->Pc - (sizeof(memoryDump) / 2));
writeString(file, tempo);
if (ReadProcessMemory(hProcess, (LPCVOID)(context->Pc - (sizeof(memoryDump) / 2)), memoryDump, sizeof(memoryDump), &size)) {
- for (i=0; i<size; i+=8) {
+ for (i = 0; i < size; i += 8) {
int j;
char digit[4];
int max;
@@ -75,7 +75,7 @@ void CEException::dumpContext(HANDLE file, HANDLE hProcess, CONTEXT *context) {
if (max > 8)
max = 8;
tempo[0] = '\0';
- for (j=0; j<max; j++) {
+ for (j = 0; j < max; j++) {
sprintf(digit, "%.2x ", memoryDump[i + j]);
strcat(tempo, digit);
}
@@ -121,10 +121,10 @@ void CEException::dumpException(HANDLE file, EXCEPTION_RECORD *exceptionRecord)
break;
}
sprintf(tempo, "Exception %s Flags %.8x Address %.8x", exceptionName, exceptionRecord->ExceptionFlags,
- exceptionRecord->ExceptionAddress);
+ exceptionRecord->ExceptionAddress);
writeString(file, tempo);
if (exceptionRecord->NumberParameters) {
- for (i=0; i<exceptionRecord->NumberParameters; i++) {
+ for (i = 0; i < exceptionRecord->NumberParameters; i++) {
sprintf(tempo, "Parameter %d %.8x", i, exceptionRecord->ExceptionInformation[i]);
writeString(file, tempo);
}
@@ -144,8 +144,8 @@ bool CEException::writeException(TCHAR *path, EXCEPTION_POINTERS *exceptionPoint
GetSystemTime(&systemTime);
wsprintf(dumpFileName, TEXT("%s_%.2d_%.2d_%.4d_%.2d_%.2d_%.2d.txt"),
- path, systemTime.wDay, systemTime.wMonth, systemTime.wYear,
- systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
+ path, systemTime.wDay, systemTime.wMonth, systemTime.wYear,
+ systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
dumpFile = CreateFile(dumpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (dumpFile == INVALID_HANDLE_VALUE)
return false;
diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp
index de1bb2f1f6..8824af732f 100644
--- a/backends/platform/wince/CELauncherDialog.cpp
+++ b/backends/platform/wince/CELauncherDialog.cpp
@@ -48,14 +48,14 @@ using namespace Common;
class CEAboutDialog : public Dialog {
public:
CEAboutDialog()
- : Dialog(10, 60, 300, 77) {
+ : Dialog(10, 60, 300, 77) {
char tempo[100];
// FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
// needs fixing, or remove it!
const int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0);
const int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
- new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME
+ new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME
Common::String videoDriver(_("Using SDL driver "));
SDL_VideoDriverName(tempo, sizeof(tempo));
@@ -106,14 +106,13 @@ void CELauncherDialog::addGame() {
MessageDialog alert(_("Do you want to perform an automatic scan ?"), _("Yes"), _("No"));
if (alert.runModal() == kMessageOK && _browser->runModal() > 0) {
// Clear existing domains
- ConfigManager::DomainMap &domains = (ConfigManager::DomainMap&)ConfMan.getGameDomains();
+ ConfigManager::DomainMap &domains = (ConfigManager::DomainMap &)ConfMan.getGameDomains();
domains.clear();
ConfMan.flushToDisk();
automaticScanDirectory(_browser->getResult());
ConfMan.flushToDisk();
updateListing();
draw();
- }
- else
+ } else
GUILauncherDialog::addGame();
}
diff --git a/backends/platform/wince/CEgui/GUIElement.cpp b/backends/platform/wince/CEgui/GUIElement.cpp
index dd463c22a1..e7ffc8d473 100644
--- a/backends/platform/wince/CEgui/GUIElement.cpp
+++ b/backends/platform/wince/CEgui/GUIElement.cpp
@@ -32,7 +32,7 @@
namespace CEGUI {
GUIElement::GUIElement(int x, int y, int width, int height) :
-_background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) {
+ _background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) {
}
bool GUIElement::setBackground(WORD backgroundReference) {
@@ -45,9 +45,7 @@ bool GUIElement::setBackground(WORD backgroundReference) {
if (!_height && !_width) {
_height = _background->height();
_width = _background->width();
- }
- else
- if (_background->height() != _height || _background->width() != _width) {
+ } else if (_background->height() != _height || _background->width() != _width) {
delete _background;
_background = NULL;
return false;
@@ -74,8 +72,7 @@ bool GUIElement::draw(SDL_Surface *surface) {
_drawn = true;
return true;
- }
- else
+ } else
return false;
}
diff --git a/backends/platform/wince/CEgui/ItemAction.cpp b/backends/platform/wince/CEgui/ItemAction.cpp
index 55805744e6..efbc43ce00 100644
--- a/backends/platform/wince/CEgui/ItemAction.cpp
+++ b/backends/platform/wince/CEgui/ItemAction.cpp
@@ -28,7 +28,7 @@
namespace CEGUI {
ItemAction::ItemAction(WORD reference, GUI::ActionType action) :
-PanelItem(reference) {
+ PanelItem(reference) {
_action = action;
if (!GUI::Actions::Instance()->isEnabled(_action))
_visible = false;
diff --git a/backends/platform/wince/CEgui/ItemSwitch.cpp b/backends/platform/wince/CEgui/ItemSwitch.cpp
index d4648f7556..8eb62bf365 100644
--- a/backends/platform/wince/CEgui/ItemSwitch.cpp
+++ b/backends/platform/wince/CEgui/ItemSwitch.cpp
@@ -40,7 +40,7 @@ void ItemSwitch::init(WORD referenceTrue, WORD referenceFalse) {
}
ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item) :
-PanelItem(referenceTrue) {
+ PanelItem(referenceTrue) {
init(referenceTrue, referenceFalse);
_item = item;
_itemmax = -1;
@@ -49,8 +49,8 @@ PanelItem(referenceTrue) {
}
ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max) :
-PanelItem(referenceTrue) {
- init(referenceTrue, referenceFalse);
+ PanelItem(referenceTrue) {
+ init(referenceTrue, referenceFalse);
_itemmultiple = item;
_itemmax = max;
if (!*item)
diff --git a/backends/platform/wince/CEgui/Panel.cpp b/backends/platform/wince/CEgui/Panel.cpp
index dfdd6526be..576da23029 100644
--- a/backends/platform/wince/CEgui/Panel.cpp
+++ b/backends/platform/wince/CEgui/Panel.cpp
@@ -34,7 +34,7 @@ Panel::Panel(int interleave_first, int interleave) : Toolbar() {
bool Panel::add(const String &name, const PanelItem *item) {
- _itemsMap[name] = (PanelItem*)item;
+ _itemsMap[name] = (PanelItem *)item;
_itemsMap[name]->move(_currentItem, _y + 10);
_itemsMap[name]->setPanel(this);
_currentItem += _interleave;
@@ -47,11 +47,10 @@ bool Panel::draw(SDL_Surface *surface) {
if (!_drawn && _visible) {
GUIElement::draw(surface);
for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) {
- ((GUIElement*)(iterator->_value))->draw(surface);
+ ((GUIElement *)(iterator->_value))->draw(surface);
}
return true;
- }
- else
+ } else
return false;
}
@@ -59,7 +58,7 @@ void Panel::forceRedraw() {
ItemMap::const_iterator iterator;
GUIElement::forceRedraw();
for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator)
- ((GUIElement*)(iterator->_value))->forceRedraw();
+ ((GUIElement *)(iterator->_value))->forceRedraw();
}
bool Panel::action(int x, int y, bool pushed) {
@@ -69,7 +68,7 @@ bool Panel::action(int x, int y, bool pushed) {
return false;
for (iterator = _itemsMap.begin(); !result && iterator != _itemsMap.end(); ++iterator)
- result = ((GUIElement*)(iterator->_value))->action(x, y, pushed);
+ result = ((GUIElement *)(iterator->_value))->action(x, y, pushed);
return result;
}
diff --git a/backends/platform/wince/CEgui/Panel.h b/backends/platform/wince/CEgui/Panel.h
index e6b693360d..1a8a580dba 100644
--- a/backends/platform/wince/CEgui/Panel.h
+++ b/backends/platform/wince/CEgui/Panel.h
@@ -51,7 +51,7 @@ public:
virtual bool action(int x, int y, bool pushed);
private:
- typedef HashMap<String, PanelItem*, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap;
+ typedef HashMap<String, PanelItem *, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap;
ItemMap _itemsMap;
int _interleave;
diff --git a/backends/platform/wince/CEgui/PanelItem.h b/backends/platform/wince/CEgui/PanelItem.h
index 14b62f0f20..9968aa8d5e 100644
--- a/backends/platform/wince/CEgui/PanelItem.h
+++ b/backends/platform/wince/CEgui/PanelItem.h
@@ -36,7 +36,7 @@ namespace CEGUI {
class Panel;
class PanelItem : public GUIElement {
-friend class Panel;
+ friend class Panel;
public:
PanelItem(WORD reference);
virtual ~PanelItem();
diff --git a/backends/platform/wince/CEgui/PanelKeyboard.cpp b/backends/platform/wince/CEgui/PanelKeyboard.cpp
index 5ca125898d..3512b34da3 100644
--- a/backends/platform/wince/CEgui/PanelKeyboard.cpp
+++ b/backends/platform/wince/CEgui/PanelKeyboard.cpp
@@ -30,8 +30,9 @@ namespace CEGUI {
const char KEYBOARD_MAPPING_ALPHA[][14] = { {"abcdefghijklm"}, {"nopqrstuvwxyz"} };
const char KEYBOARD_MAPPING_NUMERIC[][6] = { {"12345"}, {"67890"} };
-const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1,SDLK_ESCAPE}, {224,SDLK_UP}, {32,SDLK_SPACE} },
- { {224,SDLK_LEFT}, {224,SDLK_DOWN}, {224,SDLK_RIGHT} } };
+const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1, SDLK_ESCAPE}, {224, SDLK_UP}, {32, SDLK_SPACE} },
+ { {224, SDLK_LEFT}, {224, SDLK_DOWN}, {224, SDLK_RIGHT} }
+};
PanelKeyboard::PanelKeyboard(WORD reference) : Toolbar() {
setBackground(reference);
@@ -51,21 +52,23 @@ bool PanelKeyboard::action(int x, int y, bool pushed) {
int keyCode = 0;
if (x < 185) {
// Alpha selection
- keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y+20][((x + 10) / 14) - 1];
+ keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y + 20][((x + 10) / 14) - 1];
} else if (x >= 186 && x <= 255) {
// Numeric selection
- keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y+20][((x - 187 + 10) / 14) - 1];
+ keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y + 20][((x - 187 + 10) / 14) - 1];
} else if (x >= 258 && x <= 300) {
// Special keys
- keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][0];
- keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][1];
+ keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y + 20][((x - 259 + 10) / 14) - 1][0];
+ keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y + 20][((x - 259 + 10) / 14) - 1][1];
} else if (x >= 302 && x <= 316) {
- if (y < _y +20) {
+ if (y < _y + 20) {
// Backspace
- keyAscii = VK_BACK; keyCode = keyAscii;
+ keyAscii = VK_BACK;
+ keyCode = keyAscii;
} else {
// Enter
- keyAscii = 13; keyCode = 13;
+ keyAscii = 13;
+ keyCode = 13;
}
}
diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.cpp b/backends/platform/wince/CEgui/SDL_ImageResource.cpp
index 8dad5f0a0c..872b94a442 100644
--- a/backends/platform/wince/CEgui/SDL_ImageResource.cpp
+++ b/backends/platform/wince/CEgui/SDL_ImageResource.cpp
@@ -32,7 +32,7 @@ SDL_ImageResource::SDL_ImageResource() :
_surface(0) {
}
-SDL_Surface* SDL_ImageResource::load(WORD resourceID) {
+SDL_Surface *SDL_ImageResource::load(WORD resourceID) {
HRSRC resource;
HGLOBAL resourceGlobal;
LPVOID resourcePointer;
@@ -62,7 +62,7 @@ SDL_Surface* SDL_ImageResource::load(WORD resourceID) {
return _surface;
}
-SDL_Surface* SDL_ImageResource::get() {
+SDL_Surface *SDL_ImageResource::get() {
return _surface;
}
diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.h b/backends/platform/wince/CEgui/SDL_ImageResource.h
index 5affd5c33c..397ced1434 100644
--- a/backends/platform/wince/CEgui/SDL_ImageResource.h
+++ b/backends/platform/wince/CEgui/SDL_ImageResource.h
@@ -36,8 +36,8 @@ namespace CEGUI {
class SDL_ImageResource {
public:
SDL_ImageResource();
- SDL_Surface* load(WORD resourceID);
- SDL_Surface* get();
+ SDL_Surface *load(WORD resourceID);
+ SDL_Surface *get();
int height();
int width();
virtual ~SDL_ImageResource();
diff --git a/backends/platform/wince/CEgui/ToolbarHandler.cpp b/backends/platform/wince/CEgui/ToolbarHandler.cpp
index 78f69119c3..ed2a72245a 100644
--- a/backends/platform/wince/CEgui/ToolbarHandler.cpp
+++ b/backends/platform/wince/CEgui/ToolbarHandler.cpp
@@ -29,15 +29,15 @@
namespace CEGUI {
ToolbarHandler::ToolbarHandler():
-_current(""), _active(NULL) {
+ _current(""), _active(NULL) {
}
bool ToolbarHandler::add(const String &name, const Toolbar &toolbar) {
- _toolbarMap[name] = (Toolbar*)&toolbar;
+ _toolbarMap[name] = (Toolbar *)&toolbar;
if (!_active) {
- _active = &((Toolbar&)toolbar);
+ _active = &((Toolbar &)toolbar);
_current = name;
}
@@ -53,7 +53,7 @@ bool ToolbarHandler::setActive(const String &name) {
return false;
if (_current == name)
return true;
- _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel)
+ _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel)
_current = name;
_active = _toolbarMap[name];
_active->forceRedraw();
@@ -67,8 +67,7 @@ bool ToolbarHandler::action(int x, int y, bool pushed) {
return _active->action(x / 2, (y - _offset) / 2, pushed);
else
return _active->action(x, y - _offset, pushed);
- }
- else
+ } else
return false;
}
@@ -118,7 +117,7 @@ int ToolbarHandler::getOffset() {
return _offset;
}
-Toolbar* ToolbarHandler::active() {
+Toolbar *ToolbarHandler::active() {
return _active;
}
diff --git a/backends/platform/wince/CEgui/ToolbarHandler.h b/backends/platform/wince/CEgui/ToolbarHandler.h
index e3bf590768..0f794d7d61 100644
--- a/backends/platform/wince/CEgui/ToolbarHandler.h
+++ b/backends/platform/wince/CEgui/ToolbarHandler.h
@@ -57,7 +57,7 @@ public:
virtual ~ToolbarHandler();
private:
- HashMap<String, Toolbar*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap;
+ HashMap<String, Toolbar *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap;
String _current;
Toolbar *_active;
int _offset;
diff --git a/backends/platform/wince/CEkeys/EventsBuffer.cpp b/backends/platform/wince/CEkeys/EventsBuffer.cpp
index c9f4af2304..beea272d2b 100644
--- a/backends/platform/wince/CEkeys/EventsBuffer.cpp
+++ b/backends/platform/wince/CEkeys/EventsBuffer.cpp
@@ -29,55 +29,55 @@
namespace CEKEYS {
- bool EventsBuffer::simulateKey(GUI::Key *key, bool pushed) {
- SDL_Event ev = {0};
-
- if (!key->keycode())
- key->setKey(key->ascii(), key->ascii());
- else if (!key->ascii())
- key->setKey(key->keycode());
-
- ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP);
- ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field
- ev.key.keysym.sym = (SDLKey)key->keycode();
- ev.key.keysym.mod = KMOD_RESERVED;
- return (SDL_PushEvent(&ev) == 0);
- }
-
- bool EventsBuffer::simulateMouseMove(int x, int y) {
- SDL_Event ev = {0};
-
- ev.type = SDL_MOUSEMOTION;
- ev.motion.x = x;
- ev.motion.y = y;
- return (SDL_PushEvent(&ev) == 0);
- }
-
- bool EventsBuffer::simulateMouseLeftClick(int x, int y, bool pushed) {
- SDL_Event ev = {0};
- static bool state = false;
-
- if (pushed == state) return 0;
- state = pushed;
- ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
- ev.button.button = SDL_BUTTON_LEFT;
- ev.button.x = x;
- ev.button.y = y;
- return (SDL_PushEvent(&ev) == 0);
- }
-
- bool EventsBuffer::simulateMouseRightClick(int x, int y, bool pushed) {
- SDL_Event ev = {0};
- static bool state = false;
-
- if (pushed == state) return 0;
- state = pushed;
- ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
- ev.button.button = SDL_BUTTON_RIGHT;
- ev.button.x = x;
- ev.button.y = y;
- return (SDL_PushEvent(&ev) == 0);
- }
+bool EventsBuffer::simulateKey(GUI::Key *key, bool pushed) {
+ SDL_Event ev = {0};
+
+ if (!key->keycode())
+ key->setKey(key->ascii(), key->ascii());
+ else if (!key->ascii())
+ key->setKey(key->keycode());
+
+ ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP);
+ ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field
+ ev.key.keysym.sym = (SDLKey)key->keycode();
+ ev.key.keysym.mod = KMOD_RESERVED;
+ return (SDL_PushEvent(&ev) == 0);
+}
+
+bool EventsBuffer::simulateMouseMove(int x, int y) {
+ SDL_Event ev = {0};
+
+ ev.type = SDL_MOUSEMOTION;
+ ev.motion.x = x;
+ ev.motion.y = y;
+ return (SDL_PushEvent(&ev) == 0);
+}
+
+bool EventsBuffer::simulateMouseLeftClick(int x, int y, bool pushed) {
+ SDL_Event ev = {0};
+ static bool state = false;
+
+ if (pushed == state) return 0;
+ state = pushed;
+ ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
+ ev.button.button = SDL_BUTTON_LEFT;
+ ev.button.x = x;
+ ev.button.y = y;
+ return (SDL_PushEvent(&ev) == 0);
+}
+
+bool EventsBuffer::simulateMouseRightClick(int x, int y, bool pushed) {
+ SDL_Event ev = {0};
+ static bool state = false;
+
+ if (pushed == state) return 0;
+ state = pushed;
+ ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
+ ev.button.button = SDL_BUTTON_RIGHT;
+ ev.button.x = x;
+ ev.button.y = y;
+ return (SDL_PushEvent(&ev) == 0);
+}
}
diff --git a/backends/platform/wince/CEkeys/EventsBuffer.h b/backends/platform/wince/CEkeys/EventsBuffer.h
index 22590db03c..9b766c6ca9 100644
--- a/backends/platform/wince/CEkeys/EventsBuffer.h
+++ b/backends/platform/wince/CEkeys/EventsBuffer.h
@@ -34,14 +34,14 @@
namespace CEKEYS {
- class EventsBuffer {
- public:
- static bool simulateKey(GUI::Key *key, bool pushed);
- static bool simulateMouseMove(int x, int y);
- static bool simulateMouseLeftClick(int x, int y, bool pushed);
- static bool simulateMouseRightClick(int x, int y, bool pushed);
-
- };
+class EventsBuffer {
+public:
+ static bool simulateKey(GUI::Key *key, bool pushed);
+ static bool simulateMouseMove(int x, int y);
+ static bool simulateMouseLeftClick(int x, int y, bool pushed);
+ static bool simulateMouseRightClick(int x, int y, bool pushed);
+
+};
}
#endif
diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile
index 8ad134648b..21bff06f95 100644
--- a/backends/platform/wince/Makefile
+++ b/backends/platform/wince/Makefile
@@ -113,7 +113,7 @@ INCLUDES := -I$(srcdir) -I. -I$(srcdir)/engines -Imissing/gcc -Ilibs/include -Il
CFLAGS :=
ifndef UNOPTIMIZED_BUILD
-CFLAGS += -O3 -march=armv4 -mtune=xscale
+CFLAGS += -O3 -fno-inline-functions -march=armv4 -mtune=xscale
endif
LDFLAGS := -Wl,-Map,scummvm.exe.map -Wl,--stack,65536
diff --git a/backends/platform/wince/missing/io.h b/backends/platform/wince/missing/io.h
index 8c66e9405b..96bc6a9ea1 100644
--- a/backends/platform/wince/missing/io.h
+++ b/backends/platform/wince/missing/io.h
@@ -5,9 +5,9 @@
#define strdup _strdup
#ifndef _FILE_DEFINED
- typedef void FILE;
- #define _FILE_DEFINED
+typedef void FILE;
+#define _FILE_DEFINED
#endif
-FILE* wce_fopen(const char* fname, const char* fmode);
+FILE *wce_fopen(const char *fname, const char *fmode);
#define fopen wce_fopen
diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp
index 92af3e6961..c855247ae1 100644
--- a/backends/platform/wince/missing/missing.cpp
+++ b/backends/platform/wince/missing/missing.cpp
@@ -50,7 +50,7 @@ char *strdup(const char *strSource);
// common missing functions required by both gcc and evc
void *bsearch(const void *key, const void *base, size_t nmemb,
- size_t size, int (*compar)(const void *, const void *)) {
+ size_t size, int (*compar)(const void *, const void *)) {
// Perform binary search
size_t lo = 0;
size_t hi = nmemb;
@@ -63,17 +63,17 @@ void *bsearch(const void *key, const void *base, size_t nmemb,
else if (tmp > 0)
lo = mid + 1;
else
- return (void *)p;
+ return const_cast<void *>(p);
}
return NULL;
}
-static char cwd[MAX_PATH+1] = "";
+static char cwd[MAX_PATH + 1] = "";
EXT_C char *getcwd(char *buffer, int maxlen) {
- TCHAR fileUnc[MAX_PATH+1];
- char* plast;
+ TCHAR fileUnc[MAX_PATH + 1];
+ char *plast;
if (cwd[0] == 0) {
GetModuleFileName(NULL, fileUnc, MAX_PATH);
@@ -94,7 +94,7 @@ EXT_C char *getcwd(char *buffer, int maxlen) {
#undef GetCurrentDirectory
#endif
EXT_C void GetCurrentDirectory(int len, char *buf) {
- getcwd(buf,len);
+ getcwd(buf, len);
}
/*
@@ -103,8 +103,8 @@ fully qualified paths refer to root folder rather
than current folder (concept not implemented in CE).
*/
#undef fopen
-EXT_C FILE *wce_fopen(const char* fname, const char* fmode) {
- char fullname[MAX_PATH+1];
+EXT_C FILE *wce_fopen(const char *fname, const char *fmode) {
+ char fullname[MAX_PATH + 1];
if (!fname || fname[0] == '\0')
return NULL;
@@ -118,8 +118,8 @@ EXT_C FILE *wce_fopen(const char* fname, const char* fmode) {
}
/* Remove file by name */
-int remove(const char* path) {
- TCHAR pathUnc[MAX_PATH+1];
+int remove(const char *path) {
+ TCHAR pathUnc[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH);
return !DeleteFile(pathUnc);
}
@@ -128,15 +128,15 @@ int remove(const char* path) {
/* check out file access permissions */
int _access(const char *path, int mode) {
TCHAR fname[MAX_PATH];
- char fullname[MAX_PATH+1];
+ char fullname[MAX_PATH + 1];
if (path[0] != '\\' && path[0] != '/') {
getcwd(fullname, MAX_PATH);
strcat(fullname, "\\");
strcat(fullname, path);
- MultiByteToWideChar(CP_ACP, 0, fullname, -1, fname, sizeof(fname)/sizeof(TCHAR));
+ MultiByteToWideChar(CP_ACP, 0, fullname, -1, fname, sizeof(fname) / sizeof(TCHAR));
} else
- MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname)/sizeof(TCHAR));
+ MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname) / sizeof(TCHAR));
WIN32_FIND_DATA ffd;
HANDLE h = FindFirstFile(fname, &ffd);
@@ -144,10 +144,10 @@ int _access(const char *path, int mode) {
if (h == INVALID_HANDLE_VALUE) {
// WORKAROUND: WinCE 3.0 doesn't find paths ending in '\'
- if (path[strlen(path)-1] == '\\') {
+ if (path[strlen(path) - 1] == '\\') {
char p2[MAX_PATH];
- strncpy(p2, path, strlen(path)-1);
- p2[strlen(path) - 1]= '\0';
+ strncpy(p2, path, strlen(path) - 1);
+ p2[strlen(path) - 1] = '\0';
return _access(p2, mode);
} else
return -1; //Can't find file
@@ -158,7 +158,7 @@ int _access(const char *path, int mode) {
// hits for files that don't exist. TRIPLE checking for the same fname
// seems to weed out those false positives.
// Exhibited in kyra engine.
- HANDLE h = FindFirstFile(fname, &ffd);
+ h = FindFirstFile(fname, &ffd);
FindClose(h);
if (h == INVALID_HANDLE_VALUE)
return -1; //Can't find file
@@ -170,13 +170,13 @@ int _access(const char *path, int mode) {
return 0; //Always return success if target is directory and exists
}
switch (mode) {
- case 00: //Check existence
- return 0;
- case 06: //Check Read & Write permission
- case 02: //Check Write permission
- return ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? -1 : 0;
- case 04: //Check Read permission
- return 0; //Assume always have read permission
+ case 00: //Check existence
+ return 0;
+ case 06: //Check Read & Write permission
+ case 02: //Check Write permission
+ return ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? -1 : 0;
+ case 04: //Check Read permission
+ return 0; //Assume always have read permission
}
//Bad mode value supplied, return failure
return -1;
@@ -188,7 +188,7 @@ int _access(const char *path, int mode) {
char *strdup(const char *strSource) {
char *buffer;
size_z len = strlen(strSource) + 1;
- buffer = (char*)malloc(len);
+ buffer = (char *)malloc(len);
if (buffer)
memcpy(buffer, strSource, len);
return buffer;
@@ -199,25 +199,25 @@ char *strdup(const char *strSource) {
#ifndef __MINGW32CE__
int islower(int c) {
- return (c>='a' && c<='z');
+ return (c >= 'a' && c <= 'z');
}
int isspace(int c) {
- return (c==' ' || c=='\f' || c=='\n' || c=='\r' || c=='\t' || c=='\v');
+ return (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v');
}
int isalpha(int c) {
- return ((c>='a' && c<='z') || (c>='A' && c<='Z'));
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}
int isalnum(int c) {
- return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'));
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'));
}
int isprint(int c) {
//static const char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~";
//return (isalnum(c) || strchr(punct, c));
- return (32 <= c && c <= 126); // based on BSD manpage
+ return (32 <= c && c <= 126); // based on BSD manpage
}
#endif
diff --git a/backends/platform/wince/missing/time.h b/backends/platform/wince/missing/time.h
index f2bc5e4f89..a0ba6c246e 100644
--- a/backends/platform/wince/missing/time.h
+++ b/backends/platform/wince/missing/time.h
@@ -6,8 +6,7 @@
#include <stdlib.h>
#ifndef __MINGW32CE__
-struct tm
-{
+struct tm {
short tm_year;
short tm_mon;
short tm_mday;
@@ -23,8 +22,8 @@ struct tm
#define EXT_C
#endif
-EXT_C time_t time(time_t* dummy);
-EXT_C struct tm* localtime(time_t* dummy);
+EXT_C time_t time(time_t *dummy);
+EXT_C struct tm *localtime(time_t *dummy);
unsigned int clock();
diff --git a/backends/platform/wince/portdefs.h b/backends/platform/wince/portdefs.h
index cbf2006be2..8ad643946f 100644
--- a/backends/platform/wince/portdefs.h
+++ b/backends/platform/wince/portdefs.h
@@ -34,10 +34,10 @@ int isprint(int c);
int isspace(int c);
char *strrchr(const char *s, int c);
char *strdup(const char *s);
-int _stricmp( const char *string1, const char *string2 );
-int stricmp( const char *string1, const char *string2 );
-void assert( void* expression );
-void assert( int expression );
+int _stricmp(const char *string1, const char *string2);
+int stricmp(const char *string1, const char *string2);
+void assert(void *expression);
+void assert(int expression);
long int strtol(const char *nptr, char **endptr, int base);
char *_strdup(const char *s);
char *strpbrk(const char *s, const char *accept);
@@ -47,20 +47,20 @@ char *strpbrk(const char *s, const char *accept);
#ifdef _WIN32_WCE
#ifndef __GNUC__
- void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *));
- char *getcwd(char *buf, int size);
- typedef int ptrdiff_t;
- void GetCurrentDirectory(int len, char *buf);
- #define INVALID_FILE_ATTRIBUTES 0xffffffff
+void *bsearch(const void *, const void *, size_t, size_t, int (*x)(const void *, const void *));
+char *getcwd(char *buf, int size);
+typedef int ptrdiff_t;
+void GetCurrentDirectory(int len, char *buf);
+#define INVALID_FILE_ATTRIBUTES 0xffffffff
#else
- #include <math.h>
- #undef GetCurrentDirectory
- extern "C" void GetCurrentDirectory(int len, char *buf);
- #define stricmp _stricmp
- #define strnicmp _strnicmp
- #define snprintf _snprintf
- #define strdup _strdup
- #define fopen wce_fopen
+#include <math.h>
+#undef GetCurrentDirectory
+extern "C" void GetCurrentDirectory(int len, char *buf);
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+#define snprintf _snprintf
+#define strdup _strdup
+#define fopen wce_fopen
#endif
#include <windows.h>
@@ -75,12 +75,12 @@ char *strpbrk(const char *s, const char *accept);
//#include <direct.h>
#ifdef __MINGW32CE__
- void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *));
+void *bsearch(const void *, const void *, size_t, size_t, int (*x)(const void *, const void *));
#endif
int remove(const char *path);
int _access(const char *path, int mode);
-void drawError(char*);
+void drawError(char *);
#define vsnprintf _vsnprintf
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index ade90b2dfb..b829686cb0 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -23,6 +23,7 @@
*
*/
+
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
@@ -43,13 +44,12 @@
#include "audio/mixer_intern.h"
#include "audio/fmopl.h"
-#include "backends/timer/default/default-timer.h"
+#include "backends/timer/sdl/sdl-timer.h"
#include "gui/Actions.h"
#include "gui/KeysDialog.h"
#include "gui/message.h"
-#include "backends/platform/wince/resource.h"
#include "backends/platform/wince/CEActionsPocket.h"
#include "backends/platform/wince/CEActionsSmartphone.h"
#include "backends/platform/wince/CEgui/ItemAction.h"
@@ -60,39 +60,22 @@
#include "backends/platform/wince/CEException.h"
#include "backends/platform/wince/CEScaler.h"
-#ifdef USE_VORBIS
-#ifndef USE_TREMOR
-#include <vorbis/vorbisfile.h>
-#else
-#include <tremor/ivorbisfile.h>
-#endif
-#endif
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/mixer/wincesdl/wincesdl-mixer.h"
#ifdef DYNAMIC_MODULES
#include "backends/plugins/win32/win32-provider.h"
#endif
#ifdef __GNUC__
-extern "C" _CRTIMP FILE* __cdecl _wfreopen (const wchar_t*, const wchar_t*, FILE*);
+extern "C" _CRTIMP FILE *__cdecl _wfreopen(const wchar_t *, const wchar_t *, FILE *);
#endif
-#define SAMPLES_PER_SEC_OLD 11025
-#define SAMPLES_PER_SEC_NEW 22050
-
using namespace CEGUI;
// ********************************************************************************************
-// Internal GUI names
-
-#define NAME_MAIN_PANEL "MainPanel"
-#define NAME_PANEL_KEYBOARD "Keyboard"
-#define NAME_ITEM_OPTIONS "Options"
-#define NAME_ITEM_SKIP "Skip"
-#define NAME_ITEM_SOUND "Sound"
-#define NAME_ITEM_ORIENTATION "Orientation"
-#define NAME_ITEM_BINDKEYS "Bindkeys"
-
// stdin/err redirection
#define STDOUT_FNAME "\\scummvm_stdout.txt"
#define STDERR_FNAME "\\scummvm_stderr.txt"
@@ -106,34 +89,6 @@ bool OSystem_WINCE3::_soundMaster = true;
bool _isSmartphone = false;
bool _hasSmartphoneResolution = false;
-// Graphics mode consts
-
-// Low end devices 240x320
-
-static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = {
- {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
- {0, 0, 0}
-};
-
-// High end device 480x640
-
-static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = {
- {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
- {"2x", "2x", GFX_DOUBLESIZE},
-#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :)
- {"2xsai", "2xSAI", GFX_2XSAI},
- {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI},
- {"supereagle", "SuperEagle", GFX_SUPEREAGLE},
-#endif
- {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X},
-#ifndef _MSC_VER
- {"hq2x", "HQ2x", GFX_HQ2X},
- {"tv2x", "TV2x", GFX_TV2X},
-#endif
- {"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
- {0, 0, 0}
-};
-
#define DEFAULT_CONFIG_FILE "scummvm.ini"
// ********************************************************************************************
@@ -144,7 +99,7 @@ bool isSmartphone() {
}
const TCHAR *ASCIItoUnicode(const char *str) {
- static TCHAR ustr[MAX_PATH]; // size good enough
+ static TCHAR ustr[MAX_PATH]; // size good enough
MultiByteToWideChar(CP_ACP, 0, str, strlen(str) + 1, ustr, sizeof(ustr) / sizeof(TCHAR));
return ustr;
@@ -173,7 +128,7 @@ int SDL_main(int argc, char **argv) {
// thanks to joostp and DJWillis
extern void (*__CTOR_LIST__)();
void (**constructor)() = &__CTOR_LIST__;
- constructor++; // First item in list of constructors has special meaning (platform dependent), ignore it.
+ constructor++; // First item in list of constructors has special meaning (platform dependent), ignore it.
while (*constructor) {
(*constructor)();
constructor++;
@@ -238,10 +193,10 @@ int SDL_main(int argc, char **argv) {
res = scummvm_main(argc, argv);
// Free OSystem
- delete (OSystem_WINCE3 *)g_system;
+ delete(OSystem_WINCE3 *)g_system;
#if !defined(DEBUG) && !defined(__GNUC__)
}
- __except (handleException(GetExceptionInformation())) {
+ __except(handleException(GetExceptionInformation())) {
}
#endif
@@ -264,22 +219,22 @@ int console_main(int argc, char *argv[]) {
char *bufp, *appname;
appname = argv[0];
- if ( (bufp=strrchr(argv[0], '\\')) != NULL )
+ if ((bufp = strrchr(argv[0], '\\')) != NULL)
appname = bufp + 1;
- else if ( (bufp=strrchr(argv[0], '/')) != NULL )
+ else if ((bufp = strrchr(argv[0], '/')) != NULL)
appname = bufp + 1;
- if ( (bufp=strrchr(appname, '.')) == NULL )
+ if ((bufp = strrchr(appname, '.')) == NULL)
n = strlen(appname);
else
- n = (bufp-appname);
+ n = (bufp - appname);
bufp = (char *) alloca(n + 1);
strncpy(bufp, appname, n);
bufp[n] = '\0';
appname = bufp;
- if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
+ if (SDL_Init(SDL_INIT_NOPARACHUTE) < 0) {
error("WinMain() error: %d", SDL_GetError());
return(FALSE);
}
@@ -344,31 +299,31 @@ int dynamic_modules_main(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int
int nLen;
if (wcsncmp(szCmdLine, TEXT("\\"), 1)) {
- nLen = wcslen(szCmdLine)+128+1;
- bufp = (wchar_t *) alloca(nLen*2);
- wcscpy (bufp, TEXT("\""));
- GetModuleFileName(NULL, bufp+1, 128-3);
- wcscpy (bufp+wcslen(bufp), TEXT("\" "));
- wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
+ nLen = wcslen(szCmdLine) + 128 + 1;
+ bufp = (wchar_t *) alloca(nLen * 2);
+ wcscpy(bufp, TEXT("\""));
+ GetModuleFileName(NULL, bufp + 1, 128 - 3);
+ wcscpy(bufp + wcslen(bufp), TEXT("\" "));
+ wcsncpy(bufp + wcslen(bufp), szCmdLine, nLen - wcslen(bufp));
} else
bufp = szCmdLine;
- nLen = wcslen(bufp)+1;
+ nLen = wcslen(bufp) + 1;
cmdline = (char *) alloca(nLen);
WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
// Parse command line into argv and argc
argc = ParseCommandLine(cmdline, NULL);
- argv = (char **) alloca((argc+1)*(sizeof *argv));
+ argv = (char **) alloca((argc + 1) * (sizeof * argv));
ParseCommandLine(cmdline, argv);
// fix gdb-emulator combo
while (argc > 1 && !strstr(argv[0], ".exe")) {
OutputDebugString(TEXT("SDL: gdb argv[0] fixup\n"));
- *(argv[1]-1) = ' ';
+ *(argv[1] - 1) = ' ';
int i;
- for (i=1; i<argc; i++)
- argv[i] = argv[i+1];
+ for (i = 1; i < argc; i++)
+ argv[i] = argv[i + 1];
argc--;
}
@@ -380,7 +335,6 @@ int dynamic_modules_main(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int
// ********************************************************************************************
-
// ********************************************************************************************
void pumpMessages() {
@@ -407,47 +361,53 @@ static Uint32 timer_handler_wrapper(Uint32 interval) {
}
void OSystem_WINCE3::initBackend() {
- // Instantiate our own sound mixer
- // mixer init is rerun when a game engine is selected.
- setupMixer();
+
+ assert(!_inited);
+
+ // Create the backend custom managers
+ if (_eventSource == 0)
+ _eventSource = new WINCESdlEventSource();
+
+ if (_mixerManager == 0) {
+ _mixerManager = new WINCESdlMixerManager();
+
+ // Setup and start mixer
+ _mixerManager->init();
+ }
+
+ if (_graphicsManager == 0)
+ _graphicsManager = new WINCESdlGraphicsManager(_eventSource);
+
+ ((WINCESdlEventSource *)_eventSource)->init((WINCESdlGraphicsManager *)_graphicsManager);
// Create the timer. CE SDL does not support multiple timers (SDL_AddTimer).
// We work around this by using the SetTimer function, since we only use
// one timer in scummvm (for the time being)
_timer = _int_timer = new DefaultTimerManager();
- _timerID = NULL; // OSystem_SDL will call removetimer with this, it's ok
+ //_timerID = NULL; // OSystem_SDL will call removetimer with this, it's ok
SDL_SetTimer(10, &timer_handler_wrapper);
// Chain init
OSystem_SDL::initBackend();
- // Query SDL for screen size and init screen dependent stuff
- OSystem_WINCE3::initScreenInfos();
- _isSmartphone = CEDevice::isSmartphone();
- create_toolbar();
- _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone();
- if (_hasSmartphoneResolution)
- _panelVisible = false; // init correctly in smartphones
-
// Initialize global key mapping
GUI::Actions::init();
GUI_Actions::Instance()->initInstanceMain(this);
- if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version
+ if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version
warning("Setting default action mappings");
- GUI_Actions::Instance()->saveMapping(); // write defaults
+ GUI_Actions::Instance()->saveMapping(); // write defaults
}
- loadDeviceConfiguration();
+ // Call parent implementation of this method
+ //OSystem_SDL::initBackend();
+
+ _inited = true;
}
int OSystem_WINCE3::getScreenWidth() {
return _platformScreenWidth;
}
-int OSystem_WINCE3::getScreenHeight() {
- return _platformScreenHeight;
-}
-
void OSystem_WINCE3::initScreenInfos() {
// sdl port ensures that we use correctly full screen
_isOzone = 0;
@@ -457,6 +417,10 @@ void OSystem_WINCE3::initScreenInfos() {
_platformScreenHeight = r[0]->h;
}
+int OSystem_WINCE3::getScreenHeight() {
+ return _platformScreenHeight;
+}
+
bool OSystem_WINCE3::isOzone() {
return _isOzone;
}
@@ -473,496 +437,37 @@ Common::String OSystem_WINCE3::getDefaultConfigFileName() {
OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(),
- _orientationLandscape(0), _newOrientation(0), _panelInitialized(false), _canBeAspectScaled(false),
- _panelVisible(true), _panelStateForced(false), _forceHideMouse(false), _unfilteredkeys(false),
- _freeLook(false), _forcePanelInvisible(false), _toolbarHighDrawn(false), _zoomUp(false), _zoomDown(false),
- _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false), _noDoubleTapRMB(false),
- _saveToolbarState(false), _saveActiveToolbar(NAME_MAIN_PANEL), _rbutton(false), _hasfocus(true),
- _usesEmulatedMouse(false), _mouseBackupOld(NULL), _mouseBackupToolbar(NULL), _mouseBackupDim(0)
-{
- memset(&_mouseCurState, 0, sizeof(_mouseCurState));
- if (_isSmartphone) {
- _mouseCurState.x = 20;
- _mouseCurState.y = 20;
- }
-
+ _forcePanelInvisible(false) {
+ // Initialze File System Factory
+ _fsFactory = new WindowsFilesystemFactory();
_mixer = 0;
- _screen = NULL;
}
-void OSystem_WINCE3::swap_panel_visibility() {
- //if (!_forcePanelInvisible && !_panelStateForced) {
- if (_zoomDown || _zoomUp) return;
-
- if (_panelVisible) {
- if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD)
- _panelVisible = !_panelVisible;
- else
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
- } else {
- _toolbarHandler.setActive(NAME_MAIN_PANEL);
- _panelVisible = !_panelVisible;
- }
- _toolbarHandler.setVisible(_panelVisible);
- _toolbarHighDrawn = false;
-
- if (_videoMode.screenHeight > 240)
- addDirtyRect(0, 400, 640, 80);
- else
- addDirtyRect(0, 200, 320, 40);
-
- if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
- internUpdateScreen();
- else {
- update_scalers();
- hotswapGFXMode();
- }
- //}
+OSystem_WINCE3::~OSystem_WINCE3() {
+ delete _fsFactory;
+ delete _mixer;
}
-void OSystem_WINCE3::swap_panel() {
- _toolbarHighDrawn = false;
- //if (!_panelStateForced) {
- if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
- _toolbarHandler.setActive(NAME_MAIN_PANEL);
- else
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
-
- if (_videoMode.screenHeight > 240)
- addDirtyRect(0, 400, 640, 80);
- else
- addDirtyRect(0, 200, 320, 40);
-
- _toolbarHandler.setVisible(true);
- if (!_panelVisible) {
- _panelVisible = true;
- update_scalers();
- hotswapGFXMode();
- }
- //}
-}
-
-void OSystem_WINCE3::swap_smartphone_keyboard() {
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
- _panelVisible = !_panelVisible;
- _toolbarHandler.setVisible(_panelVisible);
- if (_videoMode.screenHeight > 240)
- addDirtyRect(0, 0, 640, 80);
- else
- addDirtyRect(0, 0, 320, 40);
- internUpdateScreen();
-}
-
-void OSystem_WINCE3::smartphone_rotate_display() {
- _orientationLandscape = _newOrientation = _orientationLandscape == 1 ? 2 : 1;
- ConfMan.setInt("landscape", _orientationLandscape);
- ConfMan.flushToDisk();
- hotswapGFXMode();
+FilesystemFactory *OSystem_WINCE3::getFilesystemFactory() {
+ return _fsFactory;
}
void OSystem_WINCE3::swap_sound_master() {
_soundMaster = !_soundMaster;
- if (_toolbarHandler.activeName() == NAME_MAIN_PANEL)
- _toolbarHandler.forceRedraw(); // redraw sound icon
-}
-
-void OSystem_WINCE3::add_right_click(bool pushed) {
- int x, y;
- retrieve_mouse_location(x, y);
- EventsBuffer::simulateMouseRightClick(x, y, pushed);
-}
-
-void OSystem_WINCE3::swap_mouse_visibility() {
- _forceHideMouse = !_forceHideMouse;
- if (_forceHideMouse)
- undrawMouse();
-}
-
-void OSystem_WINCE3::swap_freeLook() {
- _freeLook = !_freeLook;
-}
-void OSystem_WINCE3::swap_zoom_up() {
- if (_zoomUp) {
- // restore visibility
- _toolbarHandler.setVisible(_saveToolbarZoom);
- // restore scaler
- _scaleFactorYd = 2;
- _scalerProc = DownscaleAllByHalf;
- _zoomUp = false;
- _zoomDown = false;
- } else {
- // only active if running on a PocketPC
- if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
- return;
- if (_scalerProc == DownscaleAllByHalf) {
- _saveToolbarZoom = _toolbarHandler.visible();
- _toolbarHandler.setVisible(false);
- // set zoom scaler
- _scaleFactorYd = 1;
- _scalerProc = DownscaleHorizByHalf;
- }
+ //WINCESdlGraphicsManager _graphicsManager
- _zoomDown = false;
- _zoomUp = true;
- }
- // redraw whole screen
- addDirtyRect(0, 0, 640, 480);
- internUpdateScreen();
+ if (((WINCESdlGraphicsManager *)_graphicsManager)->_toolbarHandler.activeName() == NAME_MAIN_PANEL)
+ ((WINCESdlGraphicsManager *)_graphicsManager)->_toolbarHandler.forceRedraw(); // redraw sound icon
}
-void OSystem_WINCE3::swap_zoom_down() {
- if (_zoomDown) {
- // restore visibility
- _toolbarHandler.setVisible(_saveToolbarZoom);
- // restore scaler
- _scaleFactorYd = 2;
- _scalerProc = DownscaleAllByHalf;
- _zoomDown = false;
- _zoomUp = false;
- } else {
- // only active if running on a PocketPC
- if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
- return;
- if (_scalerProc == DownscaleAllByHalf) {
- _saveToolbarZoom = _toolbarHandler.visible();
- _toolbarHandler.setVisible(false);
- // set zoom scaler
- _scaleFactorYd = 1;
- _scalerProc = DownscaleHorizByHalf;
- }
-
- _zoomUp = false;
- _zoomDown = true;
- }
- // redraw whole screen
- addDirtyRect(0, 0, 640, 480);
- internUpdateScreen();
-}
-
-// Smartphone actions
-void OSystem_WINCE3::initZones() {
- int i;
-
- _currentZone = 0;
- for (i = 0; i < TOTAL_ZONES; i++) {
- _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)) * _scaleFactorXm / _scaleFactorXd;
- _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)) * _scaleFactorYm / _scaleFactorYd;
- }
-}
-
-void OSystem_WINCE3::loadDeviceConfigurationElement(String element, int &value, int defaultValue) {
- value = ConfMan.getInt(element, ConfMan.kApplicationDomain);
- if (!value) {
- value = defaultValue;
- ConfMan.setInt(element, value, ConfMan.kApplicationDomain);
- }
-}
-
-void OSystem_WINCE3::loadDeviceConfiguration() {
- loadDeviceConfigurationElement("repeatTrigger", _keyRepeatTrigger, 200);
- loadDeviceConfigurationElement("repeatX", _repeatX, 4);
- loadDeviceConfigurationElement("repeatY", _repeatY, 4);
- loadDeviceConfigurationElement("stepX1", _stepX1, 2);
- loadDeviceConfigurationElement("stepX2", _stepX2, 10);
- loadDeviceConfigurationElement("stepX3", _stepX3, 40);
- loadDeviceConfigurationElement("stepY1", _stepY1, 2);
- loadDeviceConfigurationElement("stepY2", _stepY2, 10);
- loadDeviceConfigurationElement("stepY3", _stepY3, 20);
- ConfMan.flushToDisk();
-}
-
-void OSystem_WINCE3::add_left_click(bool pushed) {
- int x, y;
- retrieve_mouse_location(x, y);
- EventsBuffer::simulateMouseLeftClick(x, y, pushed);
-}
-
-void OSystem_WINCE3::move_cursor_up() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatY)
- y -= _stepY3;
- else if (_keyRepeat)
- y -= _stepY2;
- else
- y -= _stepY1;
-
- if (y < 0)
- y = 0;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::move_cursor_down() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatY)
- y += _stepY3;
- else if (_keyRepeat)
- y += _stepY2;
- else
- y += _stepY1;
-
- if (y > _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd)
- y = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::move_cursor_left() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatX)
- x -= _stepX3;
- else if (_keyRepeat)
- x -= _stepX2;
- else
- x -= _stepX1;
-
- if (x < 0)
- x = 0;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::move_cursor_right() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatX)
- x += _stepX3;
- else if (_keyRepeat)
- x += _stepX2;
- else
- x += _stepX1;
-
- if (x > _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd)
- x = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::switch_zone() {
- int x, y;
- int i;
- retrieve_mouse_location(x, y);
-
- for (i = 0; i < TOTAL_ZONES; i++)
- if (x >= _zones[i].x && y >= _zones[i].y &&
- x <= _zones[i].x + _zones[i].width && y <= _zones[i].y + _zones[i].height) {
- _mouseXZone[i] = x;
- _mouseYZone[i] = y;
- break;
- }
- _currentZone = i + 1;
- if (_currentZone >= TOTAL_ZONES)
- _currentZone = 0;
-
- EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]);
-}
-
-void OSystem_WINCE3::create_toolbar() {
- PanelKeyboard *keyboard;
-
- // Add the keyboard
- keyboard = new PanelKeyboard(PANEL_KEYBOARD);
- _toolbarHandler.add(NAME_PANEL_KEYBOARD, *keyboard);
- _toolbarHandler.setVisible(false);
-}
-
-void OSystem_WINCE3::setupMixer() {
- SDL_AudioSpec desired;
- int thread_priority;
-
- uint32 sampleRate = compute_sample_rate();
- if (sampleRate == 0)
- warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work");
- else if (_mixer && _mixer->getOutputRate() == sampleRate) {
- debug(1, "Skipping sound mixer re-init: samplerate is good");
- return;
- }
-
- memset(&desired, 0, sizeof(desired));
- desired.freq = sampleRate;
- desired.format = AUDIO_S16SYS;
- desired.channels = 2;
- desired.samples = 128;
- desired.callback = private_sound_proc;
- desired.userdata = this;
-
- // Create the mixer instance
- if (_mixer == 0)
- _mixer = new Audio::MixerImpl(this, sampleRate);
-
- // Add sound thread priority
- if (!ConfMan.hasKey("sound_thread_priority"))
- thread_priority = THREAD_PRIORITY_NORMAL;
- else
- thread_priority = ConfMan.getInt("sound_thread_priority");
-
- desired.thread_priority = thread_priority;
-
- SDL_CloseAudio();
- if (SDL_OpenAudio(&desired, NULL) != 0) {
- warning("Could not open audio device: %s", SDL_GetError());
- _mixer->setReady(false);
-
- } else {
- debug(1, "Sound opened OK, mixing at %d Hz", sampleRate);
-
- // Re-create mixer to match the output rate
- int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
- int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
- int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
- int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
- delete _mixer;
- _mixer = new Audio::MixerImpl(this, sampleRate);
- _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1);
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4);
- _mixer->setReady(true);
- SDL_PauseAudio(0);
- }
-}
-
-void OSystem_WINCE3::private_sound_proc(void *param, byte *buf, int len) {
- OSystem_WINCE3 *this_ = (OSystem_WINCE3 *)param;
- assert(this_);
-
- if (this_->_mixer)
- this_->_mixer->mixCallback(buf, len);
- if (!_soundMaster)
- memset(buf, 0, len);
-}
-
-#ifdef USE_VORBIS
-bool OSystem_WINCE3::checkOggHighSampleRate() {
- char trackFile[255];
- FILE *testFile;
- OggVorbis_File *test_ov_file = new OggVorbis_File;
-
- // FIXME: The following sprintf assumes that "path" is always
- // terminated by a path separator. This is *not* true in general.
- // This code really should check for the path separator, or even
- // better, use the FSNode API.
- sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str());
- // Check if we have an OGG audio track
- testFile = fopen(trackFile, "rb");
- if (testFile) {
- if (!ov_open(testFile, test_ov_file, NULL, 0)) {
- bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050);
- ov_clear(test_ov_file);
- delete test_ov_file;
- return highSampleRate;
- }
- }
-
- // Do not test for OGG samples - too big and too slow anyway :)
-
- delete test_ov_file;
- return false;
-}
-#endif
-
-uint32 OSystem_WINCE3::compute_sample_rate() {
- uint32 sampleRate;
-
- // Force at least medium quality FM synthesis for FOTAQ
- Common::String gameid(ConfMan.get("gameid"));
- if (gameid == "queen") {
- if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) ||
- (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) {
- ConfMan.setBool("FM_medium_quality", true);
- ConfMan.flushToDisk();
- }
- }
- // See if the output frequency is forced by the game
- if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi")
- sampleRate = SAMPLES_PER_SEC_NEW;
- else {
- if (ConfMan.hasKey("high_sample_rate") && ConfMan.getBool("high_sample_rate"))
- sampleRate = SAMPLES_PER_SEC_NEW;
- else
- sampleRate = SAMPLES_PER_SEC_OLD;
- }
-
-#ifdef USE_VORBIS
- // Modify the sample rate on the fly if OGG is involved
- if (sampleRate == SAMPLES_PER_SEC_OLD)
- if (checkOggHighSampleRate())
- sampleRate = SAMPLES_PER_SEC_NEW;
-#endif
-
- return sampleRate;
-}
void OSystem_WINCE3::engineInit() {
check_mappings(); // called here to initialize virtual keys handling
//update_game_settings();
// finalize mixer init
- setupMixer();
-}
-
-const OSystem::GraphicsMode *OSystem_WINCE3::getSupportedGraphicsModes() const {
- if (CEDevice::hasWideResolution())
- return s_supportedGraphicsModesHigh;
- else
- return s_supportedGraphicsModesLow;
-}
-
-bool OSystem_WINCE3::hasFeature(Feature f) {
- return (f == kFeatureVirtualKeyboard);
-}
-
-void OSystem_WINCE3::setFeatureState(Feature f, bool enable) {
- switch (f) {
- case kFeatureFullscreenMode:
- return;
-
- case kFeatureVirtualKeyboard:
- if (_hasSmartphoneResolution)
- return;
- _toolbarHighDrawn = false;
- if (enable) {
- _panelStateForced = true;
- if (!_toolbarHandler.visible()) swap_panel_visibility();
- //_saveToolbarState = _toolbarHandler.visible();
- _saveActiveToolbar = _toolbarHandler.activeName();
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
- _toolbarHandler.setVisible(true);
- } else
- if (_panelStateForced) {
- _panelStateForced = false;
- _toolbarHandler.setActive(_saveActiveToolbar);
- //_toolbarHandler.setVisible(_saveToolbarState);
- }
- return;
-
- case kFeatureDisableKeyFiltering:
- if (_hasSmartphoneResolution)
- _unfilteredkeys = enable;
- return;
-
- default:
- OSystem_SDL::setFeatureState(f, enable);
- }
-}
-
-bool OSystem_WINCE3::getFeatureState(Feature f) {
- switch (f) {
- case kFeatureFullscreenMode:
- return false;
- case kFeatureVirtualKeyboard:
- return (_panelStateForced);
- default:
- return OSystem_SDL::getFeatureState(f);
- }
+ _mixerManager->init();
}
void OSystem_WINCE3::check_mappings() {
@@ -974,7 +479,7 @@ void OSystem_WINCE3::check_mappings() {
return;
GUI_Actions::Instance()->initInstanceGame();
- instance = (CEActionsPocket*)GUI_Actions::Instance();
+ instance = (CEActionsPocket *)GUI_Actions::Instance();
// Some games need to map the right click button, signal it here if it wasn't done
if (instance->needsRightClickMapping()) {
@@ -1014,1472 +519,39 @@ void OSystem_WINCE3::check_mappings() {
// Extra warning for Zak Mc Kracken
if (strncmp(gameid.c_str(), "zak", 3) == 0 &&
- !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) {
+ !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) {
GUI::MessageDialog alert(_("Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"));
alert.runModal();
}
}
-void OSystem_WINCE3::update_game_settings() {
- Common::String gameid(ConfMan.get("gameid"));
-
- // Finish panel initialization
- if (!_panelInitialized && !gameid.empty()) {
- Panel *panel;
- _panelInitialized = true;
- // Add the main panel
- panel = new Panel(0, 32);
- panel->setBackground(IMAGE_PANEL);
- // Save
- panel->add(NAME_ITEM_OPTIONS, new ItemAction(ITEM_OPTIONS, POCKET_ACTION_SAVE));
- // Skip
- panel->add(NAME_ITEM_SKIP, new ItemAction(ITEM_SKIP, POCKET_ACTION_SKIP));
- // sound
- panel->add(NAME_ITEM_SOUND, new ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &_soundMaster));
- // bind keys
- panel->add(NAME_ITEM_BINDKEYS, new ItemAction(ITEM_BINDKEYS, POCKET_ACTION_BINDKEYS));
- // portrait/landscape - screen dependent
- // FIXME : will still display the portrait/landscape icon when using a scaler (but will be disabled)
- if (ConfMan.hasKey("landscape")) {
- if (ConfMan.get("landscape")[0] > 57) {
- _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
- //ConfMan.removeKey("landscape", "");
- ConfMan.setInt("landscape", _orientationLandscape);
- } else
- _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
- } else {
- _newOrientation = _orientationLandscape = 0;
- }
- panel->add(NAME_ITEM_ORIENTATION, new ItemSwitch(ITEM_VIEW_LANDSCAPE, ITEM_VIEW_PORTRAIT, &_newOrientation, 2));
- _toolbarHandler.add(NAME_MAIN_PANEL, *panel);
- _toolbarHandler.setActive(NAME_MAIN_PANEL);
- _toolbarHandler.setVisible(true);
-
- if (_videoMode.mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) {
- setGraphicsMode(GFX_NORMAL);
- hotswapGFXMode();
- }
-
- if (_hasSmartphoneResolution)
- panel->setVisible(false);
-
- _saveToolbarState = true;
- }
-
- if (ConfMan.hasKey("no_doubletap_rightclick"))
- _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick");
-}
-
-void OSystem_WINCE3::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
- if (_hasSmartphoneResolution && h == 240)
- h = 200; // mainly for the launcher
-
- if (_isSmartphone && !ConfMan.hasKey("landscape")) {
- ConfMan.setInt("landscape", 1);
- ConfMan.flushToDisk();
- }
-
- _canBeAspectScaled = false;
- if (w == 320 && h == 200 && !_hasSmartphoneResolution) {
- _canBeAspectScaled = true;
- h = 240; // use the extra 40 pixels height for the toolbar
- }
-
- if (h == 400) // touche engine fixup
- h += 80;
-
- if (!_hasSmartphoneResolution) {
- if (h == 240)
- _toolbarHandler.setOffset(200);
- else
- _toolbarHandler.setOffset(400);
- } else {
- if (h == 240)
- _toolbarHandler.setOffset(200);
- else // 176x220
- _toolbarHandler.setOffset(0);
- }
-
- if (w != (uint) _videoMode.screenWidth || h != (uint) _videoMode.screenHeight)
- _scalersChanged = false;
-
- _videoMode.overlayWidth = w;
- _videoMode.overlayHeight = h;
-
- OSystem_SDL::initSize(w, h, format);
-
- if (_scalersChanged) {
- unloadGFXMode();
- loadGFXMode();
- _scalersChanged = false;
- }
-
- update_game_settings();
-}
-
-
-int OSystem_WINCE3::getDefaultGraphicsMode() const {
- return GFX_NORMAL;
-}
-
void OSystem_WINCE3::setGraphicsModeIntern() {
// Scalers have been pre-selected for the desired mode.
// No further tuning required.
}
-bool OSystem_WINCE3::update_scalers() {
- _videoMode.aspectRatioCorrection = false;
-
- if (CEDevice::hasPocketPCResolution()) {
- if (_videoMode.mode != GFX_NORMAL)
- return false;
-
- if ((!_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth))
- || CEDevice::hasSquareQVGAResolution() ) {
- if (getScreenWidth() != 320) {
- _scaleFactorXm = 3;
- _scaleFactorXd = 4;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = DownscaleHorizByThreeQuarters;
- } else {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = Normal1x;
- }
- } else if ( _orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
- if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 6;
- _scaleFactorYd = 5;
- _scalerProc = Normal1xAspect;
- _videoMode.aspectRatioCorrection = true;
- } else {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = Normal1x;
- }
- } else if (_videoMode.screenWidth == 640 && !(isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
- _scaleFactorXm = 1;
- _scaleFactorXd = 2;
- _scaleFactorYm = 1;
- _scaleFactorYd = 2;
- _scalerProc = DownscaleAllByHalf;
- } else if (_videoMode.screenWidth == 640 && (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = Normal1x;
- }
-
- return true;
- } else if (CEDevice::hasWideResolution()) {
-#ifdef USE_ARM_SCALER_ASM
- if ( _videoMode.mode == GFX_DOUBLESIZE && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth) ) {
- if ( !_panelVisible && !_overlayVisible && _canBeAspectScaled ) {
- _scaleFactorXm = 2;
- _scaleFactorXd = 1;
- _scaleFactorYm = 12;
- _scaleFactorYd = 5;
- _scalerProc = Normal2xAspect;
- _videoMode.aspectRatioCorrection = true;
- } else if ( (_panelVisible || _overlayVisible) && _canBeAspectScaled ) {
- _scaleFactorXm = 2;
- _scaleFactorXd = 1;
- _scaleFactorYm = 2;
- _scaleFactorYd = 1;
- _scalerProc = Normal2x;
- }
- return true;
- }
-#endif
- } else if (CEDevice::hasSmartphoneResolution()) {
- if (_videoMode.mode != GFX_NORMAL)
- return false;
-
- if (_videoMode.screenWidth > 320)
- error("Game resolution not supported on Smartphone");
-#ifdef ARM
- _scaleFactorXm = 11;
- _scaleFactorXd = 16;
-#else
- _scaleFactorXm = 2;
- _scaleFactorXd = 3;
-#endif
- _scaleFactorYm = 7;
- _scaleFactorYd = 8;
- _scalerProc = SmartphoneLandscape;
- initZones();
- return true;
- }
-
- return false;
-}
-
-bool OSystem_WINCE3::setGraphicsMode(int mode) {
-
- Common::StackLock lock(_graphicsMutex);
- int oldScaleFactorXm = _scaleFactorXm;
- int oldScaleFactorXd = _scaleFactorXd;
- int oldScaleFactorYm = _scaleFactorYm;
- int oldScaleFactorYd = _scaleFactorYd;
-
- _scaleFactorXm = -1;
- _scaleFactorXd = -1;
- _scaleFactorYm = -1;
- _scaleFactorYd = -1;
-
- if (ConfMan.hasKey("landscape"))
- if (ConfMan.get("landscape")[0] > 57) {
- _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
- ConfMan.setInt("landscape", _orientationLandscape);
- } else
- _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
- else
- _newOrientation = _orientationLandscape = 0;
-
- if (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640) && mode)
- _scaleFactorXm = -1;
-
- if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape)
- _videoMode.mode = GFX_NORMAL;
- else
- _videoMode.mode = mode;
-
- if (_scaleFactorXm < 0) {
- /* Standard scalers, from the SDL backend */
- switch (_videoMode.mode) {
- case GFX_NORMAL:
- _videoMode.scaleFactor = 1;
- _scalerProc = Normal1x;
- break;
- case GFX_DOUBLESIZE:
- _videoMode.scaleFactor = 2;
- _scalerProc = Normal2x;
- break;
- case GFX_TRIPLESIZE:
- _videoMode.scaleFactor = 3;
- _scalerProc = Normal3x;
- break;
- case GFX_2XSAI:
- _videoMode.scaleFactor = 2;
- _scalerProc = _2xSaI;
- break;
- case GFX_SUPER2XSAI:
- _videoMode.scaleFactor = 2;
- _scalerProc = Super2xSaI;
- break;
- case GFX_SUPEREAGLE:
- _videoMode.scaleFactor = 2;
- _scalerProc = SuperEagle;
- break;
- case GFX_ADVMAME2X:
- _videoMode.scaleFactor = 2;
- _scalerProc = AdvMame2x;
- break;
- case GFX_ADVMAME3X:
- _videoMode.scaleFactor = 3;
- _scalerProc = AdvMame3x;
- break;
-#ifdef USE_HQ_SCALERS
- case GFX_HQ2X:
- _videoMode.scaleFactor = 2;
- _scalerProc = HQ2x;
- break;
- case GFX_HQ3X:
- _videoMode.scaleFactor = 3;
- _scalerProc = HQ3x;
- break;
-#endif
- case GFX_TV2X:
- _videoMode.scaleFactor = 2;
- _scalerProc = TV2x;
- break;
- case GFX_DOTMATRIX:
- _videoMode.scaleFactor = 2;
- _scalerProc = DotMatrix;
- break;
-
- default:
- error("unknown gfx mode %d", mode);
- }
- }
-
- // Check if the scaler can be accepted, if not get back to normal scaler
- if (_videoMode.scaleFactor && ((_videoMode.scaleFactor * _videoMode.screenWidth > getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenWidth > getScreenHeight())
- || (_videoMode.scaleFactor * _videoMode.screenHeight > getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenHeight > getScreenHeight()))) {
- _videoMode.scaleFactor = 1;
- _scalerProc = Normal1x;
- }
-
- // Common scaler system was used
- if (_scaleFactorXm < 0) {
- _scaleFactorXm = _videoMode.scaleFactor;
- _scaleFactorXd = 1;
- _scaleFactorYm = _videoMode.scaleFactor;
- _scaleFactorYd = 1;
- }
-
- _forceFull = true;
-
- if (oldScaleFactorXm != _scaleFactorXm ||
- oldScaleFactorXd != _scaleFactorXd ||
- oldScaleFactorYm != _scaleFactorYm ||
- oldScaleFactorYd != _scaleFactorYd) {
- _scalersChanged = true;
- }
- else
- _scalersChanged = false;
-
-
- return true;
-
-}
-
-bool OSystem_WINCE3::loadGFXMode() {
- int displayWidth;
- int displayHeight;
- unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE;
-
- _videoMode.fullscreen = true; // forced
- _forceFull = true;
-
- _tmpscreen = NULL;
-
- // Recompute scalers if necessary
- update_scalers();
-
- // Create the surface that contains the 8 bit game data
- _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
- if (_screen == NULL)
- error("_screen failed (%s)", SDL_GetError());
-
- // Create the surface that contains the scaled graphics in 16 bit mode
- // Always use full screen mode to have a "clean screen"
- if (!_videoMode.aspectRatioCorrection) {
- displayWidth = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
- displayHeight = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
- } else {
- displayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- displayHeight = _videoMode.screenHeight* _videoMode.scaleFactor;
- }
-
- switch (_orientationLandscape) {
- case 1:
- flags |= SDL_LANDSCVIDEO;
- break;
- case 2:
- flags |= SDL_INVLNDVIDEO;
- break;
- default:
- flags |= SDL_PORTRTVIDEO;
- }
- _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags);
-
- if (_hwscreen == NULL) {
- warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
- quit();
- }
-
- // see what orientation sdl finally accepted
- if (_hwscreen->flags & SDL_PORTRTVIDEO)
- _orientationLandscape = _newOrientation = 0;
- else if (_hwscreen->flags & SDL_LANDSCVIDEO)
- _orientationLandscape = _newOrientation = 1;
- else
- _orientationLandscape = _newOrientation = 2;
-
- // Create the surface used for the graphics in 16 bit before scaling, and also the overlay
- // Distinguish 555 and 565 mode
- if (_hwscreen->format->Rmask == 0x7C00)
- InitScalers(555);
- else
- InitScalers(565);
- _overlayFormat.bytesPerPixel = _hwscreen->format->BytesPerPixel;
- _overlayFormat.rLoss = _hwscreen->format->Rloss;
- _overlayFormat.gLoss = _hwscreen->format->Gloss;
- _overlayFormat.bLoss = _hwscreen->format->Bloss;
- _overlayFormat.aLoss = _hwscreen->format->Aloss;
- _overlayFormat.rShift = _hwscreen->format->Rshift;
- _overlayFormat.gShift = _hwscreen->format->Gshift;
- _overlayFormat.bShift = _hwscreen->format->Bshift;
- _overlayFormat.aShift = _hwscreen->format->Ashift;
-
- // Need some extra bytes around when using 2xSaI
- _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
-
- if (_tmpscreen == NULL)
- error("_tmpscreen creation failed (%s)", SDL_GetError());
-
- // Overlay
- if (CEDevice::hasDesktopResolution()) {
- _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0);
- if (_overlayscreen == NULL)
- error("_overlayscreen failed (%s)", SDL_GetError());
- _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0);
- if (_tmpscreen2 == NULL)
- error("_tmpscreen2 failed (%s)", SDL_GetError());
- } else {
- _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, 0, 0, 0, 0);
- if (_overlayscreen == NULL)
- error("_overlayscreen failed (%s)", SDL_GetError());
- _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, 0, 0, 0, 0);
- if (_tmpscreen2 == NULL)
- error("_tmpscreen2 failed (%s)", SDL_GetError());
- }
-
- // Toolbar
- _toolbarHighDrawn = false;
- uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16)); // *not* leaking memory here
- _toolbarLow = SDL_CreateRGBSurfaceFrom(toolbar_screen, 320, 40, 16, 320 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
-
- if (_toolbarLow == NULL)
- error("_toolbarLow failed (%s)", SDL_GetError());
-
- if (_videoMode.screenHeight > 240) {
- uint16 *toolbar_screen = (uint16 *)calloc(640 * 80, sizeof(uint16));
- _toolbarHigh = SDL_CreateRGBSurfaceFrom(toolbar_screen, 640, 80, 16, 640 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
-
- if (_toolbarHigh == NULL)
- error("_toolbarHigh failed (%s)", SDL_GetError());
- } else
- _toolbarHigh = NULL;
-
-
- // keyboard cursor control, some other better place for it?
- _km.x_max = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd - 1;
- _km.y_max = _videoMode.screenHeight * _scaleFactorXm / _scaleFactorXd - 1;
- _km.delay_time = 25;
- _km.last_time = 0;
-
- return true;
-}
-
-void OSystem_WINCE3::unloadGFXMode() {
- if (_screen) {
- SDL_FreeSurface(_screen);
- _screen = NULL;
- }
-
- if (_hwscreen) {
- SDL_FreeSurface(_hwscreen);
- _hwscreen = NULL;
- }
-
- if (_tmpscreen) {
- SDL_FreeSurface(_tmpscreen);
- _tmpscreen = NULL;
- }
-}
-
-bool OSystem_WINCE3::hotswapGFXMode() {
- if (!_screen)
- return false;
-
- // Keep around the old _screen & _tmpscreen so we can restore the screen data
- // after the mode switch. (also for the overlay)
- SDL_Surface *old_screen = _screen;
- SDL_Surface *old_tmpscreen = _tmpscreen;
- SDL_Surface *old_overlayscreen = _overlayscreen;
- SDL_Surface *old_tmpscreen2 = _tmpscreen2;
-
- // Release the HW screen surface
- SDL_FreeSurface(_hwscreen);
-
- // Release toolbars
- free(_toolbarLow->pixels);
- SDL_FreeSurface(_toolbarLow);
- if (_toolbarHigh) {
- free(_toolbarHigh->pixels);
- SDL_FreeSurface(_toolbarHigh);
- }
-
- // Setup the new GFX mode
- if (!loadGFXMode()) {
- unloadGFXMode();
-
- _screen = old_screen;
- _overlayscreen = old_overlayscreen;
-
- return false;
- }
-
- // reset palette
- SDL_SetColors(_screen, _currentPalette, 0, 256);
-
- // Restore old screen content
- SDL_BlitSurface(old_screen, NULL, _screen, NULL);
- SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
- if (_overlayVisible) {
- SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
- SDL_BlitSurface(old_tmpscreen2, NULL, _tmpscreen2, NULL);
- }
-
- // Free the old surfaces
- SDL_FreeSurface(old_screen);
- SDL_FreeSurface(old_tmpscreen);
- SDL_FreeSurface(old_overlayscreen);
- SDL_FreeSurface(old_tmpscreen2);
-
- // Blit everything back to the screen
- _toolbarHighDrawn = false;
- internUpdateScreen();
-
- // Make sure that a Common::EVENT_SCREEN_CHANGED gets sent later -> FIXME this crashes when no game has been loaded.
-// _modeChanged = true;
-
- return true;
-}
-
-void OSystem_WINCE3::internUpdateScreen() {
- SDL_Surface *srcSurf, *origSurf;
- static bool old_overlayVisible = false;
- int numRectsOut = 0;
- int16 routx, routy, routw, routh, stretch, shakestretch;
-
- assert(_hwscreen != NULL);
-
- // bail if the application is minimized, be nice to OS
- if (!_hasfocus) {
- Sleep(20);
- return;
- }
-
- // If the shake position changed, fill the dirty area with blackness
- if (_currentShakePos != _newShakePos) {
- SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd, _newShakePos * _scaleFactorYm / _scaleFactorYd};
- if (_videoMode.aspectRatioCorrection)
- blackrect.h = real2Aspect(blackrect.h - 1) + 1;
- SDL_FillRect(_hwscreen, &blackrect, 0);
- _currentShakePos = _newShakePos;
- _forceFull = true;
- }
-
- // Make sure the mouse is drawn, if it should be drawn.
- drawMouse();
-
- // Check whether the palette was changed in the meantime and update the
- // screen surface accordingly.
- if (_paletteDirtyEnd != 0) {
- SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart);
- _paletteDirtyEnd = 0;
- _forceFull = true;
- }
+void OSystem_WINCE3::initSDL() {
+ // Check if SDL has not been initialized
+ if (!_initedSDL) {
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ if (ConfMan.hasKey("disable_sdl_parachute"))
+ sdlFlags |= SDL_INIT_NOPARACHUTE;
- if (!_overlayVisible) {
- origSurf = _screen;
- srcSurf = _tmpscreen;
- } else {
- origSurf = _overlayscreen;
- srcSurf = _tmpscreen2;
- }
-
- if (old_overlayVisible != _overlayVisible) {
- old_overlayVisible = _overlayVisible;
- update_scalers();
- }
-
- // Force a full redraw if requested
- if (_forceFull) {
- _numDirtyRects = 1;
-
- _dirtyRectList[0].x = 0;
- if (!_zoomDown)
- _dirtyRectList[0].y = 0;
- else
- _dirtyRectList[0].y = _videoMode.screenHeight / 2;
- _dirtyRectList[0].w = _videoMode.screenWidth;
- if (!_zoomUp && !_zoomDown)
- _dirtyRectList[0].h = _videoMode.screenHeight;
- else
- _dirtyRectList[0].h = _videoMode.screenHeight / 2;
-
- _toolbarHandler.forceRedraw();
- }
-
- // Only draw anything if necessary
- if (_numDirtyRects > 0) {
-
- SDL_Rect *r, *rout;
- SDL_Rect dst;
- uint32 srcPitch, dstPitch;
- SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects;
- bool toolbarVisible = _toolbarHandler.visible();
- int toolbarOffset = _toolbarHandler.getOffset();
-
- for (r = _dirtyRectList; r != last_rect; ++r) {
- dst = *r;
- dst.x++; // Shift rect by one since 2xSai needs to access the data around
- dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
- // NOTE: This is also known as BLACK MAGIC, copied from the sdl backend
- if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
- error("SDL_BlitSurface failed: %s", SDL_GetError());
+ if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) {
+ SDL_VideoInit("windib", 0);
+ sdlFlags ^= SDL_INIT_VIDEO;
}
- SDL_LockSurface(srcSurf);
- SDL_LockSurface(_hwscreen);
-
- srcPitch = srcSurf->pitch;
- dstPitch = _hwscreen->pitch;
-
- for (r = _dirtyRectList, rout = _dirtyRectOut; r != last_rect; ++r) {
-
- // always clamp to enclosing, downsampled-grid-aligned rect in the downscaled image
- if (_scaleFactorXd != 1) {
- stretch = r->x % _scaleFactorXd;
- r->x -= stretch;
- r->w += stretch;
- r->w = (r->x + r->w + _scaleFactorXd - 1) / _scaleFactorXd * _scaleFactorXd - r->x;
- }
- if (_scaleFactorYd != 1) {
- stretch = r->y % _scaleFactorYd;
- r->y -= stretch;
- r->h += stretch;
- r->h = (r->y + r->h + _scaleFactorYd - 1) / _scaleFactorYd * _scaleFactorYd - r->y;
- }
-
- // transform
- shakestretch = _currentShakePos * _scaleFactorYm / _scaleFactorYd;
- routx = r->x * _scaleFactorXm / _scaleFactorXd; // locate position in scaled screen
- routy = r->y * _scaleFactorYm / _scaleFactorYd + shakestretch; // adjust for shake offset
- routw = r->w * _scaleFactorXm / _scaleFactorXd;
- routh = r->h * _scaleFactorYm / _scaleFactorYd - shakestretch;
-
- // clipping destination rectangle inside device screen (more strict, also more tricky but more stable)
- // note that all current scalers do not make dst rect exceed left/right, unless chosen badly (FIXME)
- if (_zoomDown) routy -= 240; // adjust for zoom position
- if (routy + routh < 0) continue;
- if (routy < 0) {
- routh += routy;
- r->y -= routy * _scaleFactorYd / _scaleFactorYm;
- routy = 0;
- r->h = routh * _scaleFactorYd / _scaleFactorYm;
- }
- if (_orientationLandscape) {
- if (routy > _platformScreenWidth) continue;
- if (routy + routh > _platformScreenWidth) {
- routh = _platformScreenWidth - routy;
- r->h = routh * _scaleFactorYd / _scaleFactorYm;
- }
- } else {
- if (routy > _platformScreenHeight) continue;
- if (routy + routh > _platformScreenHeight) {
- routh = _platformScreenHeight - routy;
- r->h = routh * _scaleFactorYd / _scaleFactorYm;
- }
- }
-
- // check if the toolbar is overwritten
- if (toolbarVisible && r->y + r->h >= toolbarOffset)
- _toolbarHandler.forceRedraw();
+ // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
+ if (SDL_Init(sdlFlags) == -1)
+ error("Could not initialize SDL: %s", SDL_GetError());
- // blit it (with added voodoo from the sdl backend, shifting the source rect again)
- _scalerProc( (byte *)srcSurf->pixels + (r->x * 2 + 2)+ (r->y + 1) * srcPitch, srcPitch,
- (byte *)_hwscreen->pixels + routx * 2 + routy * dstPitch, dstPitch,
- r->w, r->h - _currentShakePos);
+ // Enable unicode support if possible
+ SDL_EnableUNICODE(1);
- // add this rect to output
- rout->x = routx; rout->y = routy - shakestretch;
- rout->w = routw; rout->h = routh + shakestretch;
- numRectsOut++;
- rout++;
-
- }
- SDL_UnlockSurface(srcSurf);
- SDL_UnlockSurface(_hwscreen);
- }
- // Add the toolbar if needed
- SDL_Rect toolbar_rect[1];
- if (_panelVisible && _toolbarHandler.draw(_toolbarLow, &toolbar_rect[0])) {
- // It can be drawn, scale it
- uint32 srcPitch, dstPitch;
- SDL_Surface *toolbarSurface;
- ScalerProc *toolbarScaler;
-
- if (_videoMode.screenHeight > 240) {
- if (!_toolbarHighDrawn) {
- // Resize the toolbar
- SDL_LockSurface(_toolbarLow);
- SDL_LockSurface(_toolbarHigh);
- Normal2x((byte*)_toolbarLow->pixels, _toolbarLow->pitch, (byte*)_toolbarHigh->pixels, _toolbarHigh->pitch, toolbar_rect[0].w, toolbar_rect[0].h);
- SDL_UnlockSurface(_toolbarHigh);
- SDL_UnlockSurface(_toolbarLow);
- _toolbarHighDrawn = true;
- }
- toolbar_rect[0].w *= 2;
- toolbar_rect[0].h *= 2;
- toolbarSurface = _toolbarHigh;
- }
- else
- toolbarSurface = _toolbarLow;
-
- drawToolbarMouse(toolbarSurface, true); // draw toolbar mouse if applicable
-
- // Apply the appropriate scaler
- SDL_LockSurface(toolbarSurface);
- SDL_LockSurface(_hwscreen);
- srcPitch = toolbarSurface->pitch;
- dstPitch = _hwscreen->pitch;
-
- toolbarScaler = _scalerProc;
- if (_videoMode.scaleFactor == 2)
- toolbarScaler = Normal2x;
- else if (_videoMode.scaleFactor == 3)
- toolbarScaler = Normal3x;
- toolbarScaler((byte *)toolbarSurface->pixels, srcPitch,
- (byte *)_hwscreen->pixels + (_toolbarHandler.getOffset() * _scaleFactorYm / _scaleFactorYd * dstPitch),
- dstPitch, toolbar_rect[0].w, toolbar_rect[0].h);
- SDL_UnlockSurface(toolbarSurface);
- SDL_UnlockSurface(_hwscreen);
-
- // And blit it
- toolbar_rect[0].y = _toolbarHandler.getOffset();
- toolbar_rect[0].x = toolbar_rect[0].x * _scaleFactorXm / _scaleFactorXd;
- toolbar_rect[0].y = toolbar_rect[0].y * _scaleFactorYm / _scaleFactorYd;
- toolbar_rect[0].w = toolbar_rect[0].w * _scaleFactorXm / _scaleFactorXd;
- toolbar_rect[0].h = toolbar_rect[0].h * _scaleFactorYm / _scaleFactorYd;
-
- SDL_UpdateRects(_hwscreen, 1, toolbar_rect);
-
- drawToolbarMouse(toolbarSurface, false); // undraw toolbar mouse
- }
-
- // Finally, blit all our changes to the screen
- if (numRectsOut > 0)
- SDL_UpdateRects(_hwscreen, numRectsOut, _dirtyRectOut);
-
- _numDirtyRects = 0;
- _forceFull = false;
-}
-
-Graphics::Surface *OSystem_WINCE3::lockScreen() {
- // Make sure mouse pointer is not painted over the playfield at the time of locking
- undrawMouse();
- return OSystem_SDL::lockScreen();
-}
-
-void OSystem_WINCE3::unlockScreen() {
- OSystem_SDL::unlockScreen();
-}
-
-bool OSystem_WINCE3::saveScreenshot(const char *filename) {
- assert(_hwscreen != NULL);
-
- Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
- SDL_SaveBMP(_hwscreen, filename);
- return true;
-}
-
-void OSystem_WINCE3::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
- assert (_transactionMode == kTransactionNone);
-
- if (_overlayscreen == NULL)
- return;
-
- // Clip the coordinates
- if (x < 0) {
- w += x;
- buf -= x;
- x = 0;
- }
-
- if (y < 0) {
- h += y; buf -= y * pitch;
- y = 0;
+ _initedSDL = true;
}
-
- if (w > _videoMode.overlayWidth - x) {
- w = _videoMode.overlayWidth - x;
- }
-
- if (h > _videoMode.overlayHeight - y) {
- h = _videoMode.overlayHeight - y;
- }
-
- if (w <= 0 || h <= 0)
- return;
-
- // Mark the modified region as dirty
- addDirtyRect(x, y, w, h);
-
- undrawMouse();
-
- if (SDL_LockSurface(_overlayscreen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
- do {
- memcpy(dst, buf, w * 2);
- dst += _overlayscreen->pitch;
- buf += pitch;
- } while (--h);
-
- SDL_UnlockSurface(_overlayscreen);
-}
-
-void OSystem_WINCE3::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
- assert (_transactionMode == kTransactionNone);
- assert(src);
-
- if (_screen == NULL)
- return;
-
- Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
-
- /* Clip the coordinates */
- if (x < 0) {
- w += x;
- src -= x;
- x = 0;
- }
-
- if (y < 0) {
- h += y;
- src -= y * pitch;
- y = 0;
- }
-
- if (w > _videoMode.screenWidth - x) {
- w = _videoMode.screenWidth - x;
- }
-
- if (h > _videoMode.screenHeight - y) {
- h = _videoMode.screenHeight - y;
- }
-
- if (w <= 0 || h <= 0)
- return;
-
- addDirtyRect(x, y, w, h);
-
- undrawMouse();
-
- // Try to lock the screen surface
- if (SDL_LockSurface(_screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
-
- if (_videoMode.screenWidth == pitch && pitch == w) {
- memcpy(dst, src, h*w);
- } else {
- do {
- memcpy(dst, src, w);
- src += pitch;
- dst += _videoMode.screenWidth;
- } while (--h);
- }
-
- // Unlock the screen surface
- SDL_UnlockSurface(_screen);
-}
-
-void OSystem_WINCE3::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
-
- undrawMouse();
- if (w == 0 || h == 0)
- return;
-
- _mouseCurState.w = w;
- _mouseCurState.h = h;
-
- _mouseHotspotX = hotspot_x;
- _mouseHotspotY = hotspot_y;
-
- _mouseKeyColor = keycolor;
-
- free(_mouseData);
-
- _mouseData = (byte *) malloc(w * h);
- memcpy(_mouseData, buf, w * h);
-
- if (w > _mouseBackupDim || h > _mouseBackupDim) {
- // mouse has been undrawn, adjust sprite backup area
- free(_mouseBackupOld);
- free(_mouseBackupToolbar);
- uint16 tmp = (w > h) ? w : h;
- _mouseBackupOld = (byte *) malloc(tmp * tmp * 2); // can hold 8bpp (playfield) or 16bpp (overlay) data
- _mouseBackupToolbar = (uint16 *) malloc(tmp * tmp * 2); // 16 bpp
- _mouseBackupDim = tmp;
- }
-}
-
-void OSystem_WINCE3::setMousePos(int x, int y) {
- if (x != _mouseCurState.x || y != _mouseCurState.y) {
- undrawMouse();
- _mouseCurState.x = x;
- _mouseCurState.y = y;
- updateScreen();
- }
-}
-
-
-void OSystem_WINCE3::internDrawMouse() {
- if (!_mouseNeedsRedraw || !_mouseVisible || !_mouseData)
- return;
-
- int x = _mouseCurState.x - _mouseHotspotX;
- int y = _mouseCurState.y - _mouseHotspotY;
- int w = _mouseCurState.w;
- int h = _mouseCurState.h;
- byte color;
- const byte *src = _mouseData; // Image representing the mouse
- int width;
-
- // clip the mouse rect, and adjust the src pointer accordingly
- if (x < 0) {
- w += x;
- src -= x;
- x = 0;
- }
- if (y < 0) {
- h += y;
- src -= y * _mouseCurState.w;
- y = 0;
- }
-
- if (w > _videoMode.screenWidth - x)
- w = _videoMode.screenWidth - x;
- if (h > _videoMode.screenHeight - y)
- h = _videoMode.screenHeight - y;
-
- // Quick check to see if anything has to be drawn at all
- if (w <= 0 || h <= 0)
- return;
-
- // Draw the mouse cursor; backup the covered area in "bak"
- if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- // Mark as dirty
- addDirtyRect(x, y, w, h);
-
- if (!_overlayVisible) {
- byte *bak = _mouseBackupOld; // Surface used to backup the area obscured by the mouse
- byte *dst; // Surface we are drawing into
-
- dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
- while (h > 0) {
- width = w;
- while (width > 0) {
- *bak++ = *dst;
- color = *src++;
- if (color != _mouseKeyColor) // transparent, don't draw
- *dst = color;
- dst++;
- width--;
- }
- src += _mouseCurState.w - w;
- bak += _mouseBackupDim - w;
- dst += _videoMode.screenWidth - w;
- h--;
- }
-
- } else {
- uint16 *bak = (uint16 *)_mouseBackupOld; // Surface used to backup the area obscured by the mouse
- byte *dst; // Surface we are drawing into
-
- dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2;
- while (h > 0) {
- width = w;
- while (width > 0) {
- *bak++ = *(uint16 *)dst;
- color = *src++;
- if (color != 0xFF) // 0xFF = transparent, don't draw
- *(uint16 *)dst = SDL_MapRGB(_overlayscreen->format, _currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
- dst += 2;
- width--;
- }
- src += _mouseCurState.w - w;
- bak += _mouseBackupDim - w;
- dst += _overlayscreen->pitch - w * 2;
- h--;
- }
- }
-
- SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
-
- // Finally, set the flag to indicate the mouse has been drawn
- _mouseNeedsRedraw = false;
-}
-
-void OSystem_WINCE3::undrawMouse() {
- assert (_transactionMode == kTransactionNone);
-
- if (_mouseNeedsRedraw)
- return;
-
- int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
- int old_mouse_y = _mouseCurState.y - _mouseHotspotY;
- int old_mouse_w = _mouseCurState.w;
- int old_mouse_h = _mouseCurState.h;
-
- // clip the mouse rect, and adjust the src pointer accordingly
- if (old_mouse_x < 0) {
- old_mouse_w += old_mouse_x;
- old_mouse_x = 0;
- }
- if (old_mouse_y < 0) {
- old_mouse_h += old_mouse_y;
- old_mouse_y = 0;
- }
-
- if (old_mouse_w > _videoMode.screenWidth - old_mouse_x)
- old_mouse_w = _videoMode.screenWidth - old_mouse_x;
- if (old_mouse_h > _videoMode.screenHeight - old_mouse_y)
- old_mouse_h = _videoMode.screenHeight - old_mouse_y;
-
- // Quick check to see if anything has to be drawn at all
- if (old_mouse_w <= 0 || old_mouse_h <= 0)
- return;
-
-
- if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- int y;
- if (!_overlayVisible) {
- byte *dst, *bak = _mouseBackupOld;
-
- // No need to do clipping here, since drawMouse() did that already
- dst = (byte *)_screen->pixels + old_mouse_y * _videoMode.screenWidth + old_mouse_x;
- for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _videoMode.screenWidth)
- memcpy(dst, bak, old_mouse_w);
- } else {
- byte *dst;
- uint16 *bak = (uint16 *)_mouseBackupOld;
-
- // No need to do clipping here, since drawMouse() did that already
- dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2;
- for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _overlayscreen->pitch)
- memcpy(dst, bak, old_mouse_w << 1);
- }
-
- addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
-
- SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
-
- _mouseNeedsRedraw = true;
-}
-
-bool OSystem_WINCE3::showMouse(bool visible) {
- if (_mouseVisible == visible)
- return visible;
-
- if (visible == false)
- undrawMouse();
-
- bool last = _mouseVisible;
- _mouseVisible = visible;
- _mouseNeedsRedraw = true;
-
- return last;
-}
-
-void OSystem_WINCE3::drawToolbarMouse(SDL_Surface *surf, bool draw) {
-
- if (!_mouseData || !_usesEmulatedMouse)
- return;
-
- int x = _mouseCurState.x - _mouseHotspotX;
- int y = _mouseCurState.y - _mouseHotspotY - _toolbarHandler.getOffset();
- int w = _mouseCurState.w;
- int h = _mouseCurState.h;
- byte color;
- const byte *src = _mouseData;
- int width;
-
- // clip
- if (x < 0) {
- w += x;
- src -= x;
- x = 0;
- }
- if (y < 0) {
- h += y;
- src -= y * _mouseCurState.w;
- y = 0;
- }
- if (w > surf->w - x)
- w = surf->w - x;
- if (h > surf->h - y)
- h = surf->h - y;
- if (w <= 0 || h <= 0)
- return;
-
- if (SDL_LockSurface(surf) == -1)
- error("SDL_LockSurface failed at internDrawToolbarMouse: %s", SDL_GetError());
-
- uint16 *bak = _mouseBackupToolbar; // toolbar surfaces are 16bpp
- uint16 *dst;
- dst = (uint16 *)surf->pixels + y * surf->w + x;
-
- if (draw) { // blit it
- while (h > 0) {
- width = w;
- while (width > 0) {
- *bak++ = *dst;
- color = *src++;
- if (color != _mouseKeyColor) // transparent color
- *dst = 0xFFFF;
- dst++;
- width--;
- }
- src += _mouseCurState.w - w;
- bak += _mouseBackupDim - w;
- dst += surf->w - w;
- h--;
- }
- } else { // restore bg
- for (y = 0; y < h; ++y, bak += _mouseBackupDim, dst += surf->w)
- memcpy(dst, bak, w << 1);
- }
-
- SDL_UnlockSurface(surf);
-}
-
-void OSystem_WINCE3::blitCursor() {
-}
-
-void OSystem_WINCE3::showOverlay() {
- assert (_transactionMode == kTransactionNone);
-
- if (_overlayVisible)
- return;
-
- undrawMouse();
- _overlayVisible = true;
- update_scalers();
- clearOverlay();
-}
-
-void OSystem_WINCE3::hideOverlay() {
- assert (_transactionMode == kTransactionNone);
-
- if (!_overlayVisible)
- return;
-
- undrawMouse();
- _overlayVisible = false;
- clearOverlay();
- _forceFull = true;
-}
-
-void OSystem_WINCE3::drawMouse() {
- if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset() && !_usesEmulatedMouse) && !_forceHideMouse)
- internDrawMouse();
-}
-
-void OSystem_WINCE3::fillMouseEvent(Common::Event &event, int x, int y) {
- event.mouse.x = x;
- event.mouse.y = y;
-
- // Update the "keyboard mouse" coords
- _km.x = event.mouse.x;
- _km.y = event.mouse.y;
-
- // Adjust for the screen scaling
- if (_zoomDown)
- event.mouse.y += 240;
-
- event.mouse.x = event.mouse.x * _scaleFactorXd / _scaleFactorXm;
- event.mouse.y = event.mouse.y * _scaleFactorYd / _scaleFactorYm;
-}
-
-void OSystem_WINCE3::retrieve_mouse_location(int &x, int &y) {
- x = _mouseCurState.x;
- y = _mouseCurState.y;
-
- x = x * _scaleFactorXm / _scaleFactorXd;
- y = y * _scaleFactorYm / _scaleFactorYd;
-
- if (_zoomDown)
- y -= 240;
-}
-
-void OSystem_WINCE3::warpMouse(int x, int y) {
- if (_mouseCurState.x != x || _mouseCurState.y != y) {
- SDL_WarpMouse(x * _scaleFactorXm / _scaleFactorXd, y * _scaleFactorYm / _scaleFactorYd);
-
- // SDL_WarpMouse() generates a mouse movement event, so
- // set_mouse_pos() would be called eventually. However, the
- // cannon script in CoMI calls this function twice each time
- // the cannon is reloaded. Unless we update the mouse position
- // immediately the second call is ignored, causing the cannon
- // to change its aim.
-
- setMousePos(x, y);
- }
-}
-
-void OSystem_WINCE3::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
-
- if (_forceFull || _paletteDirtyEnd)
- return;
-
- OSystem_SDL::addDirtyRect(x, y, w, h, false);
-}
-
-static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) {
- if (GUI::Actions::Instance()->mappingActive())
- return key;
-
- if (unfilter) {
- switch (key) {
- case SDLK_ESCAPE:
- return SDLK_BACKSPACE;
- case SDLK_F8:
- return SDLK_ASTERISK;
- case SDLK_F9:
- return SDLK_HASH;
- default:
- return key;
- }
- }
-
- if (key >= SDLK_KP0 && key <= SDLK_KP9) {
- return key - SDLK_KP0 + '0';
- } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
- return key;
- } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
- return 0;
- }
- return key;
-}
-
-bool OSystem_WINCE3::pollEvent(Common::Event &event) {
- SDL_Event ev;
- ev.type = SDL_NOEVENT;
- DWORD currentTime;
- bool keyEvent = false;
- int deltaX, deltaY;
-
- memset(&event, 0, sizeof(Common::Event));
-
- handleKbdMouse();
-
- // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED
- if (_modeChanged) {
- _modeChanged = false;
- event.type = Common::EVENT_SCREEN_CHANGED;
- _screenChangeCount++;
- return true;
- }
-
- CEDevice::wakeUp();
-
- currentTime = GetTickCount();
-
- while (SDL_PollEvent(&ev)) {
- switch (ev.type) {
- case SDL_KEYDOWN:
- debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
- // KMOD_RESERVED is used if the key has been injected by an external buffer
- if (ev.key.keysym.mod != KMOD_RESERVED && !_unfilteredkeys) {
- keyEvent = true;
- _lastKeyPressed = ev.key.keysym.sym;
- _keyRepeatTime = currentTime;
- _keyRepeat = 0;
-
- if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true))
- return true;
- }
-
- if (GUI_Actions::Instance()->mappingActive())
- event.kbd.flags = 0xFF;
- else if (ev.key.keysym.sym == SDLK_PAUSE) {
- _lastKeyPressed = 0;
- event.type = Common::EVENT_PREDICTIVE_DIALOG;
- return true;
- } event.type = Common::EVENT_KEYDOWN;
- if (!_unfilteredkeys)
- event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
- else
- event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
- event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
-
- if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
- event.kbd.ascii ^= 0x20;
- event.kbd.flags = Common::KBD_SHIFT;
- }
-
- return true;
-
- case SDL_KEYUP:
- debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
- // KMOD_RESERVED is used if the key has been injected by an external buffer
- if (ev.key.keysym.mod != KMOD_RESERVED && !_unfilteredkeys) {
- keyEvent = true;
- _lastKeyPressed = 0;
-
- if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false))
- return true;
- }
-
- if (GUI_Actions::Instance()->mappingActive())
- event.kbd.flags = 0xFF;
- else if (ev.key.keysym.sym == SDLK_PAUSE) {
- _lastKeyPressed = 0;
- return false; // chew up the show agi dialog key up event
- }
-
- event.type = Common::EVENT_KEYUP;
- if (!_unfilteredkeys)
- event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
- else
- event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
- event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
-
- if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
- event.kbd.ascii ^= 0x20;
- event.kbd.flags = Common::KBD_SHIFT;
- }
-
- return true;
-
- case SDL_MOUSEMOTION:
- event.type = Common::EVENT_MOUSEMOVE;
- fillMouseEvent(event, ev.motion.x, ev.motion.y);
- setMousePos(event.mouse.x, event.mouse.y);
- return true;
-
- case SDL_MOUSEBUTTONDOWN:
- if (ev.button.button == SDL_BUTTON_LEFT)
- event.type = Common::EVENT_LBUTTONDOWN;
- else if (ev.button.button == SDL_BUTTON_RIGHT)
- event.type = Common::EVENT_RBUTTONDOWN;
- else
- break;
- fillMouseEvent(event, ev.button.x, ev.button.y);
-
-
- if (event.mouse.x > _tapX)
- deltaX = event.mouse.x - _tapX;
- else
- deltaX = _tapX - event.mouse.x;
- if (event.mouse.y > _tapY)
- deltaY = event.mouse.y - _tapY;
- else
- deltaY = _tapY - event.mouse.y;
- _closeClick = (deltaX <= 5 && deltaY <= 5);
-
- if (!_isSmartphone) {
- // handle double-taps
- if (_tapTime) { // second tap
- if (_closeClick && (GetTickCount() - _tapTime < 1000)) {
- if (event.mouse.y <= 20 && _panelInitialized) { // top of screen (show panel)
- swap_panel_visibility();
- } else if (!_noDoubleTapRMB) { // right click
- event.type = Common::EVENT_RBUTTONDOWN;
- _rbutton = true;
- }
- }
- _tapTime = 0;
- } else {
- _tapTime = GetTickCount();
- _tapX = event.mouse.x;
- _tapY = event.mouse.y;
- }
- }
-
- if (_freeLook && !_closeClick) {
- _rbutton = false;
- _tapTime = 0;
- _tapX = event.mouse.x;
- _tapY = event.mouse.y;
- event.type = Common::EVENT_MOUSEMOVE;
- setMousePos(event.mouse.x, event.mouse.y);
- }
-
-
- if (_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) {
- if (!_toolbarHandler.drawn()) {
- _toolbarHighDrawn = false;
- internUpdateScreen();
- }
- if (_newOrientation != _orientationLandscape){
- _orientationLandscape = _newOrientation;
- _toolbarHighDrawn = false;
- ConfMan.setInt("landscape", _orientationLandscape);
- ConfMan.flushToDisk();
- hotswapGFXMode();
- }
- return false;
- }
-
- return true;
-
- case SDL_MOUSEBUTTONUP:
- if (ev.button.button == SDL_BUTTON_LEFT)
- event.type = Common::EVENT_LBUTTONUP;
- else if (ev.button.button == SDL_BUTTON_RIGHT)
- event.type = Common::EVENT_RBUTTONUP;
- else
- break;
-
- if (_rbutton) {
- event.type = Common::EVENT_RBUTTONUP;
- _rbutton = false;
- }
-
- fillMouseEvent(event, ev.button.x, ev.button.y);
-
- if (_freeLook && !_closeClick) {
- _tapX = event.mouse.x;
- _tapY = event.mouse.y;
- event.type = Common::EVENT_MOUSEMOVE;
- setMousePos(event.mouse.x, event.mouse.y);
- }
-
- if (_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) {
- if (!_toolbarHandler.drawn()) {
- _toolbarHighDrawn = false;
- internUpdateScreen();
- }
- return false;
-
- }
- return true;
-
- case SDL_VIDEOEXPOSE:
- _forceFull = true;
- break;
-
- case SDL_QUIT:
- event.type = Common::EVENT_QUIT;
- return true;
-
- case SDL_ACTIVEEVENT:
- if (ev.active.state & SDL_APPMOUSEFOCUS)
- debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost");
- if (ev.active.state & SDL_APPINPUTFOCUS)
- debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost");
- if (ev.active.state & SDL_APPACTIVE)
- debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost");
- if (ev.active.state & SDL_APPINPUTFOCUS) {
- _hasfocus = ev.active.gain;
- SDL_PauseAudio(!_hasfocus);
- _forceFull |= _hasfocus;
- }
- break;
- }
- }
-
- // Simulate repeated key for backend
- if (!keyEvent && _lastKeyPressed && currentTime > _keyRepeatTime + _keyRepeatTrigger) {
- _keyRepeatTime = currentTime;
- _keyRepeat++;
- GUI_Actions::Instance()->performMapped(_lastKeyPressed, true);
- }
-
- return false;
}
void OSystem_WINCE3::quit() {
@@ -2497,19 +569,14 @@ void OSystem_WINCE3::getTimeAndDate(TimeDate &t) const {
SYSTEMTIME systime;
GetLocalTime(&systime);
- t.tm_year = systime.wYear - 1900;
- t.tm_mon = systime.wMonth - 1;
- t.tm_mday = systime.wDay;
- t.tm_hour = systime.wHour;
- t.tm_min = systime.wMinute;
- t.tm_sec = systime.wSecond;
+ t.tm_year = systime.wYear - 1900;
+ t.tm_mon = systime.wMonth - 1;
+ t.tm_mday = systime.wDay;
+ t.tm_hour = systime.wHour;
+ t.tm_min = systime.wMinute;
+ t.tm_sec = systime.wSecond;
}
int OSystem_WINCE3::_platformScreenWidth;
int OSystem_WINCE3::_platformScreenHeight;
bool OSystem_WINCE3::_isOzone;
-OSystem_WINCE3::zoneDesc OSystem_WINCE3::_zones[TOTAL_ZONES] = {
- { 0, 0, 320, 145 },
- { 0, 145, 150, 55 },
- { 150, 145, 170, 55 }
-};
diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h
index 6cc6e538e1..d7ede8ca81 100644
--- a/backends/platform/wince/wince-sdl.h
+++ b/backends/platform/wince/wince-sdl.h
@@ -35,7 +35,10 @@
#include "backends/platform/wince/CEkeys/CEKeys.h"
#include "backends/platform/wince/CEDevice.h"
-#define TOTAL_ZONES 3
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/timer/default/default-timer.h"
+#include "backends/fs/windows/windows-fs-factory.h"
// defines used for implementing the raw frame buffer access method (2003+)
#define GETRAWFRAMEBUFFER 0x00020001
@@ -46,202 +49,45 @@
class OSystem_WINCE3 : public OSystem_SDL {
public:
OSystem_WINCE3();
-
- // Update the dirty areas of the screen
- void internUpdateScreen();
+ virtual ~OSystem_WINCE3();
void setGraphicsModeIntern();
- void initSize(uint w, uint h, const Graphics::PixelFormat *format);
void initBackend();
- // Overloaded from SDL backend (toolbar handling)
- bool pollEvent(Common::Event &event);
- // Overloaded from SDL backend (toolbar handling)
- void drawMouse();
- // Overloaded from SDL backend (mouse and new scaler handling)
- void fillMouseEvent(Common::Event &event, int x, int y);
- // Overloaded from SDL backend (new scaler handling)
- void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false);
- // Overloaded from SDL backend (new scaler handling)
- void warpMouse(int x, int y);
// Overloaded from SDL backend
void quit();
- // Overloaded from SDL backend (master volume and sample rate subtleties)
- void setupMixer();
// Overloaded from OSystem
void engineInit();
void getTimeAndDate(TimeDate &t) const;
virtual Common::String getDefaultConfigFileName();
+ virtual FilesystemFactory *getFilesystemFactory();
-
- // Overloaded from SDL_Common (FIXME)
- void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend
- void undrawMouse();
- void blitCursor();
- bool showMouse(bool visible);
- void setMousePos(int x, int y);
- void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)
- void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
- void showOverlay();
- void hideOverlay();
- Graphics::Surface *lockScreen();
- void unlockScreen();
-
- // GUI and action stuff
- void swap_panel_visibility();
- void swap_panel();
void swap_sound_master();
- void add_right_click(bool pushed);
- void swap_mouse_visibility();
- void swap_freeLook();
- void swap_zoom_up();
- void swap_zoom_down();
- void swap_smartphone_keyboard();
-
-//#ifdef WIN32_PLATFORM_WFSP
- // Smartphone actions
-
- void initZones();
- void loadDeviceConfigurationElement(String element, int &value, int defaultValue);
- void loadDeviceConfiguration();
- void add_left_click(bool pushed);
- void move_cursor_up();
- void move_cursor_down();
- void move_cursor_left();
- void move_cursor_right();
- void switch_zone();
- void smartphone_rotate_display();
-//#endif
static int getScreenWidth();
static int getScreenHeight();
static void initScreenInfos();
static bool isOzone();
-protected:
- bool loadGFXMode();
- void unloadGFXMode();
- bool hotswapGFXMode();
- bool saveScreenshot(const char *filename);
-
+ static bool _soundMaster; // turn off sound after all calculations
+ // static since needed by the SDL callback
- const GraphicsMode *getSupportedGraphicsModes() const;
- bool setGraphicsMode(int mode);
- //int getGraphicsMode() const;
- int getDefaultGraphicsMode() const;
-
- bool hasFeature(Feature f);
- void setFeatureState(Feature f, bool enable);
- bool getFeatureState(Feature f);
-
- void internDrawMouse();
- void drawToolbarMouse(SDL_Surface *surf, bool draw);
+protected:
+ void initSDL();
+ Audio::MixerImpl *_mixer;
+ DefaultTimerManager *_timer;
+ FilesystemFactory *_fsFactory;
private:
-
-#ifdef USE_VORBIS
- bool checkOggHighSampleRate();
-#endif
-
- static void private_sound_proc(void *param, byte *buf, int len);
-
- bool update_scalers();
- void create_toolbar();
- void update_game_settings();
void check_mappings();
- uint32 compute_sample_rate();
-
- void retrieve_mouse_location(int &x, int &y);
-
- CEGUI::ToolbarHandler _toolbarHandler;
- SDL_Surface *_toolbarLow; // toolbar 320x40
- SDL_Surface *_toolbarHigh; // toolbar 640x80
- bool _toolbarHighDrawn; // cache toolbar 640x80
-
- bool _freeLook; // freeLook mode (do not send mouse button events)
-
- bool _forceHideMouse; // force invisible mouse cursor
-
- bool _forcePanelInvisible; // force panel visibility for some cases
- bool _panelVisible; // panel visibility
- bool _panelStateForced; // panel visibility forced by external call
-
- bool _panelInitialized; // only initialize the toolbar once
-
- bool _unfilteredkeys; // discard key mapping temporarily (agi pred. dialog)
- static bool _soundMaster; // turn off sound after all calculations
- // static since needed by the SDL callback
- int _orientationLandscape; // current orientation
- int _newOrientation; // new orientation
-
- bool _saveToolbarState; // save visibility when forced
- String _saveActiveToolbar; // save active toolbar when forced
-
- bool _saveToolbarZoom; // save visibility when zooming
- bool _zoomUp; // zooming up mode
- bool _zoomDown; // zooming down mode
-
- bool _noDoubleTapRMB; // disable double tap -> rmb click
- bool _rbutton; // double tap -> right button simulation
- bool _closeClick; // flag when taps are spatially close together
-
- bool _usesEmulatedMouse; // emulated mousemove ever been used in this session
-
- bool _canBeAspectScaled; // game screen size allows for aspect scaling
-
- int _scaleFactorXm; // scaler X *
- int _scaleFactorXd; // scaler X /
- int _scaleFactorYm; // scaler Y *
- int _scaleFactorYd; // scaler Y /
- SDL_Rect _dirtyRectOut[NUM_DIRTY_RECT];
- bool _scalersChanged;
- bool _hasfocus; // scummvm has the top window
+ bool _forcePanelInvisible; // force panel visibility for some cases
static int _platformScreenWidth;
static int _platformScreenHeight;
- static bool _isOzone; // true if running on Windows 2003 SE
-
- // Keyboard tap
- int _tapX;
- int _tapY;
- long _tapTime;
-
- // Mouse
- int _mouseHotspotX, _mouseHotspotY;
- byte *_mouseBackupOld;
- uint16 *_mouseBackupToolbar;
- uint16 _mouseBackupDim;
-
- // Smartphone specific variables
-
- int _lastKeyPressed; // last key pressed
- int _keyRepeat; // number of time the last key was repeated
- int _keyRepeatTime; // elapsed time since the key was pressed
- int _keyRepeatTrigger; // minimum time to consider the key was repeated
-
- int _repeatX; // repeat trigger for left and right cursor moves
- int _repeatY; // repeat trigger for up and down cursor moves
- int _stepX1; // offset for left and right cursor moves (slowest)
- int _stepX2; // offset for left and right cursor moves (faster)
- int _stepX3; // offset for left and right cursor moves (fastest)
- int _stepY1; // offset for up and down cursor moves (slowest)
- int _stepY2; // offset for up and down cursor moves (faster)
- int _stepY3; // offset for up and down cursor moves (fastest)
-
- int _mouseXZone[TOTAL_ZONES];
- int _mouseYZone[TOTAL_ZONES];
- int _currentZone;
-
- struct zoneDesc {
- int x;
- int y;
- int width;
- int height;
- };
-
- static zoneDesc _zones[TOTAL_ZONES];
+ static bool _isOzone; // true if running on Windows 2003 SE
+
};
#endif
diff --git a/backends/saves/savefile.cpp b/backends/saves/savefile.cpp
index d2fc913f14..7b7d6b0c0c 100644
--- a/backends/saves/savefile.cpp
+++ b/backends/saves/savefile.cpp
@@ -31,8 +31,7 @@
namespace Common {
-bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) {
-
+bool SaveFileManager::copySavefile(const String &oldFilename, const String &newFilename) {
InSaveFile *inFile = 0;
OutSaveFile *outFile = 0;
uint32 size = 0;
@@ -57,9 +56,8 @@ bool SaveFileManager::renameSavefile(const String &oldFilename, const String &ne
if (!error) {
outFile->write(buffer, size);
outFile->finalize();
- if (!outFile->err()) {
- success = removeSavefile(oldFilename);
- }
+
+ success = !outFile->err();
}
}
@@ -71,6 +69,13 @@ bool SaveFileManager::renameSavefile(const String &oldFilename, const String &ne
return success;
}
+bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) {
+ if (!copySavefile(oldFilename, newFilename))
+ return false;
+
+ return removeSavefile(oldFilename);
+}
+
String SaveFileManager::popErrorDesc() {
String err = _errorDesc;
clearError();
diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp
index dd468bbe09..b5060c4c8d 100644
--- a/backends/timer/default/default-timer.cpp
+++ b/backends/timer/default/default-timer.cpp
@@ -34,7 +34,7 @@ struct TimerSlot {
uint32 interval; // in microseconds
uint32 nextFireTime; // in milliseconds
- uint32 nextFireTimeMicro; // mircoseconds part of nextFire
+ uint32 nextFireTimeMicro; // microseconds part of nextFire
TimerSlot *next;
};
diff --git a/backends/timer/default/default-timer.h b/backends/timer/default/default-timer.h
index e7ac3d122f..a4c7385ef9 100644
--- a/backends/timer/default/default-timer.h
+++ b/backends/timer/default/default-timer.h
@@ -40,9 +40,9 @@ private:
public:
DefaultTimerManager();
- ~DefaultTimerManager();
- bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
- void removeTimerProc(TimerProc proc);
+ virtual ~DefaultTimerManager();
+ virtual bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
+ virtual void removeTimerProc(TimerProc proc);
/**
* Timer callback, to be invoked at regular time intervals by the backend.
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 36218376c8..f920dd0170 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -178,6 +178,9 @@ void registerDefaults() {
ConfMan.registerDefault("midi_gain", 100);
// ConfMan.registerDefault("music_driver", ???);
+ ConfMan.registerDefault("mt32_device", "null");
+ ConfMan.registerDefault("gm_device", "null");
+
ConfMan.registerDefault("cdrom", 0);
// Game specific
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 93bd8348fc..38b5626fe2 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -215,6 +215,9 @@ public:
#ifdef USE_MT32EMU
LINK_PLUGIN(MT32)
#endif
+ #if defined(__ANDROID__)
+ LINK_PLUGIN(EAS)
+ #endif
LINK_PLUGIN(ADLIB)
LINK_PLUGIN(PCSPK)
LINK_PLUGIN(PCJR)
diff --git a/common/EventRecorder.cpp b/common/EventRecorder.cpp
index 07a651be65..1dedbb5059 100644
--- a/common/EventRecorder.cpp
+++ b/common/EventRecorder.cpp
@@ -144,7 +144,6 @@ void EventRecorder::init() {
}
uint32 sign;
- uint32 version;
uint32 randomSourceCount;
if (_recordMode == kRecorderPlayback) {
_playbackCount = 0;
@@ -168,7 +167,8 @@ void EventRecorder::init() {
if (sign != RECORD_SIGNATURE) {
error("Unknown record file signature");
}
- version = _playbackFile->readUint32LE();
+
+ _playbackFile->readUint32LE(); // version
// conf vars
ConfMan.setBool("subtitles", _playbackFile->readByte() != 0);
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 0561f390a4..77c918dcae 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -103,9 +103,9 @@ void ConfigManager::loadConfigFile(const String &filename) {
FSNode node(filename);
File cfg_file;
if (!cfg_file.open(node)) {
- debug("Creating configuration file: %s\n", filename.c_str());
+ debug("Creating configuration file: %s", filename.c_str());
} else {
- debug("Using configuration file: %s\n", _filename.c_str());
+ debug("Using configuration file: %s", _filename.c_str());
loadFromStream(cfg_file);
}
}
@@ -120,7 +120,7 @@ void ConfigManager::addDomain(const Common::String &domainName, const ConfigMana
if (domainName == kApplicationDomain) {
_appDomain = domain;
#ifdef ENABLE_KEYMAPPER
- } else if (domain == kKeymapperDomain) {
+ } else if (domainName == kKeymapperDomain) {
_keymapperDomain = domain;
#endif
} else if (domain.contains("gameid")) {
diff --git a/common/endian.h b/common/endian.h
index 32f92fd02c..e6c39d3a4c 100644
--- a/common/endian.h
+++ b/common/endian.h
@@ -141,27 +141,13 @@
/**
* A wrapper macro used around four character constants, like 'DATA', to
- * ensure portability. Typical usage: MKID_BE('DATA').
+ * ensure portability. Typical usage: MKTAG('D','A','T','A').
*
* Why is this necessary? The C/C++ standard does not define the endianess to
* be used for character constants. Hence if one uses multi-byte character
* constants, a potential portability problem opens up.
- *
- * Fortunately, a semi-standard has been established: On almost all systems
- * and compilers, multi-byte character constants are encoded using the big
- * endian convention (probably in analogy to the encoding of string constants).
- * Still some systems differ. This is why we provide the MKID_BE macro. If
- * you wrap your four character constants with it, the result will always be
- * BE encoded, even on systems which differ from the default BE encoding.
- *
- * For the latter systems we provide the INVERSE_MKID override.
*/
-#if defined(INVERSE_MKID)
-#define MKID_BE(a) SWAP_CONSTANT_32(a)
-
-#else
-# define MKID_BE(a) ((uint32)(a))
-#endif
+#define MKTAG(a0,a1,a2,a3) ((uint32)((a3) | ((a2) << 8) | ((a1) << 16) | ((a0) << 24)))
// Functions for reading/writing native Integers,
// this transparently handles the need for alignment
@@ -331,8 +317,6 @@
#elif defined(SCUMM_BIG_ENDIAN)
- #define MKID_BE(a) ((uint32)(a))
-
#define READ_BE_UINT16(a) READ_UINT16(a)
#define READ_BE_UINT32(a) READ_UINT32(a)
diff --git a/common/events.h b/common/events.h
index f9ebce7d64..120d7d9dea 100644
--- a/common/events.h
+++ b/common/events.h
@@ -81,30 +81,6 @@ enum EventType {
/**
* Data structure for an event. A pointer to an instance of Event
* can be passed to pollEvent.
- * @todo Rework/document this structure. It should be made 100% clear which
- * field is valid for which event type.
- * Implementation wise, we might want to use the classic
- * union-of-structs trick. It goes roughly like this:
- * struct BasicEvent {
- * EventType type;
- * };
- * struct MouseMovedEvent : BasicEvent {
- * Common::Point pos;
- * };
- * struct MouseButtonEvent : MouseMovedEvent {
- * int button;
- * };
- * struct KeyEvent : BasicEvent {
- * ...
- * };
- * ...
- * union Event {
- * EventType type;
- * MouseMovedEvent mouse;
- * MouseButtonEvent button;
- * KeyEvent key;
- * ...
- * };
*/
struct Event {
/** The type of the event. */
diff --git a/common/hashmap.h b/common/hashmap.h
index b645a37b01..233d7f5b16 100644
--- a/common/hashmap.h
+++ b/common/hashmap.h
@@ -142,8 +142,8 @@ private:
}
void assign(const HM_t &map);
- int lookup(const Key &key) const;
- int lookupAndCreateIfMissing(const Key &key);
+ uint lookup(const Key &key) const;
+ uint lookupAndCreateIfMissing(const Key &key);
void expandStorage(uint newCapacity);
#if !defined(__sgi) || defined(__GNUC__)
@@ -456,7 +456,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
}
template<class Key, class Val, class HashFunc, class EqualFunc>
-int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
+uint HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
const uint hash = _hash(key);
uint ctr = hash & _mask;
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
@@ -487,7 +487,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
}
template<class Key, class Val, class HashFunc, class EqualFunc>
-int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) {
+uint HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) {
const uint hash = _hash(key);
uint ctr = hash & _mask;
const uint NONE_FOUND = _mask + 1;
diff --git a/common/iff_container.h b/common/iff_container.h
index 16d4826238..01fc8017a9 100644
--- a/common/iff_container.h
+++ b/common/iff_container.h
@@ -35,111 +35,111 @@ namespace Common {
typedef uint32 IFF_ID;
-#define ID_FORM MKID_BE('FORM')
+#define ID_FORM MKTAG('F','O','R','M')
/* EA IFF 85 group identifier */
-#define ID_CAT MKID_BE('CAT ')
+#define ID_CAT MKTAG('C','A','T',' ')
/* EA IFF 85 group identifier */
-#define ID_LIST MKID_BE('LIST')
+#define ID_LIST MKTAG('L','I','S','T')
/* EA IFF 85 group identifier */
-#define ID_PROP MKID_BE('PROP')
+#define ID_PROP MKTAG('P','R','O','P')
/* EA IFF 85 group identifier */
-#define ID_END MKID_BE('END ')
+#define ID_END MKTAG('E','N','D',' ')
/* unofficial END-of-FORM identifier (see Amiga RKM Devices Ed.3
page 376) */
-#define ID_ILBM MKID_BE('ILBM')
+#define ID_ILBM MKTAG('I','L','B','M')
/* EA IFF 85 raster bitmap form */
-#define ID_DEEP MKID_BE('DEEP')
+#define ID_DEEP MKTAG('D','E','E','P')
/* Chunky pixel image files (Used in TV Paint) */
-#define ID_RGB8 MKID_BE('RGB8')
+#define ID_RGB8 MKTAG('R','G','B','8')
/* RGB image forms, Turbo Silver (Impulse) */
-#define ID_RGBN MKID_BE('RGBN')
+#define ID_RGBN MKTAG('R','G','B','N')
/* RGB image forms, Turbo Silver (Impulse) */
-#define ID_PBM MKID_BE('PBM ')
+#define ID_PBM MKTAG('P','B','M',' ')
/* 256-color chunky format (DPaint 2 ?) */
-#define ID_ACBM MKID_BE('ACBM')
+#define ID_ACBM MKTAG('A','C','B','M')
/* Amiga Contiguous Bitmap (AmigaBasic) */
-#define ID_8SVX MKID_BE('8SVX')
+#define ID_8SVX MKTAG('8','S','V','X')
/* Amiga 8 bits voice */
/* generic */
-#define ID_FVER MKID_BE('FVER')
+#define ID_FVER MKTAG('F','V','E','R')
/* AmigaOS version string */
-#define ID_JUNK MKID_BE('JUNK')
+#define ID_JUNK MKTAG('J','U','N','K')
/* always ignore this chunk */
-#define ID_ANNO MKID_BE('ANNO')
+#define ID_ANNO MKTAG('A','N','N','O')
/* EA IFF 85 Generic Annotation chunk */
-#define ID_AUTH MKID_BE('AUTH')
+#define ID_AUTH MKTAG('A','U','T','H')
/* EA IFF 85 Generic Author chunk */
-#define ID_CHRS MKID_BE('CHRS')
+#define ID_CHRS MKTAG('C','H','R','S')
/* EA IFF 85 Generic character string chunk */
-#define ID_NAME MKID_BE('NAME')
+#define ID_NAME MKTAG('N','A','M','E')
/* EA IFF 85 Generic Name of art, music, etc. chunk */
-#define ID_TEXT MKID_BE('TEXT')
+#define ID_TEXT MKTAG('T','E','X','T')
/* EA IFF 85 Generic unformatted ASCII text chunk */
-#define ID_copy MKID_BE('(c) ')
+#define ID_copy MKTAG('(','c',')',' ')
/* EA IFF 85 Generic Copyright text chunk */
/* ILBM chunks */
-#define ID_BMHD MKID_BE('BMHD')
+#define ID_BMHD MKTAG('B','M','H','D')
/* ILBM BitmapHeader */
-#define ID_CMAP MKID_BE('CMAP')
+#define ID_CMAP MKTAG('C','M','A','P')
/* ILBM 8bit RGB colormap */
-#define ID_GRAB MKID_BE('GRAB')
+#define ID_GRAB MKTAG('G','R','A','B')
/* ILBM "hotspot" coordiantes */
-#define ID_DEST MKID_BE('DEST')
+#define ID_DEST MKTAG('D','E','S','T')
/* ILBM destination image info */
-#define ID_SPRT MKID_BE('SPRT')
+#define ID_SPRT MKTAG('S','P','R','T')
/* ILBM sprite identifier */
-#define ID_CAMG MKID_BE('CAMG')
+#define ID_CAMG MKTAG('C','A','M','G')
/* Amiga viewportmodes */
-#define ID_BODY MKID_BE('BODY')
+#define ID_BODY MKTAG('B','O','D','Y')
/* ILBM image data */
-#define ID_CRNG MKID_BE('CRNG')
+#define ID_CRNG MKTAG('C','R','N','G')
/* color cycling */
-#define ID_CCRT MKID_BE('CCRT')
+#define ID_CCRT MKTAG('C','C','R','T')
/* color cycling */
-#define ID_CLUT MKID_BE('CLUT')
+#define ID_CLUT MKTAG('C','L','U','T')
/* Color Lookup Table chunk */
-#define ID_DPI MKID_BE('DPI ')
+#define ID_DPI MKTAG('D','P','I',' ')
/* Dots per inch chunk */
-#define ID_DPPV MKID_BE('DPPV')
+#define ID_DPPV MKTAG('D','P','P','V')
/* DPaint perspective chunk (EA) */
-#define ID_DRNG MKID_BE('DRNG')
+#define ID_DRNG MKTAG('D','R','N','G')
/* DPaint IV enhanced color cycle chunk (EA) */
-#define ID_EPSF MKID_BE('EPSF')
+#define ID_EPSF MKTAG('E','P','S','F')
/* Encapsulated Postscript chunk */
-#define ID_CMYK MKID_BE('CMYK')
+#define ID_CMYK MKTAG('C','M','Y','K')
/* Cyan, Magenta, Yellow, & Black color map (Soft-Logik) */
-#define ID_CNAM MKID_BE('CNAM')
+#define ID_CNAM MKTAG('C','N','A','M')
/* Color naming chunk (Soft-Logik) */
-#define ID_PCHG MKID_BE('PCHG')
+#define ID_PCHG MKTAG('P','C','H','G')
/* Line by line palette control information (Sebastiano Vigna) */
-#define ID_PRVW MKID_BE('PRVW')
+#define ID_PRVW MKTAG('P','R','V','W')
/* A mini duplicate ILBM used for preview (Gary Bonham) */
-#define ID_XBMI MKID_BE('XBMI')
+#define ID_XBMI MKTAG('X','B','M','I')
/* eXtended BitMap Information (Soft-Logik) */
-#define ID_CTBL MKID_BE('CTBL')
+#define ID_CTBL MKTAG('C','T','B','L')
/* Newtek Dynamic Ham color chunk */
-#define ID_DYCP MKID_BE('DYCP')
+#define ID_DYCP MKTAG('D','Y','C','P')
/* Newtek Dynamic Ham chunk */
-#define ID_SHAM MKID_BE('SHAM')
+#define ID_SHAM MKTAG('S','H','A','M')
/* Sliced HAM color chunk */
-#define ID_ABIT MKID_BE('ABIT')
+#define ID_ABIT MKTAG('A','B','I','T')
/* ACBM body chunk */
-#define ID_DCOL MKID_BE('DCOL')
+#define ID_DCOL MKTAG('D','C','O','L')
/* unofficial direct color */
-#define ID_DPPS MKID_BE('DPPS')
+#define ID_DPPS MKTAG('D','P','P','S')
/* ? */
-#define ID_TINY MKID_BE('TINY')
+#define ID_TINY MKTAG('T','I','N','Y')
/* ? */
-#define ID_DPPV MKID_BE('DPPV')
+#define ID_DPPV MKTAG('D','P','P','V')
/* ? */
/* 8SVX chunks */
-#define ID_VHDR MKID_BE('VHDR')
+#define ID_VHDR MKTAG('V','H','D','R')
/* 8SVX Voice8Header */
diff --git a/common/list.h b/common/list.h
index f3bc1df35e..ad6193c297 100644
--- a/common/list.h
+++ b/common/list.h
@@ -185,7 +185,7 @@ public:
}
uint size() const {
- int n = 0;
+ uint n = 0;
for (const NodeBase *cur = _anchor._next; cur != &_anchor; cur = cur->_next)
++n;
return n;
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 9a50549a9d..e7d4a30789 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -550,120 +550,110 @@ void MacResManager::readMap() {
}
}
-void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize) {
- MemoryReadStream dis(data, datasize);
- int i, b;
- byte imageByte;
- byte *iconData;
- int pixelsPerByte, bpp;
- int ctSize;
- byte bitmask;
- int iconRowBytes, iconBounds[4];
- int iconDataSize;
-
- dis.readUint16BE(); // type
- dis.readUint32BE(); // offset to pixel map
- dis.readUint32BE(); // offset to pixel data
- dis.readUint32BE(); // expanded cursor data
- dis.readUint16BE(); // expanded data depth
- dis.readUint32BE(); // reserved
+void MacResManager::convertCrsrCursor(SeekableReadStream *data, byte **cursor, int &w, int &h, int &hotspotX,
+ int &hotspotY, int &keycolor, bool colored, byte **palette, int &palSize) {
+
+ data->readUint16BE(); // type
+ data->readUint32BE(); // offset to pixel map
+ data->readUint32BE(); // offset to pixel data
+ data->readUint32BE(); // expanded cursor data
+ data->readUint16BE(); // expanded data depth
+ data->readUint32BE(); // reserved
// Grab B/W icon data
- *cursor = (byte *)malloc(16 * 16);
- for (i = 0; i < 32; i++) {
- imageByte = dis.readByte();
- for (b = 0; b < 8; b++)
- cursor[0][i*8+b] = (byte)((imageByte & (0x80 >> b)) > 0? 0x0F: 0x00);
+ *cursor = new byte[16 * 16];
+ for (int i = 0; i < 32; i++) {
+ byte imageByte = data->readByte();
+ for (int b = 0; b < 8; b++)
+ cursor[0][i * 8 + b] = (byte)((imageByte & (0x80 >> b)) > 0 ? 0x0F : 0x00);
}
// Apply mask data
- for (i = 0; i < 32; i++) {
- imageByte = dis.readByte();
- for (b = 0; b < 8; b++)
+ for (int i = 0; i < 32; i++) {
+ byte imageByte = data->readByte();
+ for (int b = 0; b < 8; b++)
if ((imageByte & (0x80 >> b)) == 0)
- cursor[0][i*8+b] = 0xff;
+ cursor[0][i * 8 + b] = 0xff;
}
- *hotspot_y = dis.readUint16BE();
- *hotspot_x = dis.readUint16BE();
- *w = *h = 16;
- *keycolor = 0xff;
+ hotspotY = data->readUint16BE();
+ hotspotX = data->readUint16BE();
+ w = h = 16;
+ keycolor = 0xff;
// Use b/w cursor on backends which don't support cursor palettes
if (!colored)
return;
- dis.readUint32BE(); // reserved
- dis.readUint32BE(); // cursorID
+ data->readUint32BE(); // reserved
+ data->readUint32BE(); // cursorID
// Color version of cursor
- dis.readUint32BE(); // baseAddr
+ data->readUint32BE(); // baseAddr
// Keep only lowbyte for now
- dis.readByte();
- iconRowBytes = dis.readByte();
+ data->readByte();
+ int iconRowBytes = data->readByte();
if (!iconRowBytes)
return;
- iconBounds[0] = dis.readUint16BE();
- iconBounds[1] = dis.readUint16BE();
- iconBounds[2] = dis.readUint16BE();
- iconBounds[3] = dis.readUint16BE();
+ int iconBounds[4];
+ iconBounds[0] = data->readUint16BE();
+ iconBounds[1] = data->readUint16BE();
+ iconBounds[2] = data->readUint16BE();
+ iconBounds[3] = data->readUint16BE();
- dis.readUint16BE(); // pmVersion
- dis.readUint16BE(); // packType
- dis.readUint32BE(); // packSize
+ data->readUint16BE(); // pmVersion
+ data->readUint16BE(); // packType
+ data->readUint32BE(); // packSize
- dis.readUint32BE(); // hRes
- dis.readUint32BE(); // vRes
+ data->readUint32BE(); // hRes
+ data->readUint32BE(); // vRes
- dis.readUint16BE(); // pixelType
- dis.readUint16BE(); // pixelSize
- dis.readUint16BE(); // cmpCount
- dis.readUint16BE(); // cmpSize
+ data->readUint16BE(); // pixelType
+ data->readUint16BE(); // pixelSize
+ data->readUint16BE(); // cmpCount
+ data->readUint16BE(); // cmpSize
- dis.readUint32BE(); // planeByte
- dis.readUint32BE(); // pmTable
- dis.readUint32BE(); // reserved
+ data->readUint32BE(); // planeByte
+ data->readUint32BE(); // pmTable
+ data->readUint32BE(); // reserved
// Pixel data for cursor
- iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]);
- iconData = (byte *)malloc(iconDataSize);
- dis.read(iconData, iconDataSize);
+ int iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]);
+ byte *iconData = new byte[iconDataSize];
+ data->read(iconData, iconDataSize);
// Color table
- dis.readUint32BE(); // ctSeed
- dis.readUint16BE(); // ctFlag
- ctSize = dis.readUint16BE() + 1;
+ data->readUint32BE(); // ctSeed
+ data->readUint16BE(); // ctFlag
+ uint16 ctSize = data->readUint16BE() + 1;
- *palette = (byte *)malloc(ctSize * 4);
+ *palette = new byte[ctSize * 3];
// Read just high byte of 16-bit color
for (int c = 0; c < ctSize; c++) {
// We just use indices 0..ctSize, so ignore color ID
- dis.readUint16BE(); // colorID[c]
-
- palette[0][c * 4 + 0] = dis.readByte();
- dis.readByte();
+ data->readUint16BE(); // colorID[c]
- palette[0][c * 4 + 1] = dis.readByte();
- dis.readByte();
+ palette[0][c * 3 + 0] = data->readByte();
+ data->readByte();
- palette[0][c * 4 + 2] = dis.readByte();
- dis.readByte();
+ palette[0][c * 3 + 1] = data->readByte();
+ data->readByte();
- palette[0][c * 4 + 3] = 0;
+ palette[0][c * 3 + 2] = data->readByte();
+ data->readByte();
}
- *palSize = ctSize;
+ palSize = ctSize;
- pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes;
- bpp = 8 / pixelsPerByte;
+ int pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes;
+ int bpp = 8 / pixelsPerByte;
// build a mask to make sure the pixels are properly shifted out
- bitmask = 0;
+ int bitmask = 0;
for (int m = 0; m < bpp; m++) {
bitmask <<= 1;
bitmask |= 1;
@@ -671,16 +661,16 @@ void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, i
// Extract pixels from bytes
for (int j = 0; j < iconDataSize; j++)
- for (b = 0; b < pixelsPerByte; b++) {
+ for (int b = 0; b < pixelsPerByte; b++) {
int idx = j * pixelsPerByte + (pixelsPerByte - 1 - b);
if (cursor[0][idx] != 0xff) // if mask is not there
cursor[0][idx] = (byte)((iconData[j] >> (b * bpp)) & bitmask);
}
- free(iconData);
+ delete[] iconData;
- assert(datasize - dis.pos() == 0);
+ assert(data->size() - data->pos() == 0);
}
} // End of namespace Common
diff --git a/common/macresman.h b/common/macresman.h
index 1cbebbcf4b..2ad0b608a1 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -154,14 +154,13 @@ public:
/**
* Convert cursor from crsr format to format suitable for feeding to CursorMan
- * @param data Pointer to the cursor data
- * @param datasize Size of the cursor data
+ * @param data Pointer to the cursor datax
* @param cursor Pointer to memory where result cursor will be stored. The memory
* block will be malloc()'ed
* @param w Pointer to int where the cursor width will be stored
* @param h Pointer to int where the cursor height will be stored
- * @param hotspot_x Storage for cursor hotspot X coordinate
- * @param hotspot_Y Storage for cursor hotspot Y coordinate
+ * @param hotspotX Storage for cursor hotspot X coordinate
+ * @param hotspotY Storage for cursor hotspot Y coordinate
* @param keycolor Pointer to int where the transpared color value will be stored
* @param colored If set to true then colored cursor will be returned (if any).
* b/w version will be used otherwise
@@ -169,8 +168,8 @@ public:
* The memory will be malloc()'ed
* @param palSize Pointer to integer where the palette size will be stored.
*/
- static void convertCrsrCursor(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize);
+ static void convertCrsrCursor(SeekableReadStream *data, byte **cursor, int &w, int &h, int &hotspotX,
+ int &hotspotY, int &keycolor, bool colored, byte **palette, int &palSize);
/**
* Return list of resource IDs with specified type ID
diff --git a/common/module.mk b/common/module.mk
index a4cea5c23f..a57de6a4b8 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -17,7 +17,6 @@ MODULE_OBJS := \
memorypool.o \
md5.o \
mutex.o \
- ne_exe.o \
random.o \
rational.o \
str.o \
@@ -29,6 +28,9 @@ MODULE_OBJS := \
unarj.o \
unzip.o \
util.o \
+ winexe.o \
+ winexe_ne.o \
+ winexe_pe.o \
xmlparser.o \
zlib.o
diff --git a/common/ne_exe.cpp b/common/ne_exe.cpp
deleted file mode 100644
index a216ef6446..0000000000
--- a/common/ne_exe.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/debug.h"
-#include "common/file.h"
-#include "common/memstream.h"
-#include "common/ne_exe.h"
-#include "common/str.h"
-#include "common/stream.h"
-
-namespace Common {
-
-NECursor::NECursor() {
- _width = 0;
- _height = 0;
- _hotspotX = 0;
- _hotspotY = 0;
- _surface = 0;
- memset(_palette, 0, 256 * 4);
-}
-
-NECursor::~NECursor() {
- clear();
-}
-
-uint16 NECursor::getWidth() const {
- return _width;
-}
-
-uint16 NECursor::getHeight() const {
- return _height;
-}
-
-uint16 NECursor::getHotspotX() const {
- return _hotspotX;
-}
-
-uint16 NECursor::getHotspotY() const {
- return _hotspotY;
-}
-
-void NECursor::setDimensions(uint16 width, uint16 height) {
- _width = width;
- _height = height;
-}
-
-void NECursor::setHotspot(uint16 x, uint16 y) {
- _hotspotX = x;
- _hotspotY = y;
-}
-
-bool NECursor::readCursor(SeekableReadStream &stream, uint32 count) {
- clear();
-
- SeekableReadStream *bitmap = stream.readStream(count);
- _surface = new byte[_width * _height];
-
- uint32 width = _width;
- uint32 height = _height * 2;
-
- // Sanity checks
- assert((width > 0) && (height > 0));
-
- // Check header size
- if (bitmap->readUint32LE() != 40)
- return false;
-
- // Check dimensions
- if (bitmap->readUint32LE() != width)
- return false;
- if (bitmap->readUint32LE() != height)
- return false;
-
- // Color planes
- if (bitmap->readUint16LE() != 1)
- return false;
- // Bits per pixel
- if (bitmap->readUint16LE() != 1)
- return false;
- // Compression
- if (bitmap->readUint32LE() != 0)
- return false;
-
- // Image size + X resolution + Y resolution
- bitmap->skip(12);
-
- uint32 numColors = bitmap->readUint32LE();
-
- if (numColors == 0)
- numColors = 2;
- else if (numColors > 2)
- return false;
-
- // Assert that enough data is there for the whole cursor
- if ((uint32)bitmap->size() < 40 + numColors * 4 + width * height / 8)
- return false;
-
- // Height includes AND-mask and XOR-mask
- height /= 2;
-
- // Standard palette: transparent, black, white
- _palette[8] = 0xff;
- _palette[9] = 0xff;
- _palette[10] = 0xff;
-
- // Reading the palette
- bitmap->seek(40);
- for (uint32 i = 0 ; i < numColors; i++) {
- _palette[(i + 1) * 4 + 2] = bitmap->readByte();
- _palette[(i + 1) * 4 + 1] = bitmap->readByte();
- _palette[(i + 1) * 4 + 0] = bitmap->readByte();
- bitmap->readByte();
- }
-
- // Reading the bitmap data
- uint32 dataSize = bitmap->size() - 40 - numColors * 4;
- byte *initialSource = new byte[dataSize];
- bitmap->read(initialSource, dataSize);
- const byte *srcP = initialSource;
- const byte *srcM = srcP + ((width * height) / 8);
- byte *dest = _surface + width * (height - 1);
-
- for (uint32 i = 0; i < height; i++) {
- byte *rowDest = dest;
-
- for (uint32 j = 0; j < (width / 8); j++) {
- byte p = srcP[j];
- byte m = srcM[j];
-
- for (int k = 0; k < 8; k++, rowDest++, p <<= 1, m <<= 1) {
- if ((m & 0x80) != 0x80) {
- if ((p & 0x80) == 0x80)
- *rowDest = 2;
- else
- *rowDest = 1;
- } else
- *rowDest = 0;
- }
- }
-
- dest -= width;
- srcP += width / 8;
- srcM += width / 8;
- }
-
- delete bitmap;
- delete[] initialSource;
- return true;
-}
-
-void NECursor::clear() {
- delete[] _surface; _surface = 0;
-}
-
-NEResourceID &NEResourceID::operator=(String string) {
- _name = string;
- _idType = kIDTypeString;
- return *this;
-}
-
-NEResourceID &NEResourceID::operator=(uint16 x) {
- _id = x;
- _idType = kIDTypeNumerical;
- return *this;
-}
-
-bool NEResourceID::operator==(const String &x) const {
- return _idType == kIDTypeString && _name.equalsIgnoreCase(x);
-}
-
-bool NEResourceID::operator==(const uint16 &x) const {
- return _idType == kIDTypeNumerical && _id == x;
-}
-
-bool NEResourceID::operator==(const NEResourceID &x) const {
- if (_idType != x._idType)
- return false;
- if (_idType == kIDTypeString)
- return _name.equalsIgnoreCase(x._name);
- if (_idType == kIDTypeNumerical)
- return _id == x._id;
- return true;
-}
-
-String NEResourceID::getString() const {
- if (_idType != kIDTypeString)
- return "";
-
- return _name;
-}
-
-uint16 NEResourceID::getID() const {
- if (_idType != kIDTypeNumerical)
- return 0xffff;
-
- return _idType;
-}
-
-String NEResourceID::toString() const {
- if (_idType == kIDTypeString)
- return _name;
- else if (_idType == kIDTypeNumerical)
- return String::format("%04x", _id);
-
- return "";
-}
-
-NEResources::NEResources() {
- _exe = 0;
-}
-
-NEResources::~NEResources() {
- clear();
-}
-
-void NEResources::clear() {
- if (_exe) {
- delete _exe;
- _exe = 0;
- }
-
- _resources.clear();
-
- for (uint32 i = 0; i < _cursors.size(); i++)
- for (uint32 j = 0; j < _cursors[i].cursors.size(); j++)
- delete _cursors[i].cursors[j];
-
- _cursors.clear();
-}
-
-const Array<NECursorGroup> &NEResources::getCursors() const {
- return _cursors;
-}
-
-bool NEResources::loadFromEXE(const String &fileName) {
- if (fileName.empty())
- return false;
-
- File *file = new File();
-
- if (!file->open(fileName)) {
- delete file;
- return false;
- }
-
- return loadFromEXE(file);
-}
-
-bool NEResources::loadFromEXE(SeekableReadStream *stream) {
- clear();
-
- if (!stream)
- return false;
-
- _exe = stream;
-
- uint32 offsetResourceTable = getResourceTableOffset();
- if (offsetResourceTable == 0xFFFFFFFF)
- return false;
- if (offsetResourceTable == 0)
- return true;
-
- if (!readResourceTable(offsetResourceTable))
- return false;
-
- if (!readCursors())
- return false;
-
- return true;
-}
-
-bool NEResources::loadFromCompressedEXE(const String &fileName) {
- // Based on http://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html
-
- File file;
-
- if (!file.open(fileName))
- return false;
-
- // First part of the signature
- if (file.readUint32BE() != MKID_BE('SZDD'))
- return false;
-
- // Second part of the signature
- if (file.readUint32BE() != 0x88F02733)
- return false;
-
- // Compression mode must be 'A'
- if (file.readByte() != 'A')
- return false;
-
- file.readByte(); // file name character change
- uint32 unpackedLength = file.readUint32LE();
-
- byte *window = new byte[0x1000];
- int pos = 0x1000 - 16;
- memset(window, 0x20, 0x1000); // Initialize to all spaces
-
- byte *unpackedData = (byte *)malloc(unpackedLength);
- byte *dataPos = unpackedData;
-
- // Apply simple LZSS decompression
- for (;;) {
- byte controlByte = file.readByte();
-
- if (file.eos())
- break;
-
- for (byte i = 0; i < 8; i++) {
- if (controlByte & (1 << i)) {
- *dataPos++ = window[pos++] = file.readByte();
- pos &= 0xFFF;
- } else {
- int matchPos = file.readByte();
- int matchLen = file.readByte();
- matchPos |= (matchLen & 0xF0) << 4;
- matchLen = (matchLen & 0xF) + 3;
- while (matchLen--) {
- *dataPos++ = window[pos++] = window[matchPos++];
- pos &= 0xFFF;
- matchPos &= 0xFFF;
- }
- }
-
- }
- }
-
- delete[] window;
- SeekableReadStream *stream = new MemoryReadStream(unpackedData, unpackedLength);
-
- return loadFromEXE(stream);
-}
-
-uint32 NEResources::getResourceTableOffset() {
- if (!_exe)
- return 0xFFFFFFFF;
-
- if (!_exe->seek(0))
- return 0xFFFFFFFF;
-
- // 'MZ'
- if (_exe->readUint16BE() != 0x4D5A)
- return 0xFFFFFFFF;
-
- if (!_exe->seek(60))
- return 0xFFFFFFFF;
-
- uint32 offsetSegmentEXE = _exe->readUint16LE();
- if (!_exe->seek(offsetSegmentEXE))
- return 0xFFFFFFFF;
-
- // 'NE'
- if (_exe->readUint16BE() != 0x4E45)
- return 0xFFFFFFFF;
-
- if (!_exe->seek(offsetSegmentEXE + 36))
- return 0xFFFFFFFF;
-
- uint32 offsetResourceTable = _exe->readUint16LE();
- if (offsetResourceTable == 0)
- // No resource table
- return 0;
-
- // Offset relative to the segment _exe header
- offsetResourceTable += offsetSegmentEXE;
- if (!_exe->seek(offsetResourceTable))
- return 0xFFFFFFFF;
-
- return offsetResourceTable;
-}
-
-static const char *s_resTypeNames[] = {
- "", "cursor", "bitmap", "icon", "menu", "dialog", "string",
- "font_dir", "font", "accelerator", "rc_data", "msg_table",
- "group_cursor", "group_icon", "version", "dlg_include",
- "plug_play", "vxd", "ani_cursor", "ani_icon", "html",
- "manifest"
-};
-
-bool NEResources::readResourceTable(uint32 offset) {
- if (!_exe)
- return false;
-
- if (!_exe->seek(offset))
- return false;
-
- uint32 align = 1 << _exe->readUint16LE();
-
- uint16 typeID = _exe->readUint16LE();
- while (typeID != 0) {
- uint16 resCount = _exe->readUint16LE();
-
- _exe->skip(4); // reserved
-
- for (int i = 0; i < resCount; i++) {
- Resource res;
-
- // Resource properties
- res.offset = _exe->readUint16LE() * align;
- res.size = _exe->readUint16LE() * align;
- res.flags = _exe->readUint16LE();
- uint16 id = _exe->readUint16LE();
- res.handle = _exe->readUint16LE();
- res.usage = _exe->readUint16LE();
-
- res.type = typeID;
-
- if ((id & 0x8000) == 0)
- res.id = getResourceString(*_exe, offset + id);
- else
- res.id = id & 0x7FFF;
-
- if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames)))
- debug(2, "Found resource %s %s", s_resTypeNames[typeID & 0x7FFF], res.id.toString().c_str());
- else
- debug(2, "Found resource %04x %s", typeID, res.id.toString().c_str());
-
- _resources.push_back(res);
- }
-
- typeID = _exe->readUint16LE();
- }
-
- return true;
-}
-
-String NEResources::getResourceString(SeekableReadStream &exe, uint32 offset) {
- uint32 curPos = exe.pos();
-
- if (!exe.seek(offset)) {
- exe.seek(curPos);
- return "";
- }
-
- uint8 length = exe.readByte();
-
- String string;
- for (uint16 i = 0; i < length; i++)
- string += (char)exe.readByte();
-
- exe.seek(curPos);
- return string;
-}
-
-const NEResources::Resource *NEResources::findResource(uint16 type, NEResourceID id) const {
- for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
- if (it->type == type && it->id == id)
- return &*it;
-
- return 0;
-}
-
-SeekableReadStream *NEResources::getResource(uint16 type, NEResourceID id) {
- const Resource *res = findResource(type, id);
-
- if (!res)
- return 0;
-
- _exe->seek(res->offset);
- return _exe->readStream(res->size);
-}
-
-const Array<NEResourceID> NEResources::getIDList(uint16 type) const {
- Array<NEResourceID> idArray;
-
- for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
- if (it->type == type)
- idArray.push_back(it->id);
-
- return idArray;
-}
-
-bool NEResources::readCursors() {
- uint32 cursorCount = 0;
-
- for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
- if (it->type == kNEGroupCursor)
- cursorCount++;
-
- if (cursorCount == 0) {
- _cursors.clear();
- return true;
- }
-
- _cursors.resize(cursorCount);
-
- Array<NECursorGroup>::iterator cursorGroup = _cursors.begin();
- for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) {
- if (it->type == kNEGroupCursor) {
- if (!readCursorGroup(*cursorGroup, *it))
- return false;
-
- ++cursorGroup;
- }
- }
-
- return true;
-}
-
-bool NEResources::readCursorGroup(NECursorGroup &group, const Resource &resource) {
- if (!_exe)
- return false;
-
- if (resource.size <= 6)
- return false;
-
- if (!_exe->seek(resource.offset))
- return false;
-
- byte *data = new byte[resource.size];
-
- if (!_exe->read(data, resource.size)) {
- delete[] data;
- return false;
- }
-
- uint32 cursorCount = READ_LE_UINT16(data + 4);
- if (resource.size < (6 + cursorCount * 16)) {
- delete[] data;
- return false;
- }
-
- group.cursors.resize(cursorCount);
-
- uint32 offset = 6;
- for (uint32 i = 0; i < cursorCount; i++) {
- group.cursors[i] = new NECursor();
- NECursor *cursor = group.cursors[i];
-
- // Plane count
- if (READ_LE_UINT16(data + offset + 4) != 1) {
- delete[] data;
- return false;
- }
-
- // Bit count
- if (READ_LE_UINT16(data + offset + 6) != 1) {
- delete[] data;
- return false;
- }
-
- uint32 id = READ_LE_UINT32(data + offset + 12);
- const Resource *cursorResource = findResource(kNECursor, id);
- if (!cursorResource) {
- delete[] data;
- return false;
- }
-
- cursor->setDimensions(READ_LE_UINT16(data + offset), READ_LE_UINT16(data + offset + 2) / 2);
-
- uint32 dataSize = READ_LE_UINT32(data + offset + 8);
- if (!readCursor(*cursor, *cursorResource, dataSize)) {
- delete[] data;
- return false;
- }
-
- offset += 16;
- }
-
- group.id = resource.id;
-
- delete[] data;
- return true;
-}
-
-bool NEResources::readCursor(NECursor &cursor, const Resource &resource, uint32 size) {
- if (!_exe)
- return false;
-
- if (size <= 4)
- return false;
- if (resource.size < size)
- return false;
-
- if (!_exe->seek(resource.offset))
- return false;
-
- uint32 hotspotX = _exe->readUint16LE();
- uint32 hotspotY = _exe->readUint16LE();
- cursor.setHotspot(hotspotX, hotspotY);
-
- size -= 4;
-
- if (!cursor.readCursor(*_exe, size))
- return false;
-
- return true;
-}
-
-} // End of namespace Common
diff --git a/common/savefile.h b/common/savefile.h
index 16b0fdbfbe..793aec3ba9 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -136,6 +136,14 @@ public:
virtual bool renameSavefile(const String &oldName, const String &newName);
/**
+ * Copy the given savefile.
+ * @param oldName Old name.
+ * @param newName New name.
+ * @return true if no error occurred. false otherwise.
+ */
+ virtual bool copySavefile(const String &oldName, const String &newName);
+
+ /**
* Request a list of available savegames with a given DOS-style pattern,
* also known as "glob" in the UNIX world. Refer to the Common::matchString()
* function to learn about the precise pattern format.
diff --git a/common/scummsys.h b/common/scummsys.h
index b0f514cdd1..6554c70163 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -94,6 +94,11 @@
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
+ // MSVC does not define M_PI, M_SQRT2 and other math defines by default.
+ // _USE_MATH_DEFINES must be defined in order to have these defined, thus
+ // we enable it here. For more information, check:
+ // http://msdn.microsoft.com/en-us/library/4hwaceh6(v=VS.100).aspx
+ #define _USE_MATH_DEFINES
#include <math.h>
#endif
@@ -238,11 +243,6 @@
// You need to set this manually if necessary
// #define SCUMM_NEED_ALIGNMENT
- #if defined(__DECCXX) // Assume alpha architecture
- #define INVERSE_MKID
- #define SCUMM_NEED_ALIGNMENT
- #endif
-
// Very BAD hack following, used to avoid triggering an assert in uClibc dingux library
// "toupper" when pressing keyboard function keys.
#if defined(DINGUX)
@@ -405,10 +405,6 @@
#define STRINGBUFLEN 1024
#endif
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
#ifndef MAXPATHLEN
#define MAXPATHLEN 256
#endif
diff --git a/common/winexe.cpp b/common/winexe.cpp
new file mode 100644
index 0000000000..9602e84c88
--- /dev/null
+++ b/common/winexe.cpp
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/str.h"
+#include "common/winexe.h"
+
+namespace Common {
+
+WinResourceID &WinResourceID::operator=(const String &x) {
+ _name = x;
+ _idType = kIDTypeString;
+ return *this;
+}
+
+WinResourceID &WinResourceID::operator=(uint32 x) {
+ _id = x;
+ _idType = kIDTypeNumerical;
+ return *this;
+}
+
+bool WinResourceID::operator==(const String &x) const {
+ return _idType == kIDTypeString && _name.equalsIgnoreCase(x);
+}
+
+bool WinResourceID::operator==(const uint32 &x) const {
+ return _idType == kIDTypeNumerical && _id == x;
+}
+
+bool WinResourceID::operator==(const WinResourceID &x) const {
+ if (_idType != x._idType)
+ return false;
+ if (_idType == kIDTypeString)
+ return _name.equalsIgnoreCase(x._name);
+ if (_idType == kIDTypeNumerical)
+ return _id == x._id;
+ return true;
+}
+
+String WinResourceID::getString() const {
+ if (_idType != kIDTypeString)
+ return "";
+
+ return _name;
+}
+
+uint32 WinResourceID::getID() const {
+ if (_idType != kIDTypeNumerical)
+ return 0xffffffff;
+
+ return _id;
+}
+
+String WinResourceID::toString() const {
+ if (_idType == kIDTypeString)
+ return _name;
+ else if (_idType == kIDTypeNumerical)
+ return String::format("%08x", _id);
+
+ return "";
+}
+
+} // End of namespace Common
diff --git a/common/winexe.h b/common/winexe.h
new file mode 100644
index 0000000000..af0d70c555
--- /dev/null
+++ b/common/winexe.h
@@ -0,0 +1,74 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_WINEXE_H
+#define COMMON_WINEXE_H
+
+#include "common/hash-str.h"
+
+namespace Common {
+
+class String;
+
+class WinResourceID {
+public:
+ WinResourceID() { _idType = kIDTypeNull; }
+ WinResourceID(String x) { _idType = kIDTypeString; _name = x; }
+ WinResourceID(uint32 x) { _idType = kIDTypeNumerical; _id = x; }
+
+ WinResourceID &operator=(const String &x);
+ WinResourceID &operator=(uint32 x);
+
+ bool operator==(const String &x) const;
+ bool operator==(const uint32 &x) const;
+ bool operator==(const WinResourceID &x) const;
+
+ String getString() const;
+ uint32 getID() const;
+ String toString() const;
+
+private:
+ /** An ID Type. */
+ enum IDType {
+ kIDTypeNull, ///< No type set
+ kIDTypeNumerical, ///< A numerical ID.
+ kIDTypeString ///< A string ID.
+ } _idType;
+
+ String _name; ///< The resource's string ID.
+ uint32 _id; ///< The resource's numerical ID.
+};
+
+struct WinResourceID_Hash {
+ uint operator()(const WinResourceID &id) const { return hashit(id.toString()); }
+};
+
+struct WinResourceID_EqualTo {
+ bool operator()(const WinResourceID &id1, const WinResourceID &id2) const { return id1 == id2; }
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp
new file mode 100644
index 0000000000..844127b0e1
--- /dev/null
+++ b/common/winexe_ne.cpp
@@ -0,0 +1,291 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/winexe_ne.h"
+
+namespace Common {
+
+NEResources::NEResources() {
+ _exe = 0;
+}
+
+NEResources::~NEResources() {
+ clear();
+}
+
+void NEResources::clear() {
+ if (_exe) {
+ delete _exe;
+ _exe = 0;
+ }
+
+ _resources.clear();
+}
+
+bool NEResources::loadFromEXE(const String &fileName) {
+ if (fileName.empty())
+ return false;
+
+ File *file = new File();
+
+ if (!file->open(fileName)) {
+ delete file;
+ return false;
+ }
+
+ return loadFromEXE(file);
+}
+
+bool NEResources::loadFromEXE(SeekableReadStream *stream) {
+ clear();
+
+ if (!stream)
+ return false;
+
+ _exe = stream;
+
+ uint32 offsetResourceTable = getResourceTableOffset();
+ if (offsetResourceTable == 0xFFFFFFFF)
+ return false;
+ if (offsetResourceTable == 0)
+ return true;
+
+ if (!readResourceTable(offsetResourceTable))
+ return false;
+
+ return true;
+}
+
+bool NEResources::loadFromCompressedEXE(const String &fileName) {
+ // Based on http://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html
+
+ // TODO: Merge this with with loadFromEXE() so the handling of the compressed
+ // EXE's is transparent
+
+ File file;
+
+ if (!file.open(fileName))
+ return false;
+
+ // First part of the signature
+ if (file.readUint32BE() != MKTAG('S','Z','D','D'))
+ return false;
+
+ // Second part of the signature
+ if (file.readUint32BE() != 0x88F02733)
+ return false;
+
+ // Compression mode must be 'A'
+ if (file.readByte() != 'A')
+ return false;
+
+ file.readByte(); // file name character change
+ uint32 unpackedLength = file.readUint32LE();
+
+ byte *window = new byte[0x1000];
+ int pos = 0x1000 - 16;
+ memset(window, 0x20, 0x1000); // Initialize to all spaces
+
+ byte *unpackedData = (byte *)malloc(unpackedLength);
+ assert(unpackedData);
+ byte *dataPos = unpackedData;
+
+ // Apply simple LZSS decompression
+ for (;;) {
+ byte controlByte = file.readByte();
+
+ if (file.eos())
+ break;
+
+ for (byte i = 0; i < 8; i++) {
+ if (controlByte & (1 << i)) {
+ *dataPos++ = window[pos++] = file.readByte();
+ pos &= 0xFFF;
+ } else {
+ int matchPos = file.readByte();
+ int matchLen = file.readByte();
+ matchPos |= (matchLen & 0xF0) << 4;
+ matchLen = (matchLen & 0xF) + 3;
+ while (matchLen--) {
+ *dataPos++ = window[pos++] = window[matchPos++];
+ pos &= 0xFFF;
+ matchPos &= 0xFFF;
+ }
+ }
+
+ }
+ }
+
+ delete[] window;
+ SeekableReadStream *stream = new MemoryReadStream(unpackedData, unpackedLength);
+
+ return loadFromEXE(stream);
+}
+
+uint32 NEResources::getResourceTableOffset() {
+ if (!_exe)
+ return 0xFFFFFFFF;
+
+ if (!_exe->seek(0))
+ return 0xFFFFFFFF;
+
+ // 'MZ'
+ if (_exe->readUint16BE() != 0x4D5A)
+ return 0xFFFFFFFF;
+
+ if (!_exe->seek(60))
+ return 0xFFFFFFFF;
+
+ uint32 offsetSegmentEXE = _exe->readUint16LE();
+ if (!_exe->seek(offsetSegmentEXE))
+ return 0xFFFFFFFF;
+
+ // 'NE'
+ if (_exe->readUint16BE() != 0x4E45)
+ return 0xFFFFFFFF;
+
+ if (!_exe->seek(offsetSegmentEXE + 36))
+ return 0xFFFFFFFF;
+
+ uint32 offsetResourceTable = _exe->readUint16LE();
+ if (offsetResourceTable == 0)
+ // No resource table
+ return 0;
+
+ // Offset relative to the segment _exe header
+ offsetResourceTable += offsetSegmentEXE;
+ if (!_exe->seek(offsetResourceTable))
+ return 0xFFFFFFFF;
+
+ return offsetResourceTable;
+}
+
+static const char *s_resTypeNames[] = {
+ "", "cursor", "bitmap", "icon", "menu", "dialog", "string",
+ "font_dir", "font", "accelerator", "rc_data", "msg_table",
+ "group_cursor", "group_icon", "version", "dlg_include",
+ "plug_play", "vxd", "ani_cursor", "ani_icon", "html",
+ "manifest"
+};
+
+bool NEResources::readResourceTable(uint32 offset) {
+ if (!_exe)
+ return false;
+
+ if (!_exe->seek(offset))
+ return false;
+
+ uint32 align = 1 << _exe->readUint16LE();
+
+ uint16 typeID = _exe->readUint16LE();
+ while (typeID != 0) {
+ uint16 resCount = _exe->readUint16LE();
+
+ _exe->skip(4); // reserved
+
+ for (int i = 0; i < resCount; i++) {
+ Resource res;
+
+ // Resource properties
+ res.offset = _exe->readUint16LE() * align;
+ res.size = _exe->readUint16LE() * align;
+ res.flags = _exe->readUint16LE();
+ uint16 id = _exe->readUint16LE();
+ res.handle = _exe->readUint16LE();
+ res.usage = _exe->readUint16LE();
+
+ res.type = typeID;
+
+ if ((id & 0x8000) == 0)
+ res.id = getResourceString(*_exe, offset + id);
+ else
+ res.id = id & 0x7FFF;
+
+ if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames)))
+ debug(2, "Found resource %s %s", s_resTypeNames[typeID & 0x7FFF], res.id.toString().c_str());
+ else
+ debug(2, "Found resource %04x %s", typeID, res.id.toString().c_str());
+
+ _resources.push_back(res);
+ }
+
+ typeID = _exe->readUint16LE();
+ }
+
+ return true;
+}
+
+String NEResources::getResourceString(SeekableReadStream &exe, uint32 offset) {
+ uint32 curPos = exe.pos();
+
+ if (!exe.seek(offset)) {
+ exe.seek(curPos);
+ return "";
+ }
+
+ uint8 length = exe.readByte();
+
+ String string;
+ for (uint16 i = 0; i < length; i++)
+ string += (char)exe.readByte();
+
+ exe.seek(curPos);
+ return string;
+}
+
+const NEResources::Resource *NEResources::findResource(uint16 type, WinResourceID id) const {
+ for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
+ if (it->type == type && it->id == id)
+ return &*it;
+
+ return 0;
+}
+
+SeekableReadStream *NEResources::getResource(uint16 type, WinResourceID id) {
+ const Resource *res = findResource(type, id);
+
+ if (!res)
+ return 0;
+
+ _exe->seek(res->offset);
+ return _exe->readStream(res->size);
+}
+
+const Array<WinResourceID> NEResources::getIDList(uint16 type) const {
+ Array<WinResourceID> idArray;
+
+ for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it)
+ if (it->type == type)
+ idArray.push_back(it->id);
+
+ return idArray;
+}
+
+} // End of namespace Common
diff --git a/common/ne_exe.h b/common/winexe_ne.h
index ac080d8a7c..c1d04080ba 100644
--- a/common/ne_exe.h
+++ b/common/winexe_ne.h
@@ -23,11 +23,12 @@
*
*/
-#ifndef COMMON_NE_EXE_H
-#define COMMON_NE_EXE_H
+#ifndef COMMON_WINEXE_NE_H
+#define COMMON_WINEXE_NE_H
#include "common/array.h"
#include "common/list.h"
+#include "common/winexe.h"
namespace Common {
@@ -35,80 +36,6 @@ class MemoryReadStream;
class SeekableReadStream;
class String;
-/** A New Executable cursor. */
-class NECursor {
-public:
- NECursor();
- ~NECursor();
-
- /** Return the cursor's width. */
- uint16 getWidth() const;
- /** Return the cursor's height. */
- uint16 getHeight() const;
- /** Return the cursor's hotspot's x coordinate. */
- uint16 getHotspotX() const;
- /** Return the cursor's hotspot's y coordinate. */
- uint16 getHotspotY() const;
-
- const byte *getSurface() const { return _surface; }
- const byte *getPalette() const { return _palette; }
-
- /** Set the cursor's dimensions. */
- void setDimensions(uint16 width, uint16 height);
- /** Set the cursor's hotspot. */
- void setHotspot(uint16 x, uint16 y);
-
- /** Read the cursor's data out of a stream. */
- bool readCursor(SeekableReadStream &stream, uint32 count);
-
-private:
- byte *_surface;
- byte _palette[256 * 4];
-
- uint16 _width; ///< The cursor's width.
- uint16 _height; ///< The cursor's height.
- uint16 _hotspotX; ///< The cursor's hotspot's x coordinate.
- uint16 _hotspotY; ///< The cursor's hotspot's y coordinate.
-
- /** Clear the cursor. */
- void clear();
-};
-
-class NEResourceID {
-public:
- NEResourceID() { _idType = kIDTypeNull; }
- NEResourceID(String x) { _idType = kIDTypeString; _name = x; }
- NEResourceID(uint16 x) { _idType = kIDTypeNumerical; _id = x; }
-
- NEResourceID &operator=(String string);
- NEResourceID &operator=(uint16 x);
-
- bool operator==(const String &x) const;
- bool operator==(const uint16 &x) const;
- bool operator==(const NEResourceID &x) const;
-
- String getString() const;
- uint16 getID() const;
- String toString() const;
-
-private:
- /** An ID Type. */
- enum IDType {
- kIDTypeNull, ///< No type set
- kIDTypeNumerical, ///< A numerical ID.
- kIDTypeString ///< A string ID.
- } _idType;
-
- String _name; ///< The resource's string ID.
- uint16 _id; ///< The resource's numerical ID.
-};
-
-/** A New Executable cursor group. */
-struct NECursorGroup {
- NEResourceID id;
- Array<NECursor *> cursors; ///< The cursors.
-};
-
/** The default Windows resources. */
enum NEResourceType {
kNECursor = 0x8001,
@@ -157,19 +84,16 @@ public:
/** Load from a stream. */
bool loadFromEXE(SeekableReadStream *stream);
- /** Get all cursor's read from the New Executable. */
- const Array<NECursorGroup> &getCursors() const;
-
/** Return a list of resources for a given type. */
- const Array<NEResourceID> getIDList(uint16 type) const;
+ const Array<WinResourceID> getIDList(uint16 type) const;
/** Return a stream to the specified resource (or 0 if non-existent). */
- SeekableReadStream *getResource(uint16 type, NEResourceID id);
+ SeekableReadStream *getResource(uint16 type, WinResourceID id);
private:
/** A resource. */
struct Resource {
- NEResourceID id;
+ WinResourceID id;
uint16 type; ///< Type of the resource.
@@ -186,21 +110,13 @@ private:
/** All resources. */
List<Resource> _resources;
- /** All cursor resources. */
- Array<NECursorGroup> _cursors;
-
/** Read the offset to the resource table. */
uint32 getResourceTableOffset();
/** Read the resource table. */
bool readResourceTable(uint32 offset);
- // Cursor reading helpers
- bool readCursors();
- bool readCursorGroup(NECursorGroup &group, const Resource &resource);
- bool readCursor(NECursor &cursor, const Resource &resource, uint32 size);
-
/** Find a specific resource. */
- const Resource *findResource(uint16 type, NEResourceID id) const;
+ const Resource *findResource(uint16 type, WinResourceID id) const;
/** Read a resource string. */
static String getResourceString(SeekableReadStream &exe, uint32 offset);
@@ -208,4 +124,4 @@ private:
} // End of namespace Common
-#endif // COMMON_NE_EXE_H
+#endif
diff --git a/common/winexe_pe.cpp b/common/winexe_pe.cpp
new file mode 100644
index 0000000000..17db004bfc
--- /dev/null
+++ b/common/winexe_pe.cpp
@@ -0,0 +1,255 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/winexe_pe.h"
+
+namespace Common {
+
+PEResources::PEResources() {
+ _exe = 0;
+}
+
+PEResources::~PEResources() {
+ clear();
+}
+
+void PEResources::clear() {
+ _sections.clear();
+ _resources.clear();
+ delete _exe; _exe = 0;
+}
+
+bool PEResources::loadFromEXE(const String &fileName) {
+ if (fileName.empty())
+ return false;
+
+ File *file = new File();
+
+ if (!file->open(fileName)) {
+ delete file;
+ return false;
+ }
+
+ return loadFromEXE(file);
+}
+
+bool PEResources::loadFromEXE(SeekableReadStream *stream) {
+ clear();
+
+ if (!stream)
+ return false;
+
+ if (stream->readUint16BE() != 'MZ')
+ return false;
+
+ stream->skip(58);
+
+ uint32 peOffset = stream->readUint32LE();
+
+ if (!peOffset || peOffset >= (uint32)stream->size())
+ return false;
+
+ stream->seek(peOffset);
+
+ if (stream->readUint32BE() != MKTAG('P','E',0,0))
+ return false;
+
+ stream->skip(2);
+ uint16 sectionCount = stream->readUint16LE();
+ stream->skip(12);
+ uint16 optionalHeaderSize = stream->readUint16LE();
+ stream->skip(optionalHeaderSize + 2);
+
+ // Read in all the sections
+ for (uint16 i = 0; i < sectionCount; i++) {
+ char sectionName[9];
+ stream->read(sectionName, 8);
+ sectionName[8] = 0;
+
+ Section section;
+ stream->skip(4);
+ section.virtualAddress = stream->readUint32LE();
+ section.size = stream->readUint32LE();
+ section.offset = stream->readUint32LE();
+ stream->skip(16);
+
+ _sections[sectionName] = section;
+ }
+
+ // Currently, we require loading a resource section
+ if (!_sections.contains(".rsrc")) {
+ clear();
+ return false;
+ }
+
+ _exe = stream;
+
+ Section &resSection = _sections[".rsrc"];
+ parseResourceLevel(resSection, resSection.offset, 0);
+
+ return true;
+}
+
+void PEResources::parseResourceLevel(Section &section, uint32 offset, int level) {
+ _exe->seek(offset + 12);
+
+ uint16 namedEntryCount = _exe->readUint16LE();
+ uint16 intEntryCount = _exe->readUint16LE();
+
+ for (uint32 i = 0; i < namedEntryCount + intEntryCount; i++) {
+ uint32 value = _exe->readUint32LE();
+
+ WinResourceID id;
+
+ if (value & 0x80000000) {
+ value &= 0x7fffffff;
+
+ uint32 startPos = _exe->pos();
+ _exe->seek(section.offset + (value & 0x7fffffff));
+
+ // Read in the name, truncating from unicode to ascii
+ Common::String name;
+ uint16 nameLength = _exe->readUint16LE();
+ while (nameLength--)
+ name += (char)(_exe->readUint16LE() & 0xff);
+
+ _exe->seek(startPos);
+
+ id = name;
+ } else {
+ id = value;
+ }
+
+ uint32 nextOffset = _exe->readUint32LE();
+ uint32 lastOffset = _exe->pos();
+
+ if (level == 0)
+ _curType = id;
+ else if (level == 1)
+ _curName = id;
+ else if (level == 2)
+ _curLang = id;
+
+ if (level < 2) {
+ // Time to dive down further
+ parseResourceLevel(section, section.offset + (nextOffset & 0x7fffffff), level + 1);
+ } else {
+ _exe->seek(section.offset + nextOffset);
+
+ Resource resource;
+ resource.offset = _exe->readUint32LE() + section.offset - section.virtualAddress;
+ resource.size = _exe->readUint32LE();
+
+ debug(4, "Found resource '%s' '%s' '%s' at %d of size %d", _curType.toString().c_str(),
+ _curName.toString().c_str(), _curLang.toString().c_str(), resource.offset, resource.size);
+
+ _resources[_curType][_curName][_curLang] = resource;
+ }
+
+ _exe->seek(lastOffset);
+ }
+}
+
+const Array<WinResourceID> PEResources::getTypeList() const {
+ Array<WinResourceID> array;
+
+ if (!_exe)
+ return array;
+
+ for (TypeMap::const_iterator it = _resources.begin(); it != _resources.end(); it++)
+ array.push_back(it->_key);
+
+ return array;
+}
+
+const Array<WinResourceID> PEResources::getNameList(const WinResourceID &type) const {
+ Array<WinResourceID> array;
+
+ if (!_exe || !_resources.contains(type))
+ return array;
+
+ const NameMap &nameMap = _resources[type];
+
+ for (NameMap::const_iterator it = nameMap.begin(); it != nameMap.end(); it++)
+ array.push_back(it->_key);
+
+ return array;
+}
+
+const Array<WinResourceID> PEResources::getLangList(const WinResourceID &type, const WinResourceID &name) const {
+ Array<WinResourceID> array;
+
+ if (!_exe || !_resources.contains(type))
+ return array;
+
+ const NameMap &nameMap = _resources[type];
+
+ if (!nameMap.contains(name))
+ return array;
+
+ const LangMap &langMap = nameMap[name];
+
+ for (LangMap::const_iterator it = langMap.begin(); it != langMap.end(); it++)
+ array.push_back(it->_key);
+
+ return array;
+}
+
+SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name) {
+ Array<WinResourceID> langList = getLangList(type, name);
+
+ if (langList.empty())
+ return 0;
+
+ const Resource &resource = _resources[type][name][langList[0]];
+ _exe->seek(resource.offset);
+ return _exe->readStream(resource.size);
+}
+
+SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang) {
+ if (!_exe || !_resources.contains(type))
+ return 0;
+
+ const NameMap &nameMap = _resources[type];
+
+ if (!nameMap.contains(name))
+ return 0;
+
+ const LangMap &langMap = nameMap[name];
+
+ if (!langMap.contains(lang))
+ return 0;
+
+ const Resource &resource = langMap[lang];
+ _exe->seek(resource.offset);
+ return _exe->readStream(resource.size);
+}
+
+} // End of namespace Common
diff --git a/common/winexe_pe.h b/common/winexe_pe.h
new file mode 100644
index 0000000000..5298e993ad
--- /dev/null
+++ b/common/winexe_pe.h
@@ -0,0 +1,122 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_WINEXE_PE_H
+#define COMMON_WINEXE_PE_H
+
+#include "common/array.h"
+#include "common/hashmap.h"
+#include "common/winexe.h"
+
+namespace Common {
+
+class SeekableReadStream;
+class String;
+
+/** The default Windows PE resources. */
+enum PEResourceType {
+ kPECursor = 0x01,
+ kPEBitmap = 0x02,
+ kPEIcon = 0x03,
+ kPEMenu = 0x04,
+ kPEDialog = 0x05,
+ kPEString = 0x06,
+ kPEFontDir = 0x07,
+ kPEFont = 0x08,
+ kPEAccelerator = 0x09,
+ kPERCData = 0x0A,
+ kPEMessageTable = 0x0B,
+ kPEGroupCursor = 0x0C,
+ kPEGroupIcon = 0x0E,
+ kPEVersion = 0x10,
+ kPEDlgInclude = 0x11,
+ kPEPlugPlay = 0x13,
+ kPEVXD = 0x14,
+ kPEAniCursor = 0x15,
+ kPEAniIcon = 0x16
+};
+
+/**
+ * A class able to load resources from a Windows Portable Executable, such
+ * as cursors, bitmaps, and sounds.
+ */
+class PEResources {
+public:
+ PEResources();
+ ~PEResources();
+
+ /** Clear all information. */
+ void clear();
+
+ /** Load from an EXE file. */
+ bool loadFromEXE(const String &fileName);
+
+ /** Load from a stream. */
+ bool loadFromEXE(SeekableReadStream *stream);
+
+ /** Return a list of resource types. */
+ const Array<WinResourceID> getTypeList() const;
+
+ /** Return a list of names for a given type. */
+ const Array<WinResourceID> getNameList(const WinResourceID &type) const;
+
+ /** Return a list of languages for a given type and name. */
+ const Array<WinResourceID> getLangList(const WinResourceID &type, const WinResourceID &name) const;
+
+ /** Return a stream to the specified resource, taking the first language found (or 0 if non-existent). */
+ SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &name);
+
+ /** Return a stream to the specified resource (or 0 if non-existent). */
+ SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang);
+
+private:
+ struct Section {
+ uint32 virtualAddress;
+ uint32 size;
+ uint32 offset;
+ };
+
+ HashMap<String, Section, IgnoreCase_Hash, IgnoreCase_EqualTo> _sections;
+
+ SeekableReadStream *_exe;
+
+ void parseResourceLevel(Section &section, uint32 offset, int level);
+ WinResourceID _curType, _curName, _curLang;
+
+ struct Resource {
+ uint32 offset;
+ uint32 size;
+ };
+
+ typedef HashMap<WinResourceID, Resource, WinResourceID_Hash, WinResourceID_EqualTo> LangMap;
+ typedef HashMap<WinResourceID, LangMap, WinResourceID_Hash, WinResourceID_EqualTo> NameMap;
+ typedef HashMap<WinResourceID, NameMap, WinResourceID_Hash, WinResourceID_EqualTo> TypeMap;
+
+ TypeMap _resources;
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/configure b/configure
index 3800d17fb9..64ef9efa3f 100755
--- a/configure
+++ b/configure
@@ -95,7 +95,10 @@ add_engine lastexpress "The Last Express" no
add_engine lure "Lure of the Temptress" yes
add_engine m4 "M4/MADS" no
add_engine made "MADE" yes
-add_engine mohawk "Mohawk" no
+add_engine mohawk "Mohawk" yes "cstime myst riven"
+add_engine cstime "Where in Time is Carmen Sandiego?" no
+add_engine riven "Riven: The Sequel to Myst" no
+add_engine myst "Myst" no
add_engine parallaction "Parallaction" yes
add_engine queen "Flight of the Amazon Queen" yes
add_engine saga "SAGA" yes "ihnm saga2"
@@ -216,10 +219,10 @@ cc_check_no_clean() {
echo "$CXX $LDFLAGS $CXXFLAGS $TMPC -o $TMPO$HOSTEXEEXT $@" >> "$TMPLOG"
rm -f "$TMPO$HOSTEXEEXT"
( $CXX $LDFLAGS $CXXFLAGS "$TMPC" -o "$TMPO$HOSTEXEEXT" "$@" ) >> "$TMPLOG" 2>&1
- TMP="$?"
- echo "return code: $TMP" >> "$TMPLOG"
+ TMPR="$?"
+ echo "return code: $TMPR" >> "$TMPLOG"
echo >> "$TMPLOG"
- return "$TMP"
+ return "$TMPR"
}
cc_check_clean() {
@@ -228,9 +231,9 @@ cc_check_clean() {
cc_check() {
cc_check_no_clean "$@"
- TMP="$?"
+ TMPR="$?"
cc_check_clean
- return "$TMP"
+ return "$TMPR"
}
cc_check_define() {
@@ -653,7 +656,7 @@ Configuration:
-h, --help display this help and exit
--backend=BACKEND backend to build (android, dc, dingux, ds, gp2x, gph,
iphone, linuxmoto, maemo, n64, null, openpandora, ps2,
- psp, samsungtv, sdl, symbian, wii, wince) [sdl]
+ psp, samsungtv, sdl, symbian, webos, wii, wince) [sdl]
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -696,6 +699,7 @@ Special configuration feature:
ps2 for PlayStation 2
psp for PlayStation Portable
samsungtv for Samsung TV
+ webos for HP Palm WebOS
wii for Nintendo Wii
wince for Windows CE
@@ -977,10 +981,10 @@ get_system_exe_extension $guessed_host
NATIVEEXEEXT=$_exeext
case $_host in
-android)
+android | android-v7a)
_host_os=android
_host_cpu=arm
- _host_alias=arm-oe-linux-androideabi
+ _host_alias=arm-linux-androideabi
;;
arm-riscos)
_host_os=riscos
@@ -1132,6 +1136,11 @@ samsungtv)
_host_cpu=arm
_host_alias=arm-linux-gnueabi
;;
+webos)
+ _host_os=webos
+ _host_cpu=arm
+ _host_alias=arm-none-linux-gnueabi
+ ;;
wii)
_host_os=wii
_host_cpu=ppc
@@ -1185,6 +1194,7 @@ fi
# Determine extension used for executables
#
get_system_exe_extension $_host_os
+HOSTEXEPRE=
HOSTEXEEXT=$_exeext
#
@@ -1208,6 +1218,10 @@ android)
echo "Please set ANDROID_SDK in your environment. export ANDROID_SDK=<path to Android SDK>"
exit 1
fi
+ if test -z "$ANDROID_NDK"; then
+ echo "Please set ANDROID_NDK in your environment. export ANDROID_NDK=<path to Android NDK>"
+ exit 1
+ fi
;;
ds | gamecube | wii)
if test -z "$DEVKITPRO"; then
@@ -1234,6 +1248,16 @@ psp)
exit 1
fi
;;
+webos)
+ if test -z "$WEBOS_SDK"; then
+ echo "Please set WEBOS_SDK in your environment. export WEBOS_SDK=<path to WebOS SDK>"
+ exit 1
+ fi
+ if test -z "$WEBOS_PDK"; then
+ echo "Please set WEBOS_PDK in your environment. export WEBOS_PDK=<path to WebOS PDK>"
+ exit 1
+ fi
+ ;;
*)
;;
esac
@@ -1455,21 +1479,21 @@ EOF
#
echo_n "Type with 1 byte... "
type_1_byte=`find_type_with_size 1`
-TMP="$?"
+TMPR="$?"
echo "$type_1_byte"
-test $TMP -eq 0 || exit 1 # check exit code of subshell
+test $TMPR -eq 0 || exit 1 # check exit code of subshell
echo_n "Type with 2 bytes... "
type_2_byte=`find_type_with_size 2`
-TMP="$?"
+TMPR="$?"
echo "$type_2_byte"
-test $TMP -eq 0 || exit 1 # check exit code of subshell
+test $TMPR -eq 0 || exit 1 # check exit code of subshell
echo_n "Type with 4 bytes... "
type_4_byte=`find_type_with_size 4`
-TMP="$?"
+TMPR="$?"
echo "$type_4_byte"
-test $TMP -eq 0 || exit 1 # check exit code of subshell
+test $TMPR -eq 0 || exit 1 # check exit code of subshell
#
# Check whether we can use x86 asm routines
@@ -1493,14 +1517,37 @@ echo $_host_os
case $_host_os in
amigaos*)
CXXFLAGS="$CXXFLAGS -mcrt=newlib -mstrict-align -mcpu=750 -mtune=7400"
- LDFLAGS="$LDFLAGS -mcrt=newlib -use-dynld -LSDK:Local/newib/lib"
+ LDFLAGS="$LDFLAGS -mcrt=newlib -use-dynld -L/sdk/local/newlib/lib"
# We have to use 'long' for our 4 byte typedef because AmigaOS already typedefs (u)int32
# as (unsigned) long, and consequently we'd get a compiler error otherwise.
type_4_byte='long'
add_line_to_config_mk 'AMIGAOS = 1'
;;
android)
- CXXFLAGS="$CXXFLAGS -Os -msoft-float -mtune=xscale -march=armv5te -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5TE__"
+ case $_host in
+ android)
+ CXXFLAGS="$CXXFLAGS -march=armv5te -mtune=xscale -msoft-float"
+ ;;
+ android-v7a)
+ CXXFLAGS="$CXXFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=vfp"
+ LDFLAGS="$LDFLAGS -Wl,--fix-cortex-a8"
+ ;;
+ esac
+ CXXFLAGS="$CXXFLAGS --sysroot=$ANDROID_NDK/platforms/android-4/arch-arm"
+ CXXFLAGS="$CXXFLAGS -fpic -ffunction-sections -funwind-tables"
+ if test "$_debug_build" = yes; then
+ CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer -fno-strict-aliasing"
+ else
+ CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -fstrict-aliasing"
+ fi
+ CXXFLAGS="$CXXFLAGS -finline-limit=300"
+ CXXFLAGS="$CXXFLAGS -Os -mthumb-interwork"
+ CXXFLAGS="$CXXFLAGS -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__"
+ CXXFLAGS="$CXXFLAGS -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__"
+ # supress 'mangling of 'va_list' has changed in GCC 4.4'
+ CXXFLAGS="$CXXFLAGS -Wno-psabi"
+ LDFLAGS="$LDFLAGS --sysroot=$ANDROID_NDK/platforms/android-4/arch-arm"
+ LDFLAGS="$LDFLAGS -mthumb-interwork"
add_line_to_config_mk "ANDROID_SDK = $ANDROID_SDK"
_unix=yes
_seq_midi=no
@@ -1540,9 +1587,11 @@ case $_host_os in
CXXFLAGS="$CXXFLAGS -fuse-cxa-atexit"
LDFLAGS="$LDFLAGS -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt"
if test "$_dynamic_modules" = no ; then
- LDFLAGS="$LDFLAGS -Wl,--gc-sections"
- else
- LDFLAGS="$LDFLAGS -Wl,--retain-symbols-file,ds.syms"
+ LDFLAGS="$LDFLAGS -Wl,--gc-sections"
+ else
+ LDFLAGS="$LDFLAGS -Wl,--no-gc-sections"
+ # TODO automate this required 2 step linking phase
+ # LDFLAGS="$LDFLAGS -Wl,--retain-symbols-file,ds.syms"
fi
LDFLAGS="$LDFLAGS -L$DEVKITPRO/libnds/lib"
LIBS="$LIBS -lnds9"
@@ -1568,7 +1617,6 @@ case $_host_os in
DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lnetwork for the timidity MIDI driver
LIBS="$LIBS -lnetwork"
- CXXFLAGS="$CXXFLAGS -fhuge-objects"
_unix=yes
_seq_midi=no
;;
@@ -1620,6 +1668,14 @@ case $_host_os in
LIBS="$LIBS -lnsl -lsocket"
_unix=yes
;;
+ webos)
+ LDFLAGS="$LDFLAGS -L$WEBOS_PDK/device/lib -L$WEBOS_PDK/device/usr/lib"
+ LDFLAGS="$LDFLAGS -Wl,--allow-shlib-undefined"
+ LDFLAGS="$LDFLAGS --sysroot=$WEBOS_PDK/arm-gcc/sysroot"
+ add_line_to_config_mk "WEBOS_SDK = $WEBOS_SDK"
+ _unix=yes
+ _seq_midi=no
+ ;;
wii)
CXXFLAGS="$CXXFLAGS -Os -mrvl -mcpu=750 -meabi -mhard-float"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
@@ -1633,7 +1689,7 @@ case $_host_os in
fi
;;
wince)
- CXXFLAGS="$CXXFLAGS -O3 -march=armv4 -mtune=xscale"
+ CXXFLAGS="$CXXFLAGS -O3 -fno-inline-functions -march=armv4 -mtune=xscale"
DEFINES="$DEFINES -D_WIN32_WCE=300 -D__ARM__ -D_ARM_ -DUNICODE -DFPM_DEFAULT -DNONSTANDARD_PORT"
DEFINES="$DEFINES -DWIN32 -Dcdecl= -D__cdecl__="
;;
@@ -1648,10 +1704,13 @@ if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
echo "Cross-compiling to $_host"
case "$_host" in
- android)
- DEFINES="$DEFINES -DANDROID -DUSE_ARM_SMUSH_ASM"
+ android | android-v7a)
_unix=yes
_need_memalign=yes
+ # we link a .so as default
+ LDFLAGS="$LDFLAGS -shared -Wl,-Bsymbolic,--no-undefined"
+ HOSTEXEPRE=lib
+ HOSTEXEEXT=.so
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
@@ -1659,7 +1718,10 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
_backend="android"
_port_mk="backends/platform/android/android.mk"
+ _build_scalers=no
_seq_midi=no
+ _mt32emu=no
+ _timidity=no
;;
arm-linux|arm*-linux-gnueabi|arm-*-linux)
_unix=yes
@@ -1699,9 +1761,10 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="gph"
_build_hq_scalers=no
- _mt32emu=no
_vkeybd=yes
_seq_midi=no
+ _mt32emu=no
+ _timidity=no
_port_mk="backends/platform/gph/caanoo-bundle.mk"
;;
*darwin*)
@@ -1786,12 +1849,13 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
- _backend="gp2x"
+ _backend="gph"
_build_hq_scalers=no
- _mt32emu=no
_vkeybd=yes
_seq_midi=no
- _port_mk="backends/platform/gp2x/gp2x-bundle.mk"
+ _mt32emu=no
+ _timidity=no
+ _port_mk="backends/platform/gph/gp2x-bundle.mk"
;;
gp2xwiz)
# This uses the GPH backend.
@@ -1811,9 +1875,10 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="gph"
_build_hq_scalers=no
- _mt32emu=no
_vkeybd=yes
_seq_midi=no
+ _mt32emu=no
+ _timidity=no
_port_mk="backends/platform/gph/gp2xwiz-bundle.mk"
;;
iphone)
@@ -1931,8 +1996,8 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
_backend="openpandora"
_build_hq_scalers=yes
- _mt32emu=no
_vkeybd=no
+ _mt32emu=no
_seq_midi=no
_port_mk="backends/platform/openpandora/op-bundle.mk"
;;
@@ -1992,6 +2057,23 @@ if test -n "$_host"; then
_mt32emu=no
_vkeybd=yes
;;
+ webos)
+ _unix=yes
+ _need_memalign=yes
+ add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
+ _backend="webos"
+ _port_mk="backends/platform/webos/webos.mk"
+ _build_scalers=no
+ _timidity=no
+ _mt32emu=no
+ _seq_midi=no
+ _vkeybd=no
+ _keymapper=yes
+ ;;
wii)
_endian=big
_need_memalign=yes
@@ -2078,7 +2160,7 @@ fi
# Enable 16bit support only for backends which support it
#
case $_backend in
- dingux | dreamcast | gph | openpandora | psp | samsungtv | sdl | wii)
+ android | dingux | dreamcast | gph | openpandora | psp | samsungtv | sdl | webos | wii)
if test "$_16bit" = auto ; then
_16bit=yes
else
@@ -2135,6 +2217,32 @@ _def_plugin="/* -> plugins disabled */"
if test "$_dynamic_modules" = yes ; then
echo_n "Checking whether building plugins is supported... "
case $_host_os in
+ android)
+_def_plugin='
+#define PLUGIN_PREFIX "lib"
+#define PLUGIN_SUFFIX ".so"
+'
+# Work around an Android 2.0+ run-time linker bug:
+# The linker doesn't actually look in previously
+# loaded libraries when trying to resolve symbols -
+# effectively turning all dlopen(RTLD_GLOBAL) calls
+# into dlopen(RTLD_LOCAL). It *does* look in
+# DT_NEEDED libraries, so the workaround is to add an
+# (otherwise unnecessary) dependency from plugins back
+# to the main libscummvm.so.
+_mak_plugins='
+DYNAMIC_MODULES := 1
+PLUGIN_PREFIX := lib
+PLUGIN_SUFFIX := .so
+PLUGIN_EXTRA_DEPS = libscummvm.so
+CXXFLAGS += -DDYNAMIC_MODULES
+CXXFLAGS += -fpic
+PLUGIN_LDFLAGS += $(LDFLAGS) -L. -lscummvm
+PRE_OBJS_FLAGS := -Wl,-export-dynamic -Wl,-whole-archive
+POST_OBJS_FLAGS := -Wl,-no-whole-archive
+LIBS += -ldl
+'
+ ;;
darwin*)
_def_plugin='
#define PLUGIN_PREFIX ""
@@ -2217,7 +2325,7 @@ POST_OBJS_FLAGS := -Wl,-no-whole-archive
LIBS += -ldl
'
;;
- linux*|android)
+ linux* | webos)
_def_plugin='
#define PLUGIN_PREFIX "lib"
#define PLUGIN_SUFFIX ".so"
@@ -2912,6 +3020,15 @@ fi
#
case $_backend in
android)
+ # ssp at this point so the cxxtests link
+ if test "$_debug_build" = yes; then
+ CXXFLAGS="$CXXFLAGS -fstack-protector"
+ else
+ CXXFLAGS="$CXXFLAGS -fno-stack-protector"
+ fi
+ CXXFLAGS="$CXXFLAGS -Wa,--noexecstack"
+ LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
+
static_libs=''
system_libs=''
for lib in $LIBS; do
@@ -2928,20 +3045,9 @@ case $_backend in
# -lgcc is carefully placed here - we want to catch
# all toolchain symbols in *our* libraries rather
# than pick up anything unhygenic from the Android libs.
- LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -lstdc++ -llog -lGLESv1_CM"
- DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE"
- add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic'
-
- # Work around an Android 2.0+ run-time linker bug:
- # The linker doesn't actually look in previously
- # loaded libraries when trying to resolve symbols -
- # effectively turning all dlopen(RTLD_GLOBAL) calls
- # into dlopen(RTLD_LOCAL). It *does* look in
- # DT_NEEDED libraries, so the workaround is to add an
- # (otherwise unnecessary) dependency from plugins back
- # to the main libscummvm.so.
- add_line_to_config_mk 'PLUGIN_LDFLAGS += -Lbuild.tmp -lscummvm'
- add_line_to_config_mk 'PLUGIN_EXTRA_DEPS += build.tmp/libscummvm.so'
+ LIBS="-Wl,-Bstatic $static_libs"
+ LIBS="$LIBS -Wl,-Bdynamic -lgcc $system_libs -llog -lGLESv1_CM"
+ DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE"
;;
dc)
INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc -isystem $(ronindir)/include'
@@ -3007,8 +3113,8 @@ case $_backend in
DEFINES="$DEFINES -D_EE -DFORCE_RTL"
INCLUDES="$INCLUDES -I$PS2SDK/ee/include -I$PS2SDK/common/include -I$PS2SDK/ports/include"
if test "$_dynamic_modules" = no ; then
- LDFLAGS="$LDFLAGS -mno-crt0 $PS2SDK/ee/startup/crt0.o -T $PS2SDK/ee/startup/linkfile"
- fi
+ LDFLAGS="$LDFLAGS -mno-crt0 $PS2SDK/ee/startup/crt0.o -T $PS2SDK/ee/startup/linkfile"
+ fi
LDFLAGS="$LDFLAGS -L$PS2SDK/ee/lib -L$PS2SDK/ports/lib"
LIBS="$LIBS -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lm -lc -lfileXio -lkernel -lstdc++ "
;;
@@ -3030,6 +3136,12 @@ case $_backend in
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
DEFINES="$DEFINES -DSDL_BACKEND"
;;
+ webos)
+ INCLUDES="$INCLUDES -I$WEBOS_PDK/include -I$WEBOS_PDK/include/SDL -I$WEBOS_PDK/device/usr/include"
+ LIBS="$LIBS -lSDL -lpdl"
+ DEFINES="$DEFINES -DSDL_BACKEND -DWEBOS"
+ MODULES="$MODULES backends/platform/sdl"
+ ;;
wii)
DEFINES="$DEFINES -D__WII__ -DGEKKO"
case $_host_os in
@@ -3061,7 +3173,7 @@ if test "$have_gcc" = yes ; then
case $_host_os in
# newlib-based system include files suppress non-C89 function
# declarations under __STRICT_ANSI__
- amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | wii | wince )
+ amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | wii | wince )
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
;;
*)
@@ -3223,6 +3335,7 @@ STATICLIBPATH=$_staticlibpath
BACKEND := $_backend
MODULES += $MODULES
MODULE_DIRS += $MODULE_DIRS
+EXEPRE := $HOSTEXEPRE
EXEEXT := $HOSTEXEEXT
NASM := $NASM
NASMFLAGS := $NASMFLAGS
diff --git a/tools/README b/devtools/README
index b1c0f21cb0..b1c0f21cb0 100644
--- a/tools/README
+++ b/devtools/README
diff --git a/tools/agi-palex.py b/devtools/agi-palex.py
index 1e0fa9d54f..1e0fa9d54f 100644
--- a/tools/agi-palex.py
+++ b/devtools/agi-palex.py
diff --git a/tools/construct-pred-dict.pl b/devtools/construct-pred-dict.pl
index a092429ff6..a092429ff6 100755
--- a/tools/construct-pred-dict.pl
+++ b/devtools/construct-pred-dict.pl
diff --git a/tools/convbdf.c b/devtools/convbdf.c
index fc13cff6ce..fc13cff6ce 100644
--- a/tools/convbdf.c
+++ b/devtools/convbdf.c
diff --git a/tools/create_drascula/Makefile b/devtools/create_drascula/Makefile
index 3052436b55..3052436b55 100644
--- a/tools/create_drascula/Makefile
+++ b/devtools/create_drascula/Makefile
diff --git a/tools/create_drascula/create_drascula.cpp b/devtools/create_drascula/create_drascula.cpp
index 9ea2da380a..9ea2da380a 100644
--- a/tools/create_drascula/create_drascula.cpp
+++ b/devtools/create_drascula/create_drascula.cpp
diff --git a/tools/create_drascula/create_drascula.h b/devtools/create_drascula/create_drascula.h
index 13903e9564..13903e9564 100644
--- a/tools/create_drascula/create_drascula.h
+++ b/devtools/create_drascula/create_drascula.h
diff --git a/tools/create_drascula/dists/msvc8/create_drascula.sln b/devtools/create_drascula/dists/msvc8/create_drascula.sln
index dc7428bb80..dc7428bb80 100644
--- a/tools/create_drascula/dists/msvc8/create_drascula.sln
+++ b/devtools/create_drascula/dists/msvc8/create_drascula.sln
diff --git a/tools/create_drascula/dists/msvc8/create_drascula.vcproj b/devtools/create_drascula/dists/msvc8/create_drascula.vcproj
index 3b26261a76..3b26261a76 100644
--- a/tools/create_drascula/dists/msvc8/create_drascula.vcproj
+++ b/devtools/create_drascula/dists/msvc8/create_drascula.vcproj
diff --git a/tools/create_drascula/dists/msvc8_to_msvc9.bat b/devtools/create_drascula/dists/msvc8_to_msvc9.bat
index 54820b34d0..54820b34d0 100644
--- a/tools/create_drascula/dists/msvc8_to_msvc9.bat
+++ b/devtools/create_drascula/dists/msvc8_to_msvc9.bat
diff --git a/tools/create_drascula/dists/msvc9/create_drascula.sln b/devtools/create_drascula/dists/msvc9/create_drascula.sln
index 4a39bdbe42..4a39bdbe42 100644
--- a/tools/create_drascula/dists/msvc9/create_drascula.sln
+++ b/devtools/create_drascula/dists/msvc9/create_drascula.sln
diff --git a/tools/create_drascula/dists/msvc9/create_drascula.vcproj b/devtools/create_drascula/dists/msvc9/create_drascula.vcproj
index f30d6a114b..f30d6a114b 100644
--- a/tools/create_drascula/dists/msvc9/create_drascula.vcproj
+++ b/devtools/create_drascula/dists/msvc9/create_drascula.vcproj
diff --git a/tools/create_drascula/dists/msvc9_to_msvc8.bat b/devtools/create_drascula/dists/msvc9_to_msvc8.bat
index c87a524f77..c87a524f77 100644
--- a/tools/create_drascula/dists/msvc9_to_msvc8.bat
+++ b/devtools/create_drascula/dists/msvc9_to_msvc8.bat
diff --git a/tools/create_drascula/module.mk b/devtools/create_drascula/module.mk
index 3d64871960..b5a32d8d00 100644
--- a/tools/create_drascula/module.mk
+++ b/devtools/create_drascula/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/create_drascula
+MODULE := devtools/create_drascula
MODULE_OBJS := \
create_drascula.o
diff --git a/tools/create_drascula/staticdata.h b/devtools/create_drascula/staticdata.h
index 51ed995884..51ed995884 100644
--- a/tools/create_drascula/staticdata.h
+++ b/devtools/create_drascula/staticdata.h
diff --git a/tools/create_hugo/Data/Btn_1.bmp b/devtools/create_hugo/Data/Btn_1.bmp
index 0cdfc91fd3..0cdfc91fd3 100644
--- a/tools/create_hugo/Data/Btn_1.bmp
+++ b/devtools/create_hugo/Data/Btn_1.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_1_off.bmp b/devtools/create_hugo/Data/Btn_1_off.bmp
index eb6146ac96..eb6146ac96 100644
--- a/tools/create_hugo/Data/Btn_1_off.bmp
+++ b/devtools/create_hugo/Data/Btn_1_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_2.bmp b/devtools/create_hugo/Data/Btn_2.bmp
index 971c996b4d..971c996b4d 100644
--- a/tools/create_hugo/Data/Btn_2.bmp
+++ b/devtools/create_hugo/Data/Btn_2.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_2_off.bmp b/devtools/create_hugo/Data/Btn_2_off.bmp
index 988c682b44..988c682b44 100644
--- a/tools/create_hugo/Data/Btn_2_off.bmp
+++ b/devtools/create_hugo/Data/Btn_2_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_3.bmp b/devtools/create_hugo/Data/Btn_3.bmp
index ac988d8a90..ac988d8a90 100644
--- a/tools/create_hugo/Data/Btn_3.bmp
+++ b/devtools/create_hugo/Data/Btn_3.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_3_off.bmp b/devtools/create_hugo/Data/Btn_3_off.bmp
index 14df72666b..14df72666b 100644
--- a/tools/create_hugo/Data/Btn_3_off.bmp
+++ b/devtools/create_hugo/Data/Btn_3_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_4.bmp b/devtools/create_hugo/Data/Btn_4.bmp
index ef47589044..ef47589044 100644
--- a/tools/create_hugo/Data/Btn_4.bmp
+++ b/devtools/create_hugo/Data/Btn_4.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_4_off.bmp b/devtools/create_hugo/Data/Btn_4_off.bmp
index d32f497d6c..d32f497d6c 100644
--- a/tools/create_hugo/Data/Btn_4_off.bmp
+++ b/devtools/create_hugo/Data/Btn_4_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_5.bmp b/devtools/create_hugo/Data/Btn_5.bmp
index 3eb03b20d6..3eb03b20d6 100644
--- a/tools/create_hugo/Data/Btn_5.bmp
+++ b/devtools/create_hugo/Data/Btn_5.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_5_off.bmp b/devtools/create_hugo/Data/Btn_5_off.bmp
index 6513ff2080..6513ff2080 100644
--- a/tools/create_hugo/Data/Btn_5_off.bmp
+++ b/devtools/create_hugo/Data/Btn_5_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_6.bmp b/devtools/create_hugo/Data/Btn_6.bmp
index d53585dde7..d53585dde7 100644
--- a/tools/create_hugo/Data/Btn_6.bmp
+++ b/devtools/create_hugo/Data/Btn_6.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_6_off.bmp b/devtools/create_hugo/Data/Btn_6_off.bmp
index 8748fa0ff2..8748fa0ff2 100644
--- a/tools/create_hugo/Data/Btn_6_off.bmp
+++ b/devtools/create_hugo/Data/Btn_6_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_7.bmp b/devtools/create_hugo/Data/Btn_7.bmp
index 25ba757e93..25ba757e93 100644
--- a/tools/create_hugo/Data/Btn_7.bmp
+++ b/devtools/create_hugo/Data/Btn_7.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_7_off.bmp b/devtools/create_hugo/Data/Btn_7_off.bmp
index 6fe8cff904..6fe8cff904 100644
--- a/tools/create_hugo/Data/Btn_7_off.bmp
+++ b/devtools/create_hugo/Data/Btn_7_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_8.bmp b/devtools/create_hugo/Data/Btn_8.bmp
index d3a92fccac..d3a92fccac 100644
--- a/tools/create_hugo/Data/Btn_8.bmp
+++ b/devtools/create_hugo/Data/Btn_8.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_8_off.bmp b/devtools/create_hugo/Data/Btn_8_off.bmp
index 7fb40a42b4..7fb40a42b4 100644
--- a/tools/create_hugo/Data/Btn_8_off.bmp
+++ b/devtools/create_hugo/Data/Btn_8_off.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_9.bmp b/devtools/create_hugo/Data/Btn_9.bmp
index 6443649b20..6443649b20 100644
--- a/tools/create_hugo/Data/Btn_9.bmp
+++ b/devtools/create_hugo/Data/Btn_9.bmp
Binary files differ
diff --git a/tools/create_hugo/Data/Btn_9_off.bmp b/devtools/create_hugo/Data/Btn_9_off.bmp
index a9ce9dcddb..a9ce9dcddb 100644
--- a/tools/create_hugo/Data/Btn_9_off.bmp
+++ b/devtools/create_hugo/Data/Btn_9_off.bmp
Binary files differ
diff --git a/tools/create_hugo/README b/devtools/create_hugo/README
index 42bdd22c36..42bdd22c36 100644
--- a/tools/create_hugo/README
+++ b/devtools/create_hugo/README
diff --git a/tools/create_hugo/create_hugo.cpp b/devtools/create_hugo/create_hugo.cpp
index 01b6d915f0..1dffa0edf1 100644
--- a/tools/create_hugo/create_hugo.cpp
+++ b/devtools/create_hugo/create_hugo.cpp
@@ -103,6 +103,29 @@ int main(int argc, char *argv[]) {
writeByte(outFile, _palette[i]);
}
+ // The following fonts info have been added to avoid temporarly the .FON
+ // used in the DOS version
+ // font5
+ nbrElem = sizeof(font5) / sizeof(byte);
+ writeUint16BE(outFile, nbrElem);
+
+ for (int j = 0; j < nbrElem; j++)
+ writeByte(outFile, font5[j]);
+
+ // font6
+ nbrElem = sizeof(font6) / sizeof(byte);
+ writeUint16BE(outFile, nbrElem);
+
+ for (int j = 0; j < nbrElem; j++)
+ writeByte(outFile, font6[j]);
+
+ // font8
+ nbrElem = sizeof(font8) / sizeof(byte);
+ writeUint16BE(outFile, nbrElem);
+
+ for (int j = 0; j < nbrElem; j++)
+ writeByte(outFile, font8[j]);
+
// Write textData
// textData_1w
nbrElem = sizeof(textData_1w) / sizeof(char *);
@@ -396,6 +419,114 @@ int main(int argc, char *argv[]) {
nbrElem = sizeof(arrayReqs_3d) / sizeof(uint16 *);
writeUint16Array(outFile, arrayReqs_3d, nbrElem);
+ // catchall_1w
+ nbrElem = sizeof(catchall_1w) / sizeof(background_t);
+ writeBackgroundArray(outFile, catchall_1w, nbrElem);
+
+ // catchall_2w
+ nbrElem = sizeof(catchall_2w) / sizeof(background_t);
+ writeBackgroundArray(outFile, catchall_2w, nbrElem);
+
+ // catchall_3w
+ nbrElem = sizeof(catchall_3w) / sizeof(background_t);
+ writeBackgroundArray(outFile, catchall_3w, nbrElem);
+
+ // catchall_1d
+ nbrElem = sizeof(catchall_1d) / sizeof(background_t);
+ writeBackgroundArray(outFile, catchall_1d, nbrElem);
+
+ // catchall_2d
+ nbrElem = sizeof(catchall_2d) / sizeof(background_t);
+ writeBackgroundArray(outFile, catchall_2d, nbrElem);
+
+ // catchall_3d
+ nbrElem = sizeof(catchall_3d) / sizeof(background_t);
+ writeBackgroundArray(outFile, catchall_3d, nbrElem);
+
+ // backgroundList_1w
+ nbrElem = sizeof(backgroundList_1w) / sizeof(background_t *);
+ writeUint16BE(outFile, nbrElem);
+ for (int j = 0; j < nbrElem; j++) {
+ nbrSubElem = 1;
+ for (int k = 0; backgroundList_1w[j][k].verbIndex != 0; k++)
+ nbrSubElem ++;
+ writeBackgroundArray(outFile, backgroundList_1w[j], nbrSubElem);
+ }
+
+ // backgroundList_2w
+ nbrElem = sizeof(backgroundList_2w) / sizeof(background_t *);
+ writeUint16BE(outFile, nbrElem);
+ for (int j = 0; j < nbrElem; j++) {
+ nbrSubElem = 1;
+ for (int k = 0; backgroundList_2w[j][k].verbIndex != 0; k++)
+ nbrSubElem ++;
+ writeBackgroundArray(outFile, backgroundList_2w[j], nbrSubElem);
+ }
+
+ // backgroundList_3w
+ nbrElem = sizeof(backgroundList_3w) / sizeof(background_t *);
+ writeUint16BE(outFile, nbrElem);
+ for (int j = 0; j < nbrElem; j++) {
+ nbrSubElem = 1;
+ for (int k = 0; backgroundList_3w[j][k].verbIndex != 0; k++)
+ nbrSubElem ++;
+ writeBackgroundArray(outFile, backgroundList_3w[j], nbrSubElem);
+ }
+
+ // backgroundList_1d
+ nbrElem = sizeof(backgroundList_1d) / sizeof(background_t *);
+ writeUint16BE(outFile, nbrElem);
+ for (int j = 0; j < nbrElem; j++) {
+ nbrSubElem = 1;
+ for (int k = 0; backgroundList_1d[j][k].verbIndex != 0; k++)
+ nbrSubElem ++;
+ writeBackgroundArray(outFile, backgroundList_1d[j], nbrSubElem);
+ }
+
+ // backgroundList_2d
+ nbrElem = sizeof(backgroundList_2d) / sizeof(background_t *);
+ writeUint16BE(outFile, nbrElem);
+ for (int j = 0; j < nbrElem; j++) {
+ nbrSubElem = 1;
+ for (int k = 0; backgroundList_2d[j][k].verbIndex != 0; k++)
+ nbrSubElem ++;
+ writeBackgroundArray(outFile, backgroundList_2d[j], nbrSubElem);
+ }
+
+ // backgroundList_3d
+ nbrElem = sizeof(backgroundList_3d) / sizeof(background_t *);
+ writeUint16BE(outFile, nbrElem);
+ for (int j = 0; j < nbrElem; j++) {
+ nbrSubElem = 1;
+ for (int k = 0; backgroundList_3d[j][k].verbIndex != 0; k++)
+ nbrSubElem ++;
+ writeBackgroundArray(outFile, backgroundList_3d[j], nbrSubElem);
+ }
+
+ // cmdList_1w
+ nbrElem = sizeof(cmdList_1w) / sizeof(cmd **);
+ writeCmdArray(outFile, cmdList_1w, nbrElem);
+
+ // cmdList_2w
+ nbrElem = sizeof(cmdList_2w) / sizeof(cmd **);
+ writeCmdArray(outFile, cmdList_2w, nbrElem);
+
+ // cmdList_3w
+ nbrElem = sizeof(cmdList_3w) / sizeof(cmd **);
+ writeCmdArray(outFile, cmdList_3w, nbrElem);
+
+ // cmdList_1d
+ nbrElem = sizeof(cmdList_1d) / sizeof(cmd **);
+ writeCmdArray(outFile, cmdList_1d, nbrElem);
+
+ // cmdList_2d
+ nbrElem = sizeof(cmdList_2d) / sizeof(cmd **);
+ writeCmdArray(outFile, cmdList_2d, nbrElem);
+
+ // cmdList_3d
+ nbrElem = sizeof(cmdList_3d) / sizeof(cmd **);
+ writeCmdArray(outFile, cmdList_3d, nbrElem);
+
// hotspots_1w
nbrElem = sizeof(hotspots_1w) / sizeof(hotspot_t);
writeHotspot(outFile, hotspots_1w, nbrElem);
@@ -486,89 +617,37 @@ int main(int argc, char *argv[]) {
nbrElem = sizeof(uses_3d) / sizeof(uses_t);
writeUseArray(outFile, uses_3d, nbrElem);
- // catchall_1w
- nbrElem = sizeof(catchall_1w) / sizeof(background_t);
- writeBackgroundArray(outFile, catchall_1w, nbrElem);
-
- // catchall_2w
- nbrElem = sizeof(catchall_2w) / sizeof(background_t);
- writeBackgroundArray(outFile, catchall_2w, nbrElem);
-
- // catchall_3w
- nbrElem = sizeof(catchall_3w) / sizeof(background_t);
- writeBackgroundArray(outFile, catchall_3w, nbrElem);
-
- // catchall_1d
- nbrElem = sizeof(catchall_1d) / sizeof(background_t);
- writeBackgroundArray(outFile, catchall_1d, nbrElem);
-
- // catchall_2d
- nbrElem = sizeof(catchall_2d) / sizeof(background_t);
- writeBackgroundArray(outFile, catchall_2d, nbrElem);
-
- // catchall_3d
- nbrElem = sizeof(catchall_3d) / sizeof(background_t);
- writeBackgroundArray(outFile, catchall_3d, nbrElem);
+ // objects_1w
+ nbrElem = sizeof(objects_1w) / sizeof(object_t);
+ writeObjectArray(outFile, objects_1w, nbrElem);
- // backgroundList_1w
- nbrElem = sizeof(backgroundList_1w) / sizeof(background_t *);
- writeUint16BE(outFile, nbrElem);
- for (int j = 0; j < nbrElem; j++) {
- nbrSubElem = 1;
- for (int k = 0; backgroundList_1w[j][k].verbIndex != 0; k++)
- nbrSubElem ++;
- writeBackgroundArray(outFile, backgroundList_1w[j], nbrSubElem);
- }
+ // objects_2w
+ nbrElem = sizeof(objects_2w) / sizeof(object_t);
+ writeObjectArray(outFile, objects_2w, nbrElem);
- // backgroundList_2w
- nbrElem = sizeof(backgroundList_2w) / sizeof(background_t *);
- writeUint16BE(outFile, nbrElem);
- for (int j = 0; j < nbrElem; j++) {
- nbrSubElem = 1;
- for (int k = 0; backgroundList_2w[j][k].verbIndex != 0; k++)
- nbrSubElem ++;
- writeBackgroundArray(outFile, backgroundList_2w[j], nbrSubElem);
- }
+ // objects_3w
+ nbrElem = sizeof(objects_3w) / sizeof(object_t);
+ writeObjectArray(outFile, objects_3w, nbrElem);
- // backgroundList_3w
- nbrElem = sizeof(backgroundList_3w) / sizeof(background_t *);
- writeUint16BE(outFile, nbrElem);
- for (int j = 0; j < nbrElem; j++) {
- nbrSubElem = 1;
- for (int k = 0; backgroundList_3w[j][k].verbIndex != 0; k++)
- nbrSubElem ++;
- writeBackgroundArray(outFile, backgroundList_3w[j], nbrSubElem);
- }
+ // objects_1d
+ nbrElem = sizeof(objects_1d) / sizeof(object_t);
+ writeObjectArray(outFile, objects_1d, nbrElem);
- // backgroundList_1d
- nbrElem = sizeof(backgroundList_1d) / sizeof(background_t *);
- writeUint16BE(outFile, nbrElem);
- for (int j = 0; j < nbrElem; j++) {
- nbrSubElem = 1;
- for (int k = 0; backgroundList_1d[j][k].verbIndex != 0; k++)
- nbrSubElem ++;
- writeBackgroundArray(outFile, backgroundList_1d[j], nbrSubElem);
- }
+ // objects_2d
+ nbrElem = sizeof(objects_2d) / sizeof(object_t);
+ writeObjectArray(outFile, objects_2d, nbrElem);
- // backgroundList_2d
- nbrElem = sizeof(backgroundList_2d) / sizeof(background_t *);
- writeUint16BE(outFile, nbrElem);
- for (int j = 0; j < nbrElem; j++) {
- nbrSubElem = 1;
- for (int k = 0; backgroundList_2d[j][k].verbIndex != 0; k++)
- nbrSubElem ++;
- writeBackgroundArray(outFile, backgroundList_2d[j], nbrSubElem);
- }
+ // objects_3d
+ nbrElem = sizeof(objects_3d) / sizeof(object_t);
+ writeObjectArray(outFile, objects_3d, nbrElem);
- // backgroundList_3d
- nbrElem = sizeof(backgroundList_3d) / sizeof(background_t *);
- writeUint16BE(outFile, nbrElem);
- for (int j = 0; j < nbrElem; j++) {
- nbrSubElem = 1;
- for (int k = 0; backgroundList_3d[j][k].verbIndex != 0; k++)
- nbrSubElem ++;
- writeBackgroundArray(outFile, backgroundList_3d[j], nbrSubElem);
- }
+ // Save LASTOBJ
+ writeUint16BE(outFile, LASTOBJ_1w);
+ writeUint16BE(outFile, LASTOBJ_2w);
+ writeUint16BE(outFile, LASTOBJ_3w);
+ writeUint16BE(outFile, LASTOBJ_1d); //(not set in original, as Hugo1 DOS doesn't use a DAT file to pack the screens)
+ writeUint16BE(outFile, LASTOBJ_2d);
+ writeUint16BE(outFile, LASTOBJ_3d);
// points_1w
nbrElem = sizeof(points_1w) / sizeof(byte);
@@ -612,30 +691,6 @@ int main(int argc, char *argv[]) {
for (int j = 0; j < nbrElem; j++)
writeByte(outFile, points_3d[j]);
- // cmdList_1w
- nbrElem = sizeof(cmdList_1w) / sizeof(cmd **);
- writeCmdArray(outFile, cmdList_1w, nbrElem);
-
- // cmdList_2w
- nbrElem = sizeof(cmdList_2w) / sizeof(cmd **);
- writeCmdArray(outFile, cmdList_2w, nbrElem);
-
- // cmdList_3w
- nbrElem = sizeof(cmdList_3w) / sizeof(cmd **);
- writeCmdArray(outFile, cmdList_3w, nbrElem);
-
- // cmdList_1d
- nbrElem = sizeof(cmdList_1d) / sizeof(cmd **);
- writeCmdArray(outFile, cmdList_1d, nbrElem);
-
- // cmdList_2d
- nbrElem = sizeof(cmdList_2d) / sizeof(cmd **);
- writeCmdArray(outFile, cmdList_2d, nbrElem);
-
- // cmdList_3d
- nbrElem = sizeof(cmdList_3d) / sizeof(cmd **);
- writeCmdArray(outFile, cmdList_3d, nbrElem);
-
// screenActs_1w
nbrElem = sizeof(screenActs_1w) / sizeof(uint16 *);
writeScreenActs(outFile, screenActs_1w, nbrElem);
@@ -660,30 +715,6 @@ int main(int argc, char *argv[]) {
nbrElem = sizeof(screenActs_3d) / sizeof(uint16 *);
writeScreenActs(outFile, screenActs_3d, nbrElem);
- // objects_1w
- nbrElem = sizeof(objects_1w) / sizeof(object_t);
- writeObjectArray(outFile, objects_1w, nbrElem);
-
- // objects_2w
- nbrElem = sizeof(objects_2w) / sizeof(object_t);
- writeObjectArray(outFile, objects_2w, nbrElem);
-
- // objects_3w
- nbrElem = sizeof(objects_3w) / sizeof(object_t);
- writeObjectArray(outFile, objects_3w, nbrElem);
-
- // objects_1d
- nbrElem = sizeof(objects_1d) / sizeof(object_t);
- writeObjectArray(outFile, objects_1d, nbrElem);
-
- // objects_2d
- nbrElem = sizeof(objects_2d) / sizeof(object_t);
- writeObjectArray(outFile, objects_2d, nbrElem);
-
- // objects_3d
- nbrElem = sizeof(objects_3d) / sizeof(object_t);
- writeObjectArray(outFile, objects_3d, nbrElem);
-
// actlistArr_1w
nbrElem = sizeof(actListArr_1w) / sizeof(actList);
writeActListArray(outFile, actListArr_1w, nbrElem);
@@ -708,6 +739,14 @@ int main(int argc, char *argv[]) {
nbrElem = sizeof(actListArr_3d) / sizeof(actList);
writeActListArray(outFile, actListArr_3d, nbrElem);
+ // Maze ALnewscr
+ writeUint16BE(outFile, 0);
+ writeUint16BE(outFile, kALnewscr_2w);
+ writeUint16BE(outFile, 0);
+ writeUint16BE(outFile, 0);
+ writeUint16BE(outFile, kALnewscr_2d);
+ writeUint16BE(outFile, 0);
+
writeSByte(outFile, NUM_TUNES_1w);
writeSByte(outFile, SILENCE_1w);
writeSByte(outFile, TEST_SOUND_1w);
@@ -808,22 +847,6 @@ int main(int argc, char *argv[]) {
writeUint16BE(outFile, kVTake_3d);
writeUint16BE(outFile, kVDrop_3d);
- // Save LASTOBJ
- writeUint16BE(outFile, LASTOBJ_1w);
- writeUint16BE(outFile, LASTOBJ_2w);
- writeUint16BE(outFile, LASTOBJ_3w);
- writeUint16BE(outFile, LASTOBJ_1d); //(not set in original, as Hugo1 DOS doesn't use a DAT file to pack the screens)
- writeUint16BE(outFile, LASTOBJ_2d);
- writeUint16BE(outFile, LASTOBJ_3d);
-
- // Maze ALnewscr
- writeUint16BE(outFile, 0);
- writeUint16BE(outFile, kALnewscr_2w);
- writeUint16BE(outFile, 0);
- writeUint16BE(outFile, 0);
- writeUint16BE(outFile, kALnewscr_2d);
- writeUint16BE(outFile, 0);
-
// DOS Intro music
// Win version do not use it
// H1 Dos doesn't have an intro
@@ -835,29 +858,6 @@ int main(int argc, char *argv[]) {
writeUint16BE(outFile, 0);
writeUint16BE(outFile, kDTsong11_3d);
- // The following fonts info have been added to avoid temporarly the .FON
- // used in the DOS version
- // font5
- nbrElem = sizeof(font5) / sizeof(byte);
- writeUint16BE(outFile, nbrElem);
-
- for (int j = 0; j < nbrElem; j++)
- writeByte(outFile, font5[j]);
-
- // font6
- nbrElem = sizeof(font6) / sizeof(byte);
- writeUint16BE(outFile, nbrElem);
-
- for (int j = 0; j < nbrElem; j++)
- writeByte(outFile, font6[j]);
-
- // font8
- nbrElem = sizeof(font8) / sizeof(byte);
- writeUint16BE(outFile, nbrElem);
-
- for (int j = 0; j < nbrElem; j++)
- writeByte(outFile, font8[j]);
-
//bitmap images for menu
writeUint16BE(outFile, 18);
diff --git a/tools/create_hugo/create_hugo.h b/devtools/create_hugo/create_hugo.h
index 7fb5d761ba..f30c186877 100644
--- a/tools/create_hugo/create_hugo.h
+++ b/devtools/create_hugo/create_hugo.h
@@ -31,7 +31,7 @@
#define DATAALIGNMENT 4
#define HUGO_DAT_VER_MAJ 0 // 1 byte
-#define HUGO_DAT_VER_MIN 41 // 1 byte
+#define HUGO_DAT_VER_MIN 42 // 1 byte
typedef unsigned char uint8;
typedef unsigned char byte;
diff --git a/tools/create_hugo/dists/msvc10/create_hugo.sln b/devtools/create_hugo/dists/msvc10/create_hugo.sln
index a6f87198f6..a6f87198f6 100644
--- a/tools/create_hugo/dists/msvc10/create_hugo.sln
+++ b/devtools/create_hugo/dists/msvc10/create_hugo.sln
diff --git a/tools/create_hugo/dists/msvc10/create_hugo.vcxproj b/devtools/create_hugo/dists/msvc10/create_hugo.vcxproj
index eae5fbc55c..eae5fbc55c 100644
--- a/tools/create_hugo/dists/msvc10/create_hugo.vcxproj
+++ b/devtools/create_hugo/dists/msvc10/create_hugo.vcxproj
diff --git a/tools/create_hugo/dists/msvc9/create_hugo.sln b/devtools/create_hugo/dists/msvc9/create_hugo.sln
index 2d86ae4f19..2d86ae4f19 100644
--- a/tools/create_hugo/dists/msvc9/create_hugo.sln
+++ b/devtools/create_hugo/dists/msvc9/create_hugo.sln
diff --git a/tools/create_hugo/dists/msvc9/create_hugo.vcproj b/devtools/create_hugo/dists/msvc9/create_hugo.vcproj
index 473d89e43c..473d89e43c 100644
--- a/tools/create_hugo/dists/msvc9/create_hugo.vcproj
+++ b/devtools/create_hugo/dists/msvc9/create_hugo.vcproj
diff --git a/tools/create_hugo/enums.h b/devtools/create_hugo/enums.h
index 90cb1d54f3..90cb1d54f3 100644
--- a/tools/create_hugo/enums.h
+++ b/devtools/create_hugo/enums.h
diff --git a/tools/create_hugo/module.mk b/devtools/create_hugo/module.mk
index 797ff3a1a0..ad7e833972 100644
--- a/tools/create_hugo/module.mk
+++ b/devtools/create_hugo/module.mk
@@ -1,4 +1,4 @@
-MODULE := tools/create_hugo
+MODULE := devtools/create_hugo
MODULE_OBJS := \
create_hugo.o
diff --git a/tools/create_hugo/staticdata.h b/devtools/create_hugo/staticdata.h
index c12191c11d..c12191c11d 100644
--- a/tools/create_hugo/staticdata.h
+++ b/devtools/create_hugo/staticdata.h
diff --git a/tools/create_hugo/staticdisplay.h b/devtools/create_hugo/staticdisplay.h
index a9f38ba7a0..790bf74d3b 100644
--- a/tools/create_hugo/staticdisplay.h
+++ b/devtools/create_hugo/staticdisplay.h
@@ -33,7 +33,7 @@
#ifndef STATICDISPLAY_H
#define STATICDISPLAY_H
-#define SIZE_PAL_ARRAY 64
+#define SIZE_PAL_ARRAY 3*16
#if 1
// Color table of standard 16 VGA colors
@@ -45,22 +45,22 @@
byte _palette[SIZE_PAL_ARRAY] = {
- 0, 0, 0, 0, // BLACK
- 0, 0, V1, 0, // BLUE
- 0, V1, 0, 0, // GREEN
- 0, V1, V1, 0, // CYAN
- V1, 0, 0, 0, // RED
- V1, 0, V1, 0, // MAGENTA
- V1, V3, 0, 0, // BROWN
- V1, V1, V1, 0, // WHITE (LIGHT GRAY)
- V3, V3, V3, 0, // GRAY (DARK GRAY)
- V4, V4, V2, 0, // LIGHTBLUE
- V4, V2, V4, 0, // LIGHTGREEN
- V4, V2, V2, 0, // LIGHTCYAN
- V2, V4, V4, 0, // LIGHTRED
- V2, V4, V2, 0, // LIGHTMAGENTA
- V2, V2, V4, 0, // YELLOW
- V2, V2, V2, 0 // BRIGHTWHITE
+ 0, 0, 0, // BLACK
+ 0, 0, V1, // BLUE
+ 0, V1, 0, // GREEN
+ 0, V1, V1, // CYAN
+ V1, 0, 0, // RED
+ V1, 0, V1, // MAGENTA
+ V1, V3, 0, // BROWN
+ V1, V1, V1, // WHITE (LIGHT GRAY)
+ V3, V3, V3, // GRAY (DARK GRAY)
+ V4, V4, V2, // LIGHTBLUE
+ V4, V2, V4, // LIGHTGREEN
+ V4, V2, V2, // LIGHTCYAN
+ V2, V4, V4, // LIGHTRED
+ V2, V4, V2, // LIGHTMAGENTA
+ V2, V2, V4, // YELLOW
+ V2, V2, V2 // BRIGHTWHITE
};
#else
// Original paletter found in original exe.
@@ -70,22 +70,22 @@ byte _palette[SIZE_PAL_ARRAY] = {
#define C2 255 // High intensity value
#define C3 127 // Special for Brown/Gray
byte _palette[SIZE_PAL_ARRAY] = {
- 0, 0, 0, 0, // BLACK
- 0, 0, C1, 0, // BLUE
- 0, C1, 0, 0, // GREEN
- 0, C1, C1, 0, // CYAN
- C1, 0, 0, 0, // RED
- C1, 0, C1, 0, // MAGENTA
- C3, C3, 0, 0, // BROWN
- C1, C1, C1, 0, // WHITE (LIGHT GRAY)
- C3, C3, C3, 0, // GRAY (DARK GRAY)
- 0, 0, C2, 0, // LIGHTBLUE
- 0, C2, 0, 0, // LIGHTGREEN
- 0, C2, C2, 0, // LIGHTCYAN
- C2, 0, 0, 0, // LIGHTRED
- C2, 0, C2, 0, // LIGHTMAGENTA
- C2, C2, 0, 0, // YELLOW
- C2, C2, C2, 0 // BRIGHTWHITE
+ 0, 0, 0, // BLACK
+ 0, 0, C1, // BLUE
+ 0, C1, 0, // GREEN
+ 0, C1, C1, // CYAN
+ C1, 0, 0, // RED
+ C1, 0, C1, // MAGENTA
+ C3, C3, 0, // BROWN
+ C1, C1, C1, // WHITE (LIGHT GRAY)
+ C3, C3, C3, // GRAY (DARK GRAY)
+ 0, 0, C2, // LIGHTBLUE
+ 0, C2, 0, // LIGHTGREEN
+ 0, C2, C2, // LIGHTCYAN
+ C2, 0, 0, // LIGHTRED
+ C2, 0, C2, // LIGHTMAGENTA
+ C2, C2, 0, // YELLOW
+ C2, C2, C2 // BRIGHTWHITE
};
#endif
diff --git a/tools/create_hugo/staticengine.h b/devtools/create_hugo/staticengine.h
index 362100b8f0..362100b8f0 100644
--- a/tools/create_hugo/staticengine.h
+++ b/devtools/create_hugo/staticengine.h
diff --git a/tools/create_hugo/staticfont.h b/devtools/create_hugo/staticfont.h
index c5700cdf58..c5700cdf58 100644
--- a/tools/create_hugo/staticfont.h
+++ b/devtools/create_hugo/staticfont.h
diff --git a/tools/create_hugo/staticintro.h b/devtools/create_hugo/staticintro.h
index 2fe18b8231..2fe18b8231 100644
--- a/tools/create_hugo/staticintro.h
+++ b/devtools/create_hugo/staticintro.h
diff --git a/tools/create_hugo/staticmouse.h b/devtools/create_hugo/staticmouse.h
index 2d4987a30c..2d4987a30c 100644
--- a/tools/create_hugo/staticmouse.h
+++ b/devtools/create_hugo/staticmouse.h
diff --git a/tools/create_hugo/staticparser.h b/devtools/create_hugo/staticparser.h
index 9e67e98c26..9e67e98c26 100644
--- a/tools/create_hugo/staticparser.h
+++ b/devtools/create_hugo/staticparser.h
diff --git a/tools/create_hugo/staticutil.h b/devtools/create_hugo/staticutil.h
index 050655a4de..050655a4de 100644
--- a/tools/create_hugo/staticutil.h
+++ b/devtools/create_hugo/staticutil.h
diff --git a/tools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp
index 7a4b8d73a1..7a4b8d73a1 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/devtools/create_kyradat/create_kyradat.cpp
diff --git a/tools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h
index d82e16fed0..d82e16fed0 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/devtools/create_kyradat/create_kyradat.h
diff --git a/tools/create_kyradat/extract.cpp b/devtools/create_kyradat/extract.cpp
index 6b801d14f9..6b801d14f9 100644
--- a/tools/create_kyradat/extract.cpp
+++ b/devtools/create_kyradat/extract.cpp
diff --git a/tools/create_kyradat/extract.h b/devtools/create_kyradat/extract.h
index 0903852dd2..0903852dd2 100644
--- a/tools/create_kyradat/extract.h
+++ b/devtools/create_kyradat/extract.h
diff --git a/tools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp
index 75a956cab0..75a956cab0 100644
--- a/tools/create_kyradat/games.cpp
+++ b/devtools/create_kyradat/games.cpp
diff --git a/tools/create_kyradat/md5.cpp b/devtools/create_kyradat/md5.cpp
index 214b5ef7ed..214b5ef7ed 100644
--- a/tools/create_kyradat/md5.cpp
+++ b/devtools/create_kyradat/md5.cpp
diff --git a/tools/create_kyradat/md5.h b/devtools/create_kyradat/md5.h
index dd50efece8..dd50efece8 100644
--- a/tools/create_kyradat/md5.h
+++ b/devtools/create_kyradat/md5.h
diff --git a/tools/create_kyradat/module.mk b/devtools/create_kyradat/module.mk
index b10dbb33cb..60cd1f8578 100644
--- a/tools/create_kyradat/module.mk
+++ b/devtools/create_kyradat/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/create_kyradat
+MODULE := devtools/create_kyradat
MODULE_OBJS := \
create_kyradat.o \
diff --git a/tools/create_kyradat/pak.cpp b/devtools/create_kyradat/pak.cpp
index 4179f42df0..4179f42df0 100644
--- a/tools/create_kyradat/pak.cpp
+++ b/devtools/create_kyradat/pak.cpp
diff --git a/tools/create_kyradat/pak.h b/devtools/create_kyradat/pak.h
index ee6dabb672..ee6dabb672 100644
--- a/tools/create_kyradat/pak.h
+++ b/devtools/create_kyradat/pak.h
diff --git a/tools/create_kyradat/search.cpp b/devtools/create_kyradat/search.cpp
index 28631fa652..28631fa652 100644
--- a/tools/create_kyradat/search.cpp
+++ b/devtools/create_kyradat/search.cpp
diff --git a/tools/create_kyradat/search.h b/devtools/create_kyradat/search.h
index 6459606ef8..6459606ef8 100644
--- a/tools/create_kyradat/search.h
+++ b/devtools/create_kyradat/search.h
diff --git a/tools/create_kyradat/tables.cpp b/devtools/create_kyradat/tables.cpp
index 777f237650..777f237650 100644
--- a/tools/create_kyradat/tables.cpp
+++ b/devtools/create_kyradat/tables.cpp
diff --git a/tools/create_kyradat/tables.h b/devtools/create_kyradat/tables.h
index c990043f5d..c990043f5d 100644
--- a/tools/create_kyradat/tables.h
+++ b/devtools/create_kyradat/tables.h
diff --git a/tools/create_kyradat/util.cpp b/devtools/create_kyradat/util.cpp
index 702a36bc0e..702a36bc0e 100644
--- a/tools/create_kyradat/util.cpp
+++ b/devtools/create_kyradat/util.cpp
diff --git a/tools/create_kyradat/util.h b/devtools/create_kyradat/util.h
index 077597ac07..077597ac07 100644
--- a/tools/create_kyradat/util.h
+++ b/devtools/create_kyradat/util.h
diff --git a/tools/create_lure/Makefile b/devtools/create_lure/Makefile
index 1ed33b594c..1ed33b594c 100644
--- a/tools/create_lure/Makefile
+++ b/devtools/create_lure/Makefile
diff --git a/tools/create_lure/create_lure_dat.cpp b/devtools/create_lure/create_lure_dat.cpp
index ad883b808f..ad883b808f 100644
--- a/tools/create_lure/create_lure_dat.cpp
+++ b/devtools/create_lure/create_lure_dat.cpp
diff --git a/tools/create_lure/create_lure_dat.h b/devtools/create_lure/create_lure_dat.h
index 4743f6ac3f..4743f6ac3f 100644
--- a/tools/create_lure/create_lure_dat.h
+++ b/devtools/create_lure/create_lure_dat.h
diff --git a/tools/create_lure/dists/msvc8/create_lure.sln b/devtools/create_lure/dists/msvc8/create_lure.sln
index 8d74988d8c..8d74988d8c 100644
--- a/tools/create_lure/dists/msvc8/create_lure.sln
+++ b/devtools/create_lure/dists/msvc8/create_lure.sln
diff --git a/tools/create_lure/dists/msvc8/create_lure.vcproj b/devtools/create_lure/dists/msvc8/create_lure.vcproj
index 177466a29f..177466a29f 100644
--- a/tools/create_lure/dists/msvc8/create_lure.vcproj
+++ b/devtools/create_lure/dists/msvc8/create_lure.vcproj
diff --git a/tools/create_lure/dists/msvc8_to_msvc9.bat b/devtools/create_lure/dists/msvc8_to_msvc9.bat
index 54820b34d0..54820b34d0 100644
--- a/tools/create_lure/dists/msvc8_to_msvc9.bat
+++ b/devtools/create_lure/dists/msvc8_to_msvc9.bat
diff --git a/tools/create_lure/dists/msvc9/create_lure.sln b/devtools/create_lure/dists/msvc9/create_lure.sln
index 4f55924eea..4f55924eea 100644
--- a/tools/create_lure/dists/msvc9/create_lure.sln
+++ b/devtools/create_lure/dists/msvc9/create_lure.sln
diff --git a/tools/create_lure/dists/msvc9/create_lure.vcproj b/devtools/create_lure/dists/msvc9/create_lure.vcproj
index a611db31fa..a611db31fa 100644
--- a/tools/create_lure/dists/msvc9/create_lure.vcproj
+++ b/devtools/create_lure/dists/msvc9/create_lure.vcproj
diff --git a/tools/create_lure/dists/msvc9_to_msvc8.bat b/devtools/create_lure/dists/msvc9_to_msvc8.bat
index c87a524f77..c87a524f77 100644
--- a/tools/create_lure/dists/msvc9_to_msvc8.bat
+++ b/devtools/create_lure/dists/msvc9_to_msvc8.bat
diff --git a/tools/create_lure/module.mk b/devtools/create_lure/module.mk
index 04229b9377..5d8192cb7a 100644
--- a/tools/create_lure/module.mk
+++ b/devtools/create_lure/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/create_lure
+MODULE := devtools/create_lure
MODULE_OBJS := \
create_lure_dat.o \
diff --git a/tools/create_lure/process_actions.cpp b/devtools/create_lure/process_actions.cpp
index 30e7eed9e4..30e7eed9e4 100644
--- a/tools/create_lure/process_actions.cpp
+++ b/devtools/create_lure/process_actions.cpp
diff --git a/tools/create_mads/Makefile b/devtools/create_mads/Makefile
index c2776f5d17..c2776f5d17 100644
--- a/tools/create_mads/Makefile
+++ b/devtools/create_mads/Makefile
diff --git a/tools/create_mads/dists/msvc9/create_mads.sln b/devtools/create_mads/dists/msvc9/create_mads.sln
index 5ddd18cffe..5ddd18cffe 100644
--- a/tools/create_mads/dists/msvc9/create_mads.sln
+++ b/devtools/create_mads/dists/msvc9/create_mads.sln
diff --git a/tools/create_mads/dists/msvc9/create_mads.vcproj b/devtools/create_mads/dists/msvc9/create_mads.vcproj
index 1f33faa418..1f33faa418 100644
--- a/tools/create_mads/dists/msvc9/create_mads.vcproj
+++ b/devtools/create_mads/dists/msvc9/create_mads.vcproj
diff --git a/tools/create_mads/main.cpp b/devtools/create_mads/main.cpp
index 26ae2a7558..26ae2a7558 100644
--- a/tools/create_mads/main.cpp
+++ b/devtools/create_mads/main.cpp
diff --git a/tools/create_mads/module.mk b/devtools/create_mads/module.mk
index db35973eef..c773da8366 100644
--- a/tools/create_mads/module.mk
+++ b/devtools/create_mads/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/create_mads
+MODULE := devtools/create_mads
MODULE_OBJS := \
main.o \
diff --git a/tools/create_mads/parser.cpp b/devtools/create_mads/parser.cpp
index c37b3a7a80..c37b3a7a80 100644
--- a/tools/create_mads/parser.cpp
+++ b/devtools/create_mads/parser.cpp
diff --git a/tools/create_mads/parser.h b/devtools/create_mads/parser.h
index d404e8395f..d404e8395f 100644
--- a/tools/create_mads/parser.h
+++ b/devtools/create_mads/parser.h
diff --git a/tools/create_mads/scripts/rex_nebular.txt b/devtools/create_mads/scripts/rex_nebular.txt
index f177720398..f177720398 100644
--- a/tools/create_mads/scripts/rex_nebular.txt
+++ b/devtools/create_mads/scripts/rex_nebular.txt
diff --git a/tools/create_project/codeblocks.cpp b/devtools/create_project/codeblocks.cpp
index b5fd743ee1..d803fb0a37 100644
--- a/tools/create_project/codeblocks.cpp
+++ b/devtools/create_project/codeblocks.cpp
@@ -163,8 +163,13 @@ void CodeBlocksProvider::createProjectFile(const std::string &name, const std::s
project << "\t\t\t\t\t<Add option=\"-g\" />\n"
"\t\t\t\t\t<Add directory=\"..\\..\\engines\" />\n"
- "\t\t\t\t\t<Add directory=\"..\\..\\..\\scummvm\" />\n"
- "\t\t\t\t</Compiler>\n"
+ "\t\t\t\t\t<Add directory=\"..\\..\\..\\scummvm\" />\n";
+
+ // Sword2.5 engine needs theora and vorbis includes
+ if (name == "sword25")
+ project << "\t\t\t\t\t<Add directory=\"$(SCUMMVM_LIBS)include\" />\n";
+
+ project << "\t\t\t\t</Compiler>\n"
"\t\t\t</Target>\n"
"\t\t</Build>\n";
}
diff --git a/tools/create_project/codeblocks.h b/devtools/create_project/codeblocks.h
index ba75daeafd..ba75daeafd 100644
--- a/tools/create_project/codeblocks.h
+++ b/devtools/create_project/codeblocks.h
diff --git a/tools/create_project/codeblocks/create_project.cbp b/devtools/create_project/codeblocks/create_project.cbp
index 9078ddcd51..9078ddcd51 100644
--- a/tools/create_project/codeblocks/create_project.cbp
+++ b/devtools/create_project/codeblocks/create_project.cbp
diff --git a/tools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 74a048df35..b896e85131 100644
--- a/tools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -23,6 +23,12 @@
*
*/
+// HACK to allow building with the SDL backend on MinGW
+// see bug #1800764 "TOOLS: MinGW tools building broken"
+#ifdef main
+#undef main
+#endif // main
+
#include "create_project.h"
#include "codeblocks.h"
@@ -41,7 +47,11 @@
#include <cstdlib>
#include <ctime>
-#if defined(_WIN32) || defined(WIN32)
+#if (defined(_WIN32) || defined(WIN32)) && !defined(__GNUC__)
+#define USE_WIN32_API
+#endif
+
+#ifdef USE_WIN32_API
#include <windows.h>
#else
#include <sstream>
@@ -103,7 +113,7 @@ enum ProjectType {
};
int main(int argc, char *argv[]) {
-#if !(defined(_WIN32) || defined(WIN32))
+#ifndef USE_WIN32_API
// Initialize random number generator for UUID creation
std::srand(std::time(0));
#endif
@@ -860,7 +870,7 @@ bool compareNodes(const FileNode *l, const FileNode *r) {
*/
FileList listDirectory(const std::string &dir) {
FileList result;
-#if defined(_WIN32) || defined(WIN32)
+#ifdef USE_WIN32_API
WIN32_FIND_DATA fileInformation;
HANDLE fileHandle = FindFirstFile((dir + "/*").c_str(), &fileInformation);
@@ -1035,7 +1045,7 @@ ProjectProvider::UUIDMap ProjectProvider::createUUIDMap(const BuildSetup &setup)
}
std::string ProjectProvider::createUUID() const {
-#if defined(_WIN32) || defined(WIN32)
+#ifdef USE_WIN32_API
UUID uuid;
if (UuidCreate(&uuid) != RPC_S_OK)
error("UuidCreate failed");
diff --git a/tools/create_project/create_project.h b/devtools/create_project/create_project.h
index 8c4b8c7d23..8c4b8c7d23 100644
--- a/tools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
diff --git a/tools/create_project/module.mk b/devtools/create_project/module.mk
index 9334a126af..4382fe176c 100644
--- a/tools/create_project/module.mk
+++ b/devtools/create_project/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/create_project
+MODULE := devtools/create_project
MODULE_OBJS := \
create_project.o \
diff --git a/tools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index 73511218b4..73511218b4 100644
--- a/tools/create_project/msbuild.cpp
+++ b/devtools/create_project/msbuild.cpp
diff --git a/tools/create_project/msbuild.h b/devtools/create_project/msbuild.h
index fa5311734b..fa5311734b 100644
--- a/tools/create_project/msbuild.h
+++ b/devtools/create_project/msbuild.h
diff --git a/tools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp
index 9745cffdd2..e2fff59c46 100644
--- a/tools/create_project/msvc.cpp
+++ b/devtools/create_project/msvc.cpp
@@ -152,7 +152,7 @@ std::string MSVCProvider::getPreBuildEvent() const {
cmdLine = "@echo off\n"
"echo Executing Pre-Build script...\n"
"echo.\n"
- "@call &quot;$(SolutionDir)../../tools/create_project/scripts/prebuild.cmd&quot; &quot;$(SolutionDir)/../..&quot;\n"
+ "@call &quot;$(SolutionDir)../../devtools/create_project/scripts/prebuild.cmd&quot; &quot;$(SolutionDir)/../..&quot;\n"
"EXIT /B0";
return cmdLine;
@@ -164,7 +164,7 @@ std::string MSVCProvider::getPostBuildEvent(bool isWin32) const {
cmdLine = "@echo off\n"
"echo Executing Post-Build script...\n"
"echo.\n"
- "@call &quot;$(SolutionDir)../../tools/create_project/scripts/postbuild.cmd&quot; &quot;$(SolutionDir)/../..&quot; &quot;$(OutDir)&quot; ";
+ "@call &quot;$(SolutionDir)../../devtools/create_project/scripts/postbuild.cmd&quot; &quot;$(SolutionDir)/../..&quot; &quot;$(OutDir)&quot; ";
cmdLine += (isWin32) ? "x86" : "x64";
diff --git a/tools/create_project/msvc.h b/devtools/create_project/msvc.h
index f41ecc3aba..f41ecc3aba 100644
--- a/tools/create_project/msvc.h
+++ b/devtools/create_project/msvc.h
diff --git a/tools/create_project/msvc10/create_project.sln b/devtools/create_project/msvc10/create_project.sln
index 69eeb8ed19..69eeb8ed19 100644
--- a/tools/create_project/msvc10/create_project.sln
+++ b/devtools/create_project/msvc10/create_project.sln
diff --git a/tools/create_project/msvc10/create_project.vcxproj b/devtools/create_project/msvc10/create_project.vcxproj
index 532d6dba29..532d6dba29 100644
--- a/tools/create_project/msvc10/create_project.vcxproj
+++ b/devtools/create_project/msvc10/create_project.vcxproj
diff --git a/tools/create_project/msvc10/create_project.vcxproj.filters b/devtools/create_project/msvc10/create_project.vcxproj.filters
index 7922e1e6f7..7922e1e6f7 100644
--- a/tools/create_project/msvc10/create_project.vcxproj.filters
+++ b/devtools/create_project/msvc10/create_project.vcxproj.filters
diff --git a/tools/create_project/msvc8/create_project.sln b/devtools/create_project/msvc8/create_project.sln
index 4a0152f33f..4a0152f33f 100644
--- a/tools/create_project/msvc8/create_project.sln
+++ b/devtools/create_project/msvc8/create_project.sln
diff --git a/tools/create_project/msvc8/create_project.vcproj b/devtools/create_project/msvc8/create_project.vcproj
index bc3b2437ac..bc3b2437ac 100644
--- a/tools/create_project/msvc8/create_project.vcproj
+++ b/devtools/create_project/msvc8/create_project.vcproj
diff --git a/tools/create_project/msvc9/create_project.sln b/devtools/create_project/msvc9/create_project.sln
index df754e1d78..df754e1d78 100644
--- a/tools/create_project/msvc9/create_project.sln
+++ b/devtools/create_project/msvc9/create_project.sln
diff --git a/tools/create_project/msvc9/create_project.vcproj b/devtools/create_project/msvc9/create_project.vcproj
index c89b88a1c9..c89b88a1c9 100644
--- a/tools/create_project/msvc9/create_project.vcproj
+++ b/devtools/create_project/msvc9/create_project.vcproj
diff --git a/tools/create_project/scripts/postbuild.cmd b/devtools/create_project/scripts/postbuild.cmd
index 5c2bd8a1ad..5c2bd8a1ad 100644
--- a/tools/create_project/scripts/postbuild.cmd
+++ b/devtools/create_project/scripts/postbuild.cmd
diff --git a/tools/create_project/scripts/prebuild.cmd b/devtools/create_project/scripts/prebuild.cmd
index 584e217c65..b824f0d5a0 100644
--- a/tools/create_project/scripts/prebuild.cmd
+++ b/devtools/create_project/scripts/prebuild.cmd
@@ -12,7 +12,7 @@ REM Root folder
if "%~1"=="" goto error_input
REM Run the revision script
-@call cscript "%~1/tools/create_project/scripts/revision.vbs" %~1 1>NUL
+@call cscript "%~1/devtools/create_project/scripts/revision.vbs" %~1 1>NUL
if not %errorlevel% == 0 goto error_script
goto done
diff --git a/tools/create_project/scripts/revision.vbs b/devtools/create_project/scripts/revision.vbs
index ad6b2c6b2e..851185371b 100644
--- a/tools/create_project/scripts/revision.vbs
+++ b/devtools/create_project/scripts/revision.vbs
@@ -28,7 +28,7 @@ Option Explicit
' Working copy check priority:
' True: TortoiseSVN -> SVN -> Git -> Hg
' False: Git -> Hg -> TortoiseSVN -> SVN
-Dim prioritySVN: prioritySVN = True
+Dim prioritySVN: prioritySVN = False
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
diff --git a/tools/create_project/visualstudio.cpp b/devtools/create_project/visualstudio.cpp
index f9bf3a2b60..2b7c8908cb 100644
--- a/tools/create_project/visualstudio.cpp
+++ b/devtools/create_project/visualstudio.cpp
@@ -230,11 +230,12 @@ void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int b
"\t\tIgnoreDefaultLibraryNames=\"\"\n"
"\t\tSubSystem=\"1\"\n"
"\t\tEntryPointSymbol=\"WinMainCRTStartup\"\n"
+ "\t\tAdditionalLibraryDirectories=\"$(SCUMMVM_LIBS)\\lib\\" << ((bits == 32) ? "x86" : "x64") << "\"\n"
"\t/>\n"
"\t<Tool\n"
"\t\tName=\"VCResourceCompilerTool\"\n"
"\t\tPreprocessorDefinitions=\"HAS_INCLUDE_SET\"\n"
- "\t\tAdditionalIncludeDirectories=\"$(SCUMMVM_LIBS)\\lib\\" << (bits == 32 ? "x86" : "x64") << "\"\n"
+ "\t\tAdditionalIncludeDirectories=\"" << prefix << "\"\n"
"\t/>\n"
"</VisualStudioPropertySheet>\n";
diff --git a/tools/create_project/visualstudio.h b/devtools/create_project/visualstudio.h
index 0cf572429b..0cf572429b 100644
--- a/tools/create_project/visualstudio.h
+++ b/devtools/create_project/visualstudio.h
diff --git a/tools/create_teenagent/create_teenagent.cpp b/devtools/create_teenagent/create_teenagent.cpp
index ae88cc5d65..9a9c00d4b4 100644
--- a/tools/create_teenagent/create_teenagent.cpp
+++ b/devtools/create_teenagent/create_teenagent.cpp
@@ -26,6 +26,12 @@
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
+// HACK to allow building with the SDL backend on MinGW
+// see bug #1800764 "TOOLS: MinGW tools building broken"
+#ifdef main
+#undef main
+#endif // main
+
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
diff --git a/tools/create_teenagent/md5.cpp b/devtools/create_teenagent/md5.cpp
index 214b5ef7ed..214b5ef7ed 100644
--- a/tools/create_teenagent/md5.cpp
+++ b/devtools/create_teenagent/md5.cpp
diff --git a/tools/create_teenagent/md5.h b/devtools/create_teenagent/md5.h
index dd50efece8..dd50efece8 100644
--- a/tools/create_teenagent/md5.h
+++ b/devtools/create_teenagent/md5.h
diff --git a/tools/create_teenagent/module.mk b/devtools/create_teenagent/module.mk
index f7e4e11250..5c9b876140 100644
--- a/tools/create_teenagent/module.mk
+++ b/devtools/create_teenagent/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/create_teenagent
+MODULE := devtools/create_teenagent
MODULE_OBJS := \
create_teenagent.o \
diff --git a/tools/create_teenagent/util.h b/devtools/create_teenagent/util.h
index 077597ac07..077597ac07 100644
--- a/tools/create_teenagent/util.h
+++ b/devtools/create_teenagent/util.h
diff --git a/tools/create_toon/create_toon.cpp b/devtools/create_toon/create_toon.cpp
index 3cf252cbcd..3cf252cbcd 100644
--- a/tools/create_toon/create_toon.cpp
+++ b/devtools/create_toon/create_toon.cpp
diff --git a/tools/create_toon/create_toon.h b/devtools/create_toon/create_toon.h
index 0695944b17..0695944b17 100644
--- a/tools/create_toon/create_toon.h
+++ b/devtools/create_toon/create_toon.h
diff --git a/tools/create_toon/dists/msvc9/create_toon.sln b/devtools/create_toon/dists/msvc9/create_toon.sln
index e9c3750590..e9c3750590 100644
--- a/tools/create_toon/dists/msvc9/create_toon.sln
+++ b/devtools/create_toon/dists/msvc9/create_toon.sln
diff --git a/tools/create_toon/dists/msvc9/create_toon.vcproj b/devtools/create_toon/dists/msvc9/create_toon.vcproj
index f860b8b201..f860b8b201 100644
--- a/tools/create_toon/dists/msvc9/create_toon.vcproj
+++ b/devtools/create_toon/dists/msvc9/create_toon.vcproj
diff --git a/tools/create_toon/module.mk b/devtools/create_toon/module.mk
index 761afb7a7f..9bcbfcb6e8 100644
--- a/tools/create_toon/module.mk
+++ b/devtools/create_toon/module.mk
@@ -1,4 +1,4 @@
-MODULE := tools/create_toon
+MODULE := devtools/create_toon
MODULE_OBJS := \
create_toon.o
diff --git a/tools/create_toon/staticdata.h b/devtools/create_toon/staticdata.h
index efcb893024..efcb893024 100644
--- a/tools/create_toon/staticdata.h
+++ b/devtools/create_toon/staticdata.h
diff --git a/tools/create_translations/create_translations.cpp b/devtools/create_translations/create_translations.cpp
index 9fcf3b4a31..9fcf3b4a31 100644
--- a/tools/create_translations/create_translations.cpp
+++ b/devtools/create_translations/create_translations.cpp
diff --git a/tools/create_translations/create_translations.h b/devtools/create_translations/create_translations.h
index 0ece8102f0..0ece8102f0 100644
--- a/tools/create_translations/create_translations.h
+++ b/devtools/create_translations/create_translations.h
diff --git a/tools/create_translations/module.mk b/devtools/create_translations/module.mk
index 4ffb39183b..430cf91976 100644
--- a/tools/create_translations/module.mk
+++ b/devtools/create_translations/module.mk
@@ -1,4 +1,4 @@
-MODULE := tools/create_translations
+MODULE := devtools/create_translations
MODULE_OBJS := \
po_parser.o \
diff --git a/tools/create_translations/po_parser.cpp b/devtools/create_translations/po_parser.cpp
index bc49da40d4..bc49da40d4 100644
--- a/tools/create_translations/po_parser.cpp
+++ b/devtools/create_translations/po_parser.cpp
diff --git a/tools/create_translations/po_parser.h b/devtools/create_translations/po_parser.h
index 6991b1d11e..6991b1d11e 100644
--- a/tools/create_translations/po_parser.h
+++ b/devtools/create_translations/po_parser.h
diff --git a/tools/credits.pl b/devtools/credits.pl
index b72d38bcd1..075d7b03db 100755
--- a/tools/credits.pl
+++ b/devtools/credits.pl
@@ -640,8 +640,10 @@ begin_credits("Credits");
end_section();
begin_section("Mohawk");
+ add_person("Bastien Bouclet", "bgk", "");
add_person("Matthew Hoops", "clone2727", "");
add_person("Filippos Karapetis", "[md5]", "");
+ add_person("Alyssa Milburn", "fuzzie", "");
add_person("Eugene Sandulenko", "sev", "");
add_person("David Turner", "digitall", "");
end_section();
@@ -702,6 +704,7 @@ begin_credits("Credits");
begin_section("Backend Teams");
begin_section("Android");
+ add_person("Andre Heider", "dhewg", "");
add_person("Angus Lees", "Gus", "");
end_section();
@@ -762,6 +765,10 @@ begin_credits("Credits");
add_person("Lars Persson", "AnotherGuest", "");
end_section();
+ begin_section("WebOS");
+ add_person("Klaus Reimer", "kayahr", "");
+ end_section();
+
begin_section("Wii");
add_person("Andre Heider", "dhewg", "");
end_section();
@@ -783,7 +790,7 @@ begin_credits("Credits");
begin_section("Miscellaneous");
add_person("David Corrales-Lopez", "david_corrales", "Filesystem access improvements (GSoC 2007 task) (retired)");
- add_person("Jerome Fisher", "KingGuppy", "MT-32 emulator (retired)");
+ add_person("Jerome Fisher", "KingGuppy", "MT-32 emulator");
add_person("Benjamin Haisch", "john_doe", "Heavily improved de-/encoder for DXA videos");
add_person("Jochen Hoenicke", "hoenicke", "Speaker &amp; PCjr sound support, AdLib work (retired)");
add_person("Chris Page", "cp88", "Return to launcher, savestate improvements, leak fixes, ... (GSoC 2008 task) (retired)");
@@ -796,6 +803,19 @@ begin_credits("Credits");
add_person("Fredrik Wendel", "", "(retired)");
end_persons();
end_section();
+
+ begin_section("Website (maintenance)");
+ begin_persons();
+ add_person("James Brown", "Ender", "IRC Logs maintainer");
+ add_person("Thierry Crozat", "criezy", "Wiki maintainer");
+ add_person("Andre Heider", "dhewg", "Buildbot maintainer");
+ add_person("Max Horn", "Fingolfin", "Forum, IRC channel and Mailing list maintainer");
+ add_person("Joost Peters", "JoostP", "Doxygen Project Documentation maintainer");
+ add_person("Jordi Vilalta Prat", "jvprat", "Wiki maintainer");
+ add_person("Eugene Sandulenko", "sev", "Forum, IRC channel, Screen Shots and Mailing list maintainer");
+ add_person("John Willis", "DJWillis", "");
+ end_persons();
+ end_section();
begin_section("Website (content)");
add_paragraph("All active team members");
@@ -937,6 +957,9 @@ begin_credits("Credits");
begin_section("Spanish");
add_person("Tom&aacute;s Maidagan", "Truido", "");
end_section();
+ begin_section("Swedish");
+ add_person("Hampus Flink", "", "");
+ end_section();
begin_section("Ukrainian");
add_person("Lubomyr Lisen", "", "");
end_section();
@@ -949,6 +972,7 @@ begin_credits("Credits");
add_person("David Jensen", "Tyst", "SVG logo conversion");
add_person("Jean Marc Gimenez", "", "ScummVM logo");
add_person("", "Raina", "ScummVM forum buttons");
+ add_person("William Claydon", "billwashere", "Skins for doxygen and wiki");
end_persons();
end_section();
@@ -958,7 +982,7 @@ begin_credits("Credits");
add_person("Stuart Caie", "", "Decoders for Amiga and AtariST data files (AGOS engine)");
add_person("Paolo Costabel", "", "PSP port contributions");
add_person("Martin Doucha", "next_ghost", "CinE engine objectification");
- add_person("Thomas Fach-Pedersen", "madmoose", "ProTracker module player");
+ add_person("Thomas Fach-Pedersen", "madmoose", "ProTracker module player, Smacker video decoder");
add_person("Tobias Gunkel", "hennymcc", "Sound support for C64 version of MM/Zak, Loom PCE support");
add_person("Janne Huttunen", "", "V3 actor mask support, Dig/FT SMUSH audio");
add_person("Kov&aacute;cs Endre J&aacute;nos", "", "Several fixes for Simon1");
diff --git a/tools/dist-scummvm.sh b/devtools/dist-scummvm.sh
index de76c9f6a9..de76c9f6a9 100755
--- a/tools/dist-scummvm.sh
+++ b/devtools/dist-scummvm.sh
diff --git a/tools/extract-words-tok.pl b/devtools/extract-words-tok.pl
index ea654759aa..9209d49eb5 100755
--- a/tools/extract-words-tok.pl
+++ b/devtools/extract-words-tok.pl
@@ -32,8 +32,8 @@
#
# for i in agigames/*/words.tok
# do
-# tools/extract-words-tok.pl "$i"
-# done | tools/construct-pred-dict.pl
+# devtools/extract-words-tok.pl "$i"
+# done | devtools/construct-pred-dict.pl
#
local $/;
diff --git a/tools/make-scumm-fontdata.c b/devtools/make-scumm-fontdata.c
index 991d49831a..991d49831a 100644
--- a/tools/make-scumm-fontdata.c
+++ b/devtools/make-scumm-fontdata.c
diff --git a/tools/md5table.c b/devtools/md5table.c
index 7d76b7541d..7d76b7541d 100644
--- a/tools/md5table.c
+++ b/devtools/md5table.c
diff --git a/devtools/module.mk b/devtools/module.mk
new file mode 100644
index 0000000000..fdbc13f645
--- /dev/null
+++ b/devtools/module.mk
@@ -0,0 +1,86 @@
+# $URL$
+# $Id$
+
+MODULE := devtools
+
+MODULE_DIRS += \
+ devtools/
+
+
+#######################################################################
+# Tools directory
+#######################################################################
+
+DEVTOOLS := \
+ devtools/convbdf$(EXEEXT) \
+ devtools/md5table$(EXEEXT) \
+ devtools/make-scumm-fontdata$(EXEEXT)
+
+include $(srcdir)/devtools/*/module.mk
+
+.PHONY: $(srcdir)/devtools/*/module.mk
+
+# Make sure the 'all' / 'clean' targets build/clean the devtools, too
+#all:
+clean: clean-devtools
+
+# Main target
+devtools: $(DEVTOOLS)
+
+clean-devtools:
+ -$(RM) $(DEVTOOLS)
+
+#
+# Build rules for the devtools
+#
+
+devtools/convbdf$(EXEEXT): $(srcdir)/devtools/convbdf.c
+ $(QUIET)$(MKDIR) devtools/$(DEPDIR)
+ $(QUIET_LINK)$(LD) $(CFLAGS) -Wall -o $@ $<
+
+devtools/md5table$(EXEEXT): $(srcdir)/devtools/md5table.c
+ $(QUIET)$(MKDIR) devtools/$(DEPDIR)
+ $(QUIET_LINK)$(LD) $(CFLAGS) -Wall -o $@ $<
+
+devtools/make-scumm-fontdata$(EXEEXT): $(srcdir)/devtools/make-scumm-fontdata.c
+ $(QUIET)$(MKDIR) devtools/$(DEPDIR)
+ $(QUIET_LINK)$(LD) $(CFLAGS) -Wall -o $@ $<
+
+#
+# Rules to explicitly rebuild the credits / MD5 tables.
+# The rules for the files in the "web" resp. "docs" modules
+# assume that you are invoking "make" from within a complete
+# checkout of the ScummVM repository. Of course if that is not the
+# case, then you have to modify those paths...
+#
+
+credits:
+ $(srcdir)/devtools/credits.pl --text > $(srcdir)/AUTHORS
+# $(srcdir)/devtools/credits.pl --rtf > $(srcdir)/Credits.rtf
+ $(srcdir)/devtools/credits.pl --cpp > $(srcdir)/gui/credits.h
+ $(srcdir)/devtools/credits.pl --xml-website > $(srcdir)/../../web/trunk/data/credits.xml
+# $(srcdir)/devtools/credits.pl --xml-docbook > $(srcdir)/../../docs/trunk/docbook/credits.xml
+
+md5scumm: devtools/md5table$(EXEEXT)
+ devtools/md5table$(EXEEXT) --c++ < $(srcdir)/devtools/scumm-md5.txt > $(srcdir)/engines/scumm/scumm-md5.h
+
+#
+# Rules which automatically and implicitly rebuild the credits and
+# MD5 tables when needed.
+# These are currently disabled, because if the input data changes, then
+# the generated files should be checked in, too. Otherwise, we'd reduce
+# portability to system on which our devtools can't (automatically) be
+# run for some reason.
+#
+
+#scumm/scumm-md5.h: $(srcdir)/devtools/scumm-md5.txt devtools/md5table$(EXEEXT)
+# devtools/md5table$(EXEEXT) --c++ < $< > $@
+
+#AUTHORS: $(srcdir)/devtools/credits.pl
+# $(srcdir)/devtools/credits.pl --text > $@
+
+#gui/credits.h: $(srcdir)/devtools/credits.pl
+# $(srcdir)/devtools/credits.pl --cpp > $@
+
+
+.PHONY: clean-devtools devtools credits md5scumm
diff --git a/tools/qtable/fat_amiga_demo.h b/devtools/qtable/fat_amiga_demo.h
index 027fc83e78..027fc83e78 100644
--- a/tools/qtable/fat_amiga_demo.h
+++ b/devtools/qtable/fat_amiga_demo.h
diff --git a/tools/qtable/fat_amiga_eng_floppy.h b/devtools/qtable/fat_amiga_eng_floppy.h
index 49895cd0eb..49895cd0eb 100644
--- a/tools/qtable/fat_amiga_eng_floppy.h
+++ b/devtools/qtable/fat_amiga_eng_floppy.h
diff --git a/tools/qtable/fat_amiga_interview.h b/devtools/qtable/fat_amiga_interview.h
index 1ea39df6cb..1ea39df6cb 100644
--- a/tools/qtable/fat_amiga_interview.h
+++ b/devtools/qtable/fat_amiga_interview.h
diff --git a/tools/qtable/fat_eng_cdrom.h b/devtools/qtable/fat_eng_cdrom.h
index 28a7d4fa56..28a7d4fa56 100644
--- a/tools/qtable/fat_eng_cdrom.h
+++ b/devtools/qtable/fat_eng_cdrom.h
diff --git a/tools/qtable/fat_eng_floppy.h b/devtools/qtable/fat_eng_floppy.h
index 075c27431d..075c27431d 100644
--- a/tools/qtable/fat_eng_floppy.h
+++ b/devtools/qtable/fat_eng_floppy.h
diff --git a/tools/qtable/fat_fre_cdrom.h b/devtools/qtable/fat_fre_cdrom.h
index 1cb60b1814..1cb60b1814 100644
--- a/tools/qtable/fat_fre_cdrom.h
+++ b/devtools/qtable/fat_fre_cdrom.h
diff --git a/tools/qtable/fat_fre_floppy.h b/devtools/qtable/fat_fre_floppy.h
index f280abbb19..f280abbb19 100644
--- a/tools/qtable/fat_fre_floppy.h
+++ b/devtools/qtable/fat_fre_floppy.h
diff --git a/tools/qtable/fat_ger_cdrom.h b/devtools/qtable/fat_ger_cdrom.h
index 6842892342..6842892342 100644
--- a/tools/qtable/fat_ger_cdrom.h
+++ b/devtools/qtable/fat_ger_cdrom.h
diff --git a/tools/qtable/fat_ger_floppy.h b/devtools/qtable/fat_ger_floppy.h
index f05892f87d..f05892f87d 100644
--- a/tools/qtable/fat_ger_floppy.h
+++ b/devtools/qtable/fat_ger_floppy.h
diff --git a/tools/qtable/fat_heb_cdrom.h b/devtools/qtable/fat_heb_cdrom.h
index bc7ca92869..bc7ca92869 100644
--- a/tools/qtable/fat_heb_cdrom.h
+++ b/devtools/qtable/fat_heb_cdrom.h
diff --git a/tools/qtable/fat_ita_cdrom.h b/devtools/qtable/fat_ita_cdrom.h
index 0bd0a484ae..0bd0a484ae 100644
--- a/tools/qtable/fat_ita_cdrom.h
+++ b/devtools/qtable/fat_ita_cdrom.h
diff --git a/tools/qtable/fat_ita_floppy.h b/devtools/qtable/fat_ita_floppy.h
index 1cbf3518bd..1cbf3518bd 100644
--- a/tools/qtable/fat_ita_floppy.h
+++ b/devtools/qtable/fat_ita_floppy.h
diff --git a/tools/qtable/fat_pc_demo.h b/devtools/qtable/fat_pc_demo.h
index e0ab9ae663..e0ab9ae663 100644
--- a/tools/qtable/fat_pc_demo.h
+++ b/devtools/qtable/fat_pc_demo.h
diff --git a/tools/qtable/fat_pc_demo_pcgames.h b/devtools/qtable/fat_pc_demo_pcgames.h
index b9632e174f..b9632e174f 100644
--- a/tools/qtable/fat_pc_demo_pcgames.h
+++ b/devtools/qtable/fat_pc_demo_pcgames.h
diff --git a/tools/qtable/fat_pc_interview.h b/devtools/qtable/fat_pc_interview.h
index 30b96a81c3..30b96a81c3 100644
--- a/tools/qtable/fat_pc_interview.h
+++ b/devtools/qtable/fat_pc_interview.h
diff --git a/tools/qtable/fat_spa_cdrom.h b/devtools/qtable/fat_spa_cdrom.h
index 38eba99cf0..38eba99cf0 100644
--- a/tools/qtable/fat_spa_cdrom.h
+++ b/devtools/qtable/fat_spa_cdrom.h
diff --git a/tools/qtable/module.mk b/devtools/qtable/module.mk
index 43225040c8..5aab9ad0c7 100644
--- a/tools/qtable/module.mk
+++ b/devtools/qtable/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/qtable
+MODULE := devtools/qtable
MODULE_OBJS := \
qtable.o
diff --git a/tools/qtable/qtable.cpp b/devtools/qtable/qtable.cpp
index a659698688..a659698688 100644
--- a/tools/qtable/qtable.cpp
+++ b/devtools/qtable/qtable.cpp
diff --git a/tools/sci/musicplayer.cpp b/devtools/sci/musicplayer.cpp
index 139ce451ef..139ce451ef 100644
--- a/tools/sci/musicplayer.cpp
+++ b/devtools/sci/musicplayer.cpp
diff --git a/tools/sci/scidisasm.cpp b/devtools/sci/scidisasm.cpp
index 39ea7f9c41..39ea7f9c41 100644
--- a/tools/sci/scidisasm.cpp
+++ b/devtools/sci/scidisasm.cpp
diff --git a/tools/sci/scipack.cpp b/devtools/sci/scipack.cpp
index f70d91fabc..f70d91fabc 100644
--- a/tools/sci/scipack.cpp
+++ b/devtools/sci/scipack.cpp
diff --git a/tools/sci/scitrace.asm b/devtools/sci/scitrace.asm
index 360e0b7ffc..360e0b7ffc 100644
--- a/tools/sci/scitrace.asm
+++ b/devtools/sci/scitrace.asm
diff --git a/tools/scumm-md5.txt b/devtools/scumm-md5.txt
index 60fc615057..60fc615057 100644
--- a/tools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
diff --git a/tools/skycpt/288diff.txt b/devtools/skycpt/288diff.txt
index 61d82b4262..61d82b4262 100644
--- a/tools/skycpt/288diff.txt
+++ b/devtools/skycpt/288diff.txt
diff --git a/tools/skycpt/AsciiCptCompile.cpp b/devtools/skycpt/AsciiCptCompile.cpp
index 1169de5aea..1169de5aea 100644
--- a/tools/skycpt/AsciiCptCompile.cpp
+++ b/devtools/skycpt/AsciiCptCompile.cpp
diff --git a/tools/skycpt/AsciiCptCompile.sln b/devtools/skycpt/AsciiCptCompile.sln
index 93de755bf3..93de755bf3 100644
--- a/tools/skycpt/AsciiCptCompile.sln
+++ b/devtools/skycpt/AsciiCptCompile.sln
diff --git a/tools/skycpt/AsciiCptCompile.vcproj b/devtools/skycpt/AsciiCptCompile.vcproj
index e6a5def316..e6a5def316 100644
--- a/tools/skycpt/AsciiCptCompile.vcproj
+++ b/devtools/skycpt/AsciiCptCompile.vcproj
diff --git a/tools/skycpt/COMPACT.TXT b/devtools/skycpt/COMPACT.TXT
index af22e129cf..af22e129cf 100644
--- a/tools/skycpt/COMPACT.TXT
+++ b/devtools/skycpt/COMPACT.TXT
diff --git a/tools/skycpt/KmpSearch.cpp b/devtools/skycpt/KmpSearch.cpp
index b0512a8d3e..b0512a8d3e 100644
--- a/tools/skycpt/KmpSearch.cpp
+++ b/devtools/skycpt/KmpSearch.cpp
diff --git a/tools/skycpt/KmpSearch.h b/devtools/skycpt/KmpSearch.h
index 6f13ace4a5..6f13ace4a5 100644
--- a/tools/skycpt/KmpSearch.h
+++ b/devtools/skycpt/KmpSearch.h
diff --git a/tools/skycpt/README b/devtools/skycpt/README
index 4b303cb0e9..4b303cb0e9 100644
--- a/tools/skycpt/README
+++ b/devtools/skycpt/README
diff --git a/tools/skycpt/TextFile.cpp b/devtools/skycpt/TextFile.cpp
index ee64d22f5f..ee64d22f5f 100644
--- a/tools/skycpt/TextFile.cpp
+++ b/devtools/skycpt/TextFile.cpp
diff --git a/tools/skycpt/TextFile.h b/devtools/skycpt/TextFile.h
index a9ad65417c..a9ad65417c 100644
--- a/tools/skycpt/TextFile.h
+++ b/devtools/skycpt/TextFile.h
diff --git a/tools/skycpt/cptcompiler.cpp b/devtools/skycpt/cptcompiler.cpp
index 956f575d7d..7453b383b6 100644
--- a/tools/skycpt/cptcompiler.cpp
+++ b/devtools/skycpt/cptcompiler.cpp
@@ -362,6 +362,7 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
fwrite(&tmp, 2, 1, resOutf);
}
}
+ printf("DEBUG lcnt: %lu Output File Position: 0x%08lX\r\n", lcnt, ftell(debOutf));
}
cptSize[0] = ftell(debOutf) - cptSize[0];
cptSize[1] = ftell(resOutf) - cptSize[1];
@@ -390,6 +391,7 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
fwrite(dlinks + cnt * 2 + 1, 2, 1, resOutf);
}
printf("Processing diff data...\n");
+ printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
// 288 diffdata
FILE *dif = fopen("288diff.txt", "r");
assert(dif);
@@ -448,6 +450,7 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
fwrite(diff, 2, diffDest, resOutf);
printf("Converting Save data...\n");
+ printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
// the IDs of the compacts to be saved
char cptName[1024];
uint16 saveIds[2048];
@@ -503,6 +506,8 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
fwrite(&tmp, 2, 1, debOutf);
tmp = 0;
fwrite(&tmp, 2, 1, debOutf);
+
+ printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
printf("reset destination: %ld\n", ftell(debOutf));
for (int cnt = 0; cnt < 6; cnt++) {
printf("Processing diff v0.0%03d\n", gameVers[cnt]);
@@ -527,6 +532,7 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
fwrite(&diffPos, 1, 2, debOutf);
fwrite(diff, 2, 2 * diffPos, debOutf);
printf("diff v0.0%03d: 2 * 2 * %d\n", gameVers[cnt], diffPos);
+ printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
}
free(buf288);
} else {
diff --git a/tools/skycpt/cpthelp.cpp b/devtools/skycpt/cpthelp.cpp
index 134e440fd7..134e440fd7 100644
--- a/tools/skycpt/cpthelp.cpp
+++ b/devtools/skycpt/cpthelp.cpp
diff --git a/tools/skycpt/cpthelp.h b/devtools/skycpt/cpthelp.h
index 722e756edf..722e756edf 100644
--- a/tools/skycpt/cpthelp.h
+++ b/devtools/skycpt/cpthelp.h
diff --git a/tools/skycpt/idFinder.cpp b/devtools/skycpt/idFinder.cpp
index 53c9f1f1a0..53c9f1f1a0 100644
--- a/tools/skycpt/idFinder.cpp
+++ b/devtools/skycpt/idFinder.cpp
diff --git a/tools/skycpt/module.mk b/devtools/skycpt/module.mk
index 8ce208210b..84a59cee9f 100644
--- a/tools/skycpt/module.mk
+++ b/devtools/skycpt/module.mk
@@ -1,7 +1,7 @@
# $URL$
# $Id$
-MODULE := tools/skycpt
+MODULE := devtools/skycpt
MODULE_OBJS := \
AsciiCptCompile.o \
diff --git a/tools/skycpt/savedata.txt b/devtools/skycpt/savedata.txt
index e867287c33..e867287c33 100644
--- a/tools/skycpt/savedata.txt
+++ b/devtools/skycpt/savedata.txt
diff --git a/tools/skycpt/skycpt-engine.patch b/devtools/skycpt/skycpt-engine.patch
index 16388a3221..16388a3221 100644
--- a/tools/skycpt/skycpt-engine.patch
+++ b/devtools/skycpt/skycpt-engine.patch
diff --git a/tools/skycpt/stdafx.cpp b/devtools/skycpt/stdafx.cpp
index 8a5c78bc36..8a5c78bc36 100644
--- a/tools/skycpt/stdafx.cpp
+++ b/devtools/skycpt/stdafx.cpp
diff --git a/tools/skycpt/stdafx.h b/devtools/skycpt/stdafx.h
index 3e5c6042eb..3e5c6042eb 100644
--- a/tools/skycpt/stdafx.h
+++ b/devtools/skycpt/stdafx.h
diff --git a/tools/themeparser.py b/devtools/themeparser.py
index 993f7c79bc..993f7c79bc 100644
--- a/tools/themeparser.py
+++ b/devtools/themeparser.py
diff --git a/tools/update-version.pl b/devtools/update-version.pl
index 81aa5c27f9..91e9e2492b 100755
--- a/tools/update-version.pl
+++ b/devtools/update-version.pl
@@ -41,6 +41,7 @@ my @subs_files = qw(
dists/irix/scummvm.spec
dists/wii/meta.xml
dists/android/AndroidManifest.xml
+ dists/android/plugin-manifest.xml
backends/platform/psp/README.PSP
);
diff --git a/dists/android/AndroidManifest.xml b/dists/android/AndroidManifest.xml
index 3b69c9f1f3..cae1f369e7 100644
--- a/dists/android/AndroidManifest.xml
+++ b/dists/android/AndroidManifest.xml
@@ -1,58 +1,61 @@
-<?xml version="1.0" encoding="utf-8"?> <!-- -*- xml -*- -->
+<?xml version="1.0" encoding="utf-8"?>
<!-- NB: android:versionCode needs to be bumped for formal releases -->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.inodes.gus.scummvm"
- android:versionCode="6" android:versionName="1.3.0svn"
- android:installLocation="preferExternal">
-
- <!-- This version works on Android 1.5 (SDK 3) and newer, but we
- want Android 2.2 (SDK 8) defaults and features.
- -->
- <uses-sdk android:minSdkVersion="3"
- android:targetSdkVersion="8" />
-
- <application android:name=".ScummVMApplication"
- android:label="@string/app_name"
- android:description="@string/app_desc"
- android:icon="@drawable/scummvm"
- android:persistent="true">
- <activity android:name=".ScummVMActivity"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- android:screenOrientation="landscape"
- android:configChanges="orientation|keyboardHidden"
- android:windowSoftInputMode="adjustResize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
- <activity android:name=".Unpacker"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- android:screenOrientation="landscape"
- android:configChanges="orientation|keyboardHidden">
- <meta-data android:name="org.inodes.gus.unpacker.nextActivity"
- android:value="org.inodes.gus.scummvm/.ScummVMActivity" />
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"
- android:label="@string/scummvm_perm_plugin_label"
- android:description="@string/scummvm_perm_plugin_desc"
- android:protectionLevel="signature" />
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-
- <!-- Always needs some sort of qwerty keyboard.
- Can work with a D-pad / trackball -->
- <uses-configuration android:reqFiveWayNav="true"
- android:reqKeyboardType="qwerty"/>
- <!-- .. or touchscreen -->
- <uses-configuration android:reqTouchScreen="finger"
- android:reqKeyboardType="qwerty"/>
- <uses-configuration android:reqTouchScreen="stylus"
- android:reqKeyboardType="qwerty"/>
+ package="org.inodes.gus.scummvm"
+ android:versionCode="@ANDROID_VERSIONCODE@"
+ android:versionName="1.3.0git"
+ android:installLocation="preferExternal">
+
+ <!-- This version works on Android 1.5 (SDK 3) and newer, but we
+ want Android 2.2 (SDK 8) defaults and features. -->
+ <uses-sdk android:minSdkVersion="3"
+ android:targetSdkVersion="8"/>
+
+ <application android:name=".ScummVMApplication"
+ android:label="@string/app_name"
+ android:description="@string/app_desc"
+ android:icon="@drawable/scummvm">
+ <activity android:name=".ScummVMActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden"
+ android:windowSoftInputMode="adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".Unpacker"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden">
+ <meta-data android:name="org.inodes.gus.unpacker.nextActivity"
+ android:value="org.inodes.gus.scummvm/.ScummVMActivity"/>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"
+ android:label="@string/scummvm_perm_plugin_label"
+ android:description="@string/scummvm_perm_plugin_desc"
+ android:protectionLevel="signature"/>
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+ <!-- Always needs some sort of qwerty keyboard.
+ Can work with a D-pad / trackball -->
+ <uses-configuration android:reqFiveWayNav="true"
+ android:reqKeyboardType="qwerty"/>
+
+ <!-- .. or touchscreen -->
+ <uses-configuration android:reqTouchScreen="finger"
+ android:reqKeyboardType="qwerty"/>
+
+ <uses-configuration android:reqTouchScreen="stylus"
+ android:reqKeyboardType="qwerty"/>
</manifest>
+
diff --git a/dists/android/AndroidManifest.xml.in b/dists/android/AndroidManifest.xml.in
index 26a94f957b..a8d40bdddc 100644
--- a/dists/android/AndroidManifest.xml.in
+++ b/dists/android/AndroidManifest.xml.in
@@ -1,58 +1,61 @@
-<?xml version="1.0" encoding="utf-8"?> <!-- -*- xml -*- -->
+<?xml version="1.0" encoding="utf-8"?>
<!-- NB: android:versionCode needs to be bumped for formal releases -->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.inodes.gus.scummvm"
- android:versionCode="6" android:versionName="@VERSION@"
- android:installLocation="preferExternal">
-
- <!-- This version works on Android 1.5 (SDK 3) and newer, but we
- want Android 2.2 (SDK 8) defaults and features.
- -->
- <uses-sdk android:minSdkVersion="3"
- android:targetSdkVersion="8" />
-
- <application android:name=".ScummVMApplication"
- android:label="@string/app_name"
- android:description="@string/app_desc"
- android:icon="@drawable/scummvm"
- android:persistent="true">
- <activity android:name=".ScummVMActivity"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- android:screenOrientation="landscape"
- android:configChanges="orientation|keyboardHidden"
- android:windowSoftInputMode="adjustResize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
- <activity android:name=".Unpacker"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- android:screenOrientation="landscape"
- android:configChanges="orientation|keyboardHidden">
- <meta-data android:name="org.inodes.gus.unpacker.nextActivity"
- android:value="org.inodes.gus.scummvm/.ScummVMActivity" />
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"
- android:label="@string/scummvm_perm_plugin_label"
- android:description="@string/scummvm_perm_plugin_desc"
- android:protectionLevel="signature" />
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-
- <!-- Always needs some sort of qwerty keyboard.
- Can work with a D-pad / trackball -->
- <uses-configuration android:reqFiveWayNav="true"
- android:reqKeyboardType="qwerty"/>
- <!-- .. or touchscreen -->
- <uses-configuration android:reqTouchScreen="finger"
- android:reqKeyboardType="qwerty"/>
- <uses-configuration android:reqTouchScreen="stylus"
- android:reqKeyboardType="qwerty"/>
+ package="org.inodes.gus.scummvm"
+ android:versionCode="@ANDROID_VERSIONCODE@"
+ android:versionName="@VERSION@"
+ android:installLocation="preferExternal">
+
+ <!-- This version works on Android 1.5 (SDK 3) and newer, but we
+ want Android 2.2 (SDK 8) defaults and features. -->
+ <uses-sdk android:minSdkVersion="3"
+ android:targetSdkVersion="8"/>
+
+ <application android:name=".ScummVMApplication"
+ android:label="@string/app_name"
+ android:description="@string/app_desc"
+ android:icon="@drawable/scummvm">
+ <activity android:name=".ScummVMActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden"
+ android:windowSoftInputMode="adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".Unpacker"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|keyboardHidden">
+ <meta-data android:name="org.inodes.gus.unpacker.nextActivity"
+ android:value="org.inodes.gus.scummvm/.ScummVMActivity"/>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"
+ android:label="@string/scummvm_perm_plugin_label"
+ android:description="@string/scummvm_perm_plugin_desc"
+ android:protectionLevel="signature"/>
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+ <!-- Always needs some sort of qwerty keyboard.
+ Can work with a D-pad / trackball -->
+ <uses-configuration android:reqFiveWayNav="true"
+ android:reqKeyboardType="qwerty"/>
+
+ <!-- .. or touchscreen -->
+ <uses-configuration android:reqTouchScreen="finger"
+ android:reqKeyboardType="qwerty"/>
+
+ <uses-configuration android:reqTouchScreen="stylus"
+ android:reqKeyboardType="qwerty"/>
</manifest>
+
diff --git a/dists/android/README.Android b/dists/android/README.Android
new file mode 100644
index 0000000000..550b73bdfa
--- /dev/null
+++ b/dists/android/README.Android
@@ -0,0 +1,56 @@
+README for the Android port of ScummVM
+--------------------------------------
+
+REQUIREMENTS
+
+ TODO
+
+INSTALL
+
+ TODO
+
+CONTROLS
+
+ 5-Way navigation control / DPAD
+
+ DPAD up/down/left/right: Mouse movement
+ DPAD center: Left mouse button
+
+ Trackball
+
+ Movement: Mouse movement
+ Click: Left mouse button
+
+ Touchscreen
+
+ The touchscreen can be used in two modes
+
+ 1) Direct mode
+ 2) Touchpad mode
+
+ When in direct mode, the mouse cursor moves to the touched point on screen.
+ In touchpad mode, the mouse cursor is independent of the touched point, it
+ is moved relative to its current position - like on a touchpad.
+
+ The port currently misses its own configuration dialog, the mode can
+ be toggled with the "Mixed AdLib/MIDI mode" on the MIDI tab in ScummVM's
+ own option dialog.
+
+ Tap + movement: Mouse movement
+ Tap without movement: Left mouse button click
+ Tap held for >0.5s without movement: Right mouse button click
+ Tap held for >1s without movement: Middle mouse button click
+ Double Tap + movement: Drag and drop
+
+ On devices supporting multitouch:
+
+ Two finger tap: Right mouse button click
+ Three finger tap: Middle mouse button click
+
+ System keys
+
+ Back button: Escape
+ Menu button: ScummVM menu
+ Menu button held for 0.5s: Toggle virtual keyboard
+ Camera or Search button: Right mouse button click
+
diff --git a/dists/android/mkmanifest.pl b/dists/android/mkmanifest.pl
deleted file mode 100755
index 62caa64a55..0000000000
--- a/dists/android/mkmanifest.pl
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/usr/bin/perl
-
-use File::Basename qw(dirname);
-use File::Path qw(mkpath);
-use IO::File;
-use XML::Writer;
-use XML::Parser;
-use Getopt::Long;
-
-use warnings;
-use strict;
-
-use constant ANDROID => 'http://schemas.android.com/apk/res/android';
-
-my $id;
-my $package_versionName;
-my $package_versionCode;
-my $configure = 'configure';
-my $stringres = 'res/string/values.xml';
-my $manifest = 'AndroidManifest.xml';
-my $master_manifest;
-my @unpack_libs;
-GetOptions('id=s' => \$id,
- 'version-name=s' => \$package_versionName,
- 'version-code=i' => \$package_versionCode,
- 'configure=s' => \$configure,
- 'stringres=s' => \$stringres,
- 'manifest=s' => \$manifest,
- 'master-manifest=s' => \$master_manifest,
- 'unpacklib=s' => \@unpack_libs,
- ) or die;
-die "Missing required arg"
- unless $id and $package_versionName and $package_versionCode;
-
-
-sub grope_engine_info {
- my $configure = shift;
- my @ret;
- while (<$configure>) {
- m/^add_engine \s+ (\w+) \s+ "(.*?)" \s+ \w+ (?:\s+ "([\w\s]*)")?/x
- or next;
- my $subengines = $3 || '';
- my %info = (id => $1, name => $2,
- subengines => [split / /, $subengines]);
- push @ret, \%info;
- }
- return @ret;
-}
-
-sub read_constraints {
- my $manifest = shift;
- my @constraints;
- my $parser = new XML::Parser Handlers => {
- Start => sub {
- my $expat = shift;
- my $elem = shift;
- return if $elem !~
- /^(uses-configuration|supports-screens|uses-sdk)$/;
- my @constraint = ($elem);
- while (@_) {
- my $attr = shift;
- my $value = shift;
- $attr = [ANDROID, $attr] if $attr =~ s/^android://;
- push @constraint, $attr, $value;
- }
- push @constraints, \@constraint;
- },
- };
- $parser->parse($manifest);
- return @constraints;
-}
-
-sub print_stringres {
- my $output = shift;
- my $info = shift;
-
- my $writer = new XML::Writer(OUTPUT => $output, ENCODING => 'utf-8',
- DATA_MODE => 1, DATA_INDENT => 2);
-
- $writer->xmlDecl();
- $writer->startTag('resources');
-
- while (my ($k,$v) = each %$info) {
- $writer->dataElement('string', $v, name => $k);
- }
-
- $writer->endTag('resources');
- $writer->end();
-}
-
-sub print_manifest {
- my $output = shift;
- my $info = shift;
- my $constraints = shift;
-
- my $writer = new XML::Writer(OUTPUT => $output, ENCODING => 'utf-8',
- DATA_MODE => 1, DATA_INDENT => 2,
- NAMESPACES => 1,
- PREFIX_MAP => {ANDROID, 'android'});
-
- $writer->xmlDecl();
-
- $writer->startTag(
- 'manifest',
- 'package' => "org.inodes.gus.scummvm.plugin.$info->{name}",
- [ANDROID, 'versionCode'] => $package_versionCode,
- [ANDROID, 'versionName'] => $package_versionName,
- [ANDROID, 'installLocation'] => 'preferExternal',
- );
-
- $writer->startTag(
- 'application',
- [ANDROID, 'label'] => '@string/app_name',
- [ANDROID, 'description'] => '@string/app_desc',
- [ANDROID, 'icon'] => '@drawable/scummvm',
- );
-
- $writer->startTag(
- 'receiver',
- [ANDROID, 'name'] => 'org.inodes.gus.scummvm.PluginProvider',
- [ANDROID, 'process'] => 'org.inodes.gus.scummvm');
-
- $writer->startTag('intent-filter');
- $writer->emptyTag('action', [ANDROID, 'name'] =>
- 'org.inodes.gus.scummvm.action.PLUGIN_QUERY');
- $writer->emptyTag('category', [ANDROID, 'name'] =>
- 'android.intent.category.INFO');
- $writer->endTag('intent-filter');
- $writer->emptyTag(
- 'meta-data',
- [ANDROID, 'name'] => 'org.inodes.gus.scummvm.meta.UNPACK_LIB',
- [ANDROID, 'value'] => $_)
- for @{$info->{unpack_libs}};
-
- $writer->endTag('receiver');
- $writer->endTag('application');
-
- $writer->emptyTag('uses-permission', [ANDROID, 'name'] =>
- 'org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN');
-
- $writer->emptyTag(@$_) foreach @$constraints;
-
- $writer->endTag('manifest');
- $writer->end();
-}
-
-
-my %engines;
-for my $engine (grope_engine_info(new IO::File $configure, 'r')) {
- $engines{$engine->{id}} = $engine;
-}
-
-my @games = ($id, @{$engines{$id}{subengines}});
-my $games_desc = join('; ', map $engines{$_}{name}, @games);
-
-my @constraints = read_constraints(new IO::File $master_manifest, 'r');
-
-print "Writing $stringres ...\n";
-mkpath(dirname($stringres));
-print_stringres(IO::File->new($stringres, 'w'),
- {app_name => qq{ScummVM plugin: "$id"},
- app_desc => "Game engine for: $games_desc",
- });
-
-print "Writing $manifest ...\n";
-mkpath(dirname($manifest));
-print_manifest(IO::File->new($manifest, 'w'),
- {name => $id, unpack_libs => \@unpack_libs}, \@constraints);
-
-exit 0;
diff --git a/dists/android/mkplugin.sh b/dists/android/mkplugin.sh
new file mode 100755
index 0000000000..f4643132cf
--- /dev/null
+++ b/dists/android/mkplugin.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ $# -ne 5 ]; then
+ echo "usage: $0 configure plugin template versioncode target"
+ exit 1
+fi
+
+CONFIGURE=$1
+PLUGIN_NAME=$2
+TEMPLATE=$3
+PLUGIN_VERSION_CODE=$4
+TARGET=$5
+
+PLUGIN_DESC=`sed -n s/add_engine\s$PLUGIN_NAME\s\"\(.\+\)\"\s.*/\1/p` < $CONFIGURE
+
+sed "s|@PLUGIN_NAME@|$PLUGIN_NAME|;s|@PLUGIN_VERSION_CODE@|$PLUGIN_VERSION_CODE|;s|@PLUGIN_DESC@|$PLUGIN_DESC|" < $TEMPLATE > $TARGET
+
diff --git a/dists/android/plugin-manifest.xml b/dists/android/plugin-manifest.xml
new file mode 100644
index 0000000000..2442d3f32a
--- /dev/null
+++ b/dists/android/plugin-manifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.inodes.gus.scummvm.plugin.@PLUGIN_NAME@"
+ android:versionCode="@PLUGIN_VERSION_CODE@"
+ android:versionName="1.3.0git"
+ android:installLocation="preferExternal">
+
+ <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8" />
+
+ <application android:label="@string/app_name"
+ android:description="@string/app_desc"
+ android:icon="@drawable/scummvm">
+ <receiver android:name="org.inodes.gus.scummvm.PluginProvider"
+ android:process="org.inodes.gus.scummvm">
+ <intent-filter>
+ <action android:name="org.inodes.gus.scummvm.action.PLUGIN_QUERY"/>
+ <category android:name="android.intent.category.INFO"/>
+ </intent-filter>
+ <meta-data android:name="org.inodes.gus.scummvm.meta.UNPACK_LIB"
+ android:value="mylib/armeabi/lib@PLUGIN_NAME@.so" />
+ </receiver>
+ </application>
+
+ <uses-permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"/>
+ <uses-configuration android:reqFiveWayNav="true"
+ android:reqKeyboardType="qwerty"/>
+
+ <uses-configuration android:reqTouchScreen="finger"
+ android:reqKeyboardType="qwerty"/>
+
+ <uses-configuration android:reqTouchScreen="stylus"
+ android:reqKeyboardType="qwerty"/>
+</manifest>
+
diff --git a/dists/android/plugin-manifest.xml.in b/dists/android/plugin-manifest.xml.in
new file mode 100644
index 0000000000..c941b2f48c
--- /dev/null
+++ b/dists/android/plugin-manifest.xml.in
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.inodes.gus.scummvm.plugin.@PLUGIN_NAME@"
+ android:versionCode="@PLUGIN_VERSION_CODE@"
+ android:versionName="@VERSION@"
+ android:installLocation="preferExternal">
+
+ <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8" />
+
+ <application android:label="@string/app_name"
+ android:description="@string/app_desc"
+ android:icon="@drawable/scummvm">
+ <receiver android:name="org.inodes.gus.scummvm.PluginProvider"
+ android:process="org.inodes.gus.scummvm">
+ <intent-filter>
+ <action android:name="org.inodes.gus.scummvm.action.PLUGIN_QUERY"/>
+ <category android:name="android.intent.category.INFO"/>
+ </intent-filter>
+ <meta-data android:name="org.inodes.gus.scummvm.meta.UNPACK_LIB"
+ android:value="mylib/armeabi/lib@PLUGIN_NAME@.so" />
+ </receiver>
+ </application>
+
+ <uses-permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN"/>
+ <uses-configuration android:reqFiveWayNav="true"
+ android:reqKeyboardType="qwerty"/>
+
+ <uses-configuration android:reqTouchScreen="finger"
+ android:reqKeyboardType="qwerty"/>
+
+ <uses-configuration android:reqTouchScreen="stylus"
+ android:reqKeyboardType="qwerty"/>
+</manifest>
+
diff --git a/dists/android/plugin-strings.xml b/dists/android/plugin-strings.xml
new file mode 100644
index 0000000000..363503f8d8
--- /dev/null
+++ b/dists/android/plugin-strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <string name="app_name">ScummVM plugin: "@PLUGIN_NAME@"</string>
+ <string name="app_desc">Game engine for: @PLUGIN_DESC@</string>
+</resources>
+
diff --git a/dists/android/res/layout/main.xml b/dists/android/res/layout/main.xml
index f5276ce41b..b6164edc96 100644
--- a/dists/android/res/layout/main.xml
+++ b/dists/android/res/layout/main.xml
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
+
<org.inodes.gus.scummvm.EditableSurfaceView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- android:id="@+id/main_surface"
- android:gravity="center"
- android:keepScreenOn="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_surface"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center"
+ android:keepScreenOn="true"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
/>
+
diff --git a/dists/engine-data/hugo.dat b/dists/engine-data/hugo.dat
index c404a1b456..556bb29436 100644
--- a/dists/engine-data/hugo.dat
+++ b/dists/engine-data/hugo.dat
Binary files differ
diff --git a/dists/iphone/Info.plist b/dists/iphone/Info.plist
index 9fc4debc92..f18cc61ede 100644
--- a/dists/iphone/Info.plist
+++ b/dists/iphone/Info.plist
@@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.3.0svn</string>
+ <string>1.3.0git</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.3.0svn</string>
+ <string>1.3.0git</string>
<key>CFBundleIconFile</key>
<string>icon.png</string>
<key>CFBundleIconFiles</key>
diff --git a/dists/irix/scummvm.spec b/dists/irix/scummvm.spec
index f19a4716b7..b6b1524a42 100644
--- a/dists/irix/scummvm.spec
+++ b/dists/irix/scummvm.spec
@@ -1,5 +1,5 @@
product scummvm
- id "ScummVM 1.3.0svn"
+ id "ScummVM 1.3.0git"
image sw
id "software"
version 18
diff --git a/dists/macosx/Info.plist b/dists/macosx/Info.plist
index f2fbbbf720..9e19926f3f 100644
--- a/dists/macosx/Info.plist
+++ b/dists/macosx/Info.plist
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>scummvm</string>
<key>CFBundleGetInfoString</key>
- <string>1.3.0svn, Copyright 2001-2011 The ScummVM team</string>
+ <string>1.3.0git, Copyright 2001-2011 The ScummVM team</string>
<key>CFBundleIconFile</key>
<string>scummvm.icns</string>
<key>CFBundleIdentifier</key>
@@ -21,9 +21,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.3.0svn</string>
+ <string>1.3.0git</string>
<key>CFBundleVersion</key>
- <string>1.3.0svn</string>
+ <string>1.3.0git</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
diff --git a/dists/msvc10/readme.txt b/dists/msvc10/readme.txt
index be7b8a4db5..fa077fa485 100644
--- a/dists/msvc10/readme.txt
+++ b/dists/msvc10/readme.txt
@@ -1,5 +1,5 @@
The Visual Studio project files can now be created automatically from the GCC
-files using the create_project tool inside the /tools/create_project folder.
+files using the create_project tool inside the /devtools/create_project folder.
To create the default project files, build create_project.exe, copy it inside
this folder and run the create_msvc10.bat file for a default build. You can run
diff --git a/dists/msvc8/readme.txt b/dists/msvc8/readme.txt
index 461e5c9bd5..95b55e973a 100644
--- a/dists/msvc8/readme.txt
+++ b/dists/msvc8/readme.txt
@@ -1,5 +1,5 @@
The Visual Studio project files can now be created automatically from the GCC
-files using the create_project tool inside the /tools/create_project folder.
+files using the create_project tool inside the /devtools/create_project folder.
To create the default project files, build create_project.exe, copy it inside
this folder and run the create_msvc8.bat file for a default build. You can run
diff --git a/dists/msvc9/readme.txt b/dists/msvc9/readme.txt
index 059c9e556b..410b8ea403 100644
--- a/dists/msvc9/readme.txt
+++ b/dists/msvc9/readme.txt
@@ -1,5 +1,5 @@
The Visual Studio project files can now be created automatically from the GCC
-files using the create_project tool inside the /tools/create_project folder.
+files using the create_project tool inside the /devtools/create_project folder.
To create the default project files, build create_project.exe, copy it inside
this folder and run the create_msvc9.bat file for a default build. You can run
diff --git a/dists/redhat/scummvm-tools.spec b/dists/redhat/scummvm-tools.spec
index 2370468e28..b034e4479e 100644
--- a/dists/redhat/scummvm-tools.spec
+++ b/dists/redhat/scummvm-tools.spec
@@ -7,7 +7,7 @@
# Prologue information
#------------------------------------------------------------------------------
Name : scummvm-tools
-Version : 1.3.0svn
+Version : 1.3.0git
Release : 1
Summary : ScummVM-related tools
Group : Interpreters
diff --git a/dists/redhat/scummvm.spec b/dists/redhat/scummvm.spec
index 950acf2a74..d0d273fc66 100644
--- a/dists/redhat/scummvm.spec
+++ b/dists/redhat/scummvm.spec
@@ -7,7 +7,7 @@
# Prologue information
#------------------------------------------------------------------------------
Name : scummvm
-Version : 1.3.0svn
+Version : 1.3.0git
Release : 1
Summary : Graphic adventure game interpreter
Group : Interpreters
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index e123bebd6f..61981b30c5 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -7,35 +7,36 @@ IDI_ICON ICON DISCARDABLE "../../icons/scummvm.ico"
#endif
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,3,0,0
- PRODUCTVERSION 1,3,0,0
- FILEFLAGSMASK 0x3fL
+ FILEVERSION 1,3,0,0
+ PRODUCTVERSION 1,3,0,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
- FILEFLAGS 0x1L
+ FILEFLAGS VS_FF_DEBUG
#else
- FILEFLAGS 0x0L
+ FILEFLAGS 0
#endif
- FILEOS 0x40004L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
- BLOCK "040904b0"
+ BLOCK "040904b0" // US English, Unicode
BEGIN
VALUE "Comments", "Look! A three headed monkey (TM)! .. Nice use of the TM!\0"
VALUE "FileDescription", "http://www.scummvm.org/\0"
- VALUE "FileVersion", "1.3.0svn\0"
+ VALUE "FileVersion", "1.3.0git\0"
VALUE "InternalName", "scummvm\0"
- VALUE "LegalCopyright", "Copyright Љ 2001-2010 The ScummVM Team\0"
+ VALUE "LegalCopyright", "Copyright Љ 2001-2011 The ScummVM Team\0"
VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0"
VALUE "OriginalFilename", "scummvm.exe\0"
VALUE "ProductName", "ScummVM\0"
- VALUE "ProductVersion", "1.3.0svn\0"
+ VALUE "ProductVersion", "1.3.0git\0"
END
END
+
BLOCK "VarFileInfo"
BEGIN
- VALUE "Translation", 0x409, 1200
+ VALUE "Translation", 0x409, 1200 // US English, Unicode
END
END
diff --git a/dists/scummvm.rc.in b/dists/scummvm.rc.in
index 17415f3d12..a0fcf82dbb 100644
--- a/dists/scummvm.rc.in
+++ b/dists/scummvm.rc.in
@@ -7,21 +7,21 @@ IDI_ICON ICON DISCARDABLE "../../icons/scummvm.ico"
#endif
VS_VERSION_INFO VERSIONINFO
- FILEVERSION @VER_MAJOR@,@VER_MINOR@,@VER_PATCH@,0
- PRODUCTVERSION @VER_MAJOR@,@VER_MINOR@,@VER_PATCH@,0
- FILEFLAGSMASK 0x3fL
+ FILEVERSION @VER_MAJOR@,@VER_MINOR@,@VER_PATCH@,0
+ PRODUCTVERSION @VER_MAJOR@,@VER_MINOR@,@VER_PATCH@,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
- FILEFLAGS 0x1L
+ FILEFLAGS VS_FF_DEBUG
#else
- FILEFLAGS 0x0L
+ FILEFLAGS 0
#endif
- FILEOS 0x40004L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
- BLOCK "040904b0"
+ BLOCK "040904b0" // US English, Unicode
BEGIN
VALUE "Comments", "Look! A three headed monkey (TM)! .. Nice use of the TM!\0"
VALUE "FileDescription", "http://www.scummvm.org/\0"
@@ -34,8 +34,9 @@ BEGIN
VALUE "ProductVersion", "@VERSION@\0"
END
END
+
BLOCK "VarFileInfo"
BEGIN
- VALUE "Translation", 0x409, 1200
+ VALUE "Translation", 0x409, 1200 // US English, Unicode
END
END
diff --git a/dists/slackware/scummvm.SlackBuild b/dists/slackware/scummvm.SlackBuild
index a53c1b2a57..0e5436b85e 100755
--- a/dists/slackware/scummvm.SlackBuild
+++ b/dists/slackware/scummvm.SlackBuild
@@ -9,7 +9,7 @@ if [ "$TMP" = "" ]; then
fi
PKG=$TMP/package-scummvm
-VERSION=1.3.0svn
+VERSION=1.3.0git
ARCH=i486
BUILD=1
diff --git a/dists/webos/README.WebOS b/dists/webos/README.WebOS
new file mode 100644
index 0000000000..5947d86f20
--- /dev/null
+++ b/dists/webos/README.WebOS
@@ -0,0 +1,37 @@
+README for the WebOS port of ScummVM
+------------------------------------
+
+INSTALLATION
+
+ When starting ScummVM the first time on a WebOS device it creates the
+ following directory structure on the flash drive:
+
+ ScummVM/
+ Extras/
+ Games/
+ Plugins/
+ Saves/
+ Screenshots/
+ Themes/
+
+ To install the games switch your WebOS device to USB drive mode and copy
+ the game folders into the ScummVM/Games directory. Then start ScummVM,
+ click "Add game" and select the game folder.
+
+CONTROLS
+
+ Touchscreen
+
+ The touchscreen operates like a touchpad. The mouse cursor is independent
+ of the touched point, it is moved relative to its current position.
+
+ Tap + movement: Mouse movement
+ Tap without movement: Left mouse button click
+ Tap held for >0.5s without movement: Right mouse button click
+ Tap held for >1s without movement: Middle mouse button click
+ Double Tap + movement: Drag and drop
+
+ Gesture area
+
+ Back gesture: Escape
+ Forward gesture: ScummVM menu
diff --git a/dists/webos/mojo/appinfo.json b/dists/webos/mojo/appinfo.json
new file mode 100644
index 0000000000..00762c9410
--- /dev/null
+++ b/dists/webos/mojo/appinfo.json
@@ -0,0 +1,10 @@
+{
+ "id": "org.scummvm.scummvm",
+ "version": "1.3.0001",
+ "vendor": "ScummVM Team",
+ "type": "pdk",
+ "main": "start",
+ "title": "ScummVM",
+ "icon": "icon.png",
+ "requiredMemory": 64
+}
diff --git a/dists/webos/mojo/icon.png b/dists/webos/mojo/icon.png
new file mode 100644
index 0000000000..eb9d8e37e7
--- /dev/null
+++ b/dists/webos/mojo/icon.png
Binary files differ
diff --git a/dists/webos/mojo/package.properties b/dists/webos/mojo/package.properties
new file mode 100644
index 0000000000..962e809ec6
--- /dev/null
+++ b/dists/webos/mojo/package.properties
@@ -0,0 +1 @@
+filemode.755=start,bin/scummvm
diff --git a/dists/webos/mojo/scummvmrc-default b/dists/webos/mojo/scummvmrc-default
new file mode 100644
index 0000000000..d29a0fc6db
--- /dev/null
+++ b/dists/webos/mojo/scummvmrc-default
@@ -0,0 +1,36 @@
+[scummvm]
+gui_theme=scummmodern
+mute=false
+speech_volume=192
+native_mt32=false
+midi_gain=100
+talkspeed=60
+subtitles=true
+multi_midi=false
+fullscreen=true
+sfx_volume=192
+music_volume=192
+autosave_period=300
+music_driver=auto
+opl_driver=auto
+aspect_ratio=false
+speech_mute=false
+enable_gs=false
+browser_lastpath=/media/internal/ScummVM/Games
+themepath=/media/internal/ScummVM/Themes
+savepath=/media/internal/ScummVM/Saves
+extrapath=/media/internal/ScummVM/Extras
+pluginspath=/media/internal/ScummVM/Plugins
+vkeybdpath=/media/cryptofs/apps/usr/palm/applications/org.scummvm.scummvm/share/scummvm
+
+[keymapper]
+keymap_global_MEN=FORWARD
+keymap_gui_VIR=C+k
+keymap_global_SKL=PERIOD
+keymap_global_SKC=ESCAPE
+keymap_gui_REM=AT
+keymap_global_PAU=SPACE
+keymap_gui_CLO=ESCAPE
+keymap_gui_CLI=RETURN
+keymap_global_VIR=C+k
+keymap_global_REM=AT
diff --git a/dists/webos/mojo/start b/dists/webos/mojo/start
new file mode 100755
index 0000000000..3bdb9a59d8
--- /dev/null
+++ b/dists/webos/mojo/start
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Setup directories
+APPDIR=$(readlink -f $(dirname $0))
+SCUMMVMDIR=/media/internal/ScummVM
+
+
+# Create the initial ScummVM directory structure
+mkdir -p $SCUMMVMDIR/Games
+mkdir -p $SCUMMVMDIR/Saves
+mkdir -p $SCUMMVMDIR/Screenshots
+mkdir -p $SCUMMVMDIR/Themes
+mkdir -p $SCUMMVMDIR/Extras
+mkdir -p $SCUMMVMDIR/Plugins
+
+# Install default configuration file if not already present
+if [ ! -f $SCUMMVMDIR/scummvmrc ]
+then
+ cp $APPDIR/scummvmrc-default $SCUMMVMDIR/scummvmrc
+fi
+
+# Copy themes to theme directory
+cp -f $APPDIR/share/scummvm/*.zip $SCUMMVMDIR/Themes
+
+# Change into the screenshots directory so screenshots are saved there
+cd $SCUMMVMDIR/Screenshots
+
+# Set library path so the app finds its custom shared libraries
+export LD_LIBRARY_PATH=$APPDIR/lib
+
+# Run the game
+exec $APPDIR/bin/scummvm -c $SCUMMVMDIR/scummvmrc
diff --git a/dists/wii/meta.xml b/dists/wii/meta.xml
index b881b4ce39..562d0982f5 100644
--- a/dists/wii/meta.xml
+++ b/dists/wii/meta.xml
@@ -2,7 +2,7 @@
<app version="1">
<name>ScummVM</name>
<coder>The ScummVM Team</coder>
- <version>1.3.0svn@REVISION@</version>
+ <version>1.3.0git@REVISION@</version>
<release_date>@TIMESTAMP@</release_date>
<short_description>Point &amp; Click Adventures</short_description>
<long_description>ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files. The clever part about this: ScummVM just replaces the executables shipped with the games, allowing you to play them on systems for which they were never designed!
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index fdc05f0ba9..632587f7f7 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -273,23 +273,16 @@ void AgiEngine::processEvents() {
}
void AgiEngine::pollTimer() {
- uint32 dm;
+ _lastTick += 50;
- if (_tickTimer < _lastTickTimer)
- _lastTickTimer = 0;
-
- while ((dm = _tickTimer - _lastTickTimer) < 5) {
+ while (_system->getMillis() < _lastTick) {
processEvents();
_console->onFrame();
_system->delayMillis(10);
_system->updateScreen();
}
- _lastTickTimer = _tickTimer;
-}
-void AgiEngine::agiTimerFunctionLow(void *refCon) {
- AgiEngine *self = (AgiEngine *)refCon;
- self->_tickTimer++;
+ _lastTick = _system->getMillis();
}
void AgiEngine::pause(uint32 msec) {
@@ -361,12 +354,12 @@ int AgiEngine::agiInit() {
switch (getVersion() >> 12) {
case 2:
- debug("Emulating Sierra AGI v%x.%03x\n",
+ debug("Emulating Sierra AGI v%x.%03x",
(int)(getVersion() >> 12) & 0xF,
(int)(getVersion()) & 0xFFF);
break;
case 3:
- debug("Emulating Sierra AGI v%x.002.%03x\n",
+ debug("Emulating Sierra AGI v%x.002.%03x",
(int)(getVersion() >> 12) & 0xF,
(int)(getVersion()) & 0xFFF);
break;
@@ -532,9 +525,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_allowSynthetic = false;
- _tickTimer = 0;
- _lastTickTimer = 0;
-
_intobj = NULL;
_menu = NULL;
@@ -646,11 +636,10 @@ void AgiEngine::initialize() {
_lastSaveTime = 0;
- _timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, this);
+ _lastTick = _system->getMillis();
debugC(2, kDebugLevelMain, "Detect game");
-
if (agiDetectGame() == errOK) {
_game.state = STATE_LOADED;
debugC(2, kDebugLevelMain, "game loaded");
@@ -662,8 +651,6 @@ void AgiEngine::initialize() {
}
AgiEngine::~AgiEngine() {
- _timer->removeTimerProc(agiTimerFunctionLow);
-
// If the engine hasn't been initialized yet via AgiEngine::initialize(), don't attempt to free any resources,
// as they haven't been allocated. Fixes bug #1742432 - AGI: Engine crashes if no game is detected
if (_game.state == STATE_INIT) {
@@ -719,7 +706,7 @@ void AgiEngine::parseFeatures() {
/* FIXME: Seems this method doesn't really do anything. It might
be a leftover that could be removed, except that some of its
intended purpose may still need to be reimplemented.
-
+
[0:29] <Fingolfin> can you tell me what the point behind AgiEngine::parseFeatures() is?
[0:30] <_sev> when games are created with WAGI studio
[0:31] <_sev> it creates .wag site with game-specific features such as full game title, whether to use AGIMOUSE etc
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 89b116daec..df19f55b52 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -810,9 +810,7 @@ public:
Common::Error saveGameState(int slot, const char *desc);
private:
-
- uint32 _tickTimer;
- uint32 _lastTickTimer;
+ uint32 _lastTick;
int _keyQueue[KEY_QUEUE_SIZE];
int _keyQueueStart;
@@ -883,7 +881,6 @@ public:
virtual bool isKeypress();
virtual void clearKeyQueue();
- static void agiTimerFunctionLow(void *refCon);
void initPriTable();
void newInputMode(InputMode mode);
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 6e9a996756..0a53f0c4f4 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -218,7 +218,7 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
}
SaveStateList AgiMetaEngine::listSaves(const char *target) const {
- const uint32 AGIflag = MKID_BE('AGI:');
+ const uint32 AGIflag = MKTAG('A','G','I',':');
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
char saveDesc[31];
@@ -257,7 +257,7 @@ void AgiMetaEngine::removeSaveState(const char *target, int slot) const {
}
SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
- const uint32 AGIflag = MKID_BE('AGI:');
+ const uint32 AGIflag = MKTAG('A','G','I',':');
char fileName[MAXPATHLEN];
sprintf(fileName, "%s.%03d", target, slot);
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 711701f55a..4689915007 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -528,6 +528,10 @@ static const AGIGameDescription gameDescriptions[] = {
// Space Quest 2 (PC 5.25") 2.0A [AGI 2.912]
GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC),
+ // reported by RadG (radg123) in bug report #3260349
+ // Space Quest 2 (Spanish)
+ GAME_LPS("sq2", "", "1ae7640dd4d253c3ac2d708d61a35379", 426, Common::ES_ESP, 0x2917, GID_SQ2, Common::kPlatformPC),
+
// Space Quest 2 (Russian)
GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC),
@@ -569,6 +573,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3),
FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE),
+ FANMADE("AGI Combat", "0be6a8a9e19203dcca0067d280798871"),
FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"),
FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"),
FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"),
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 7f8d99cc2f..58982a2931 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -799,9 +799,8 @@ void GfxMgr::initPalette(const uint8 *p, uint colorCount, uint fromBits, uint to
const uint destMax = (1 << toBits) - 1;
for (uint col = 0; col < colorCount; col++) {
for (uint comp = 0; comp < 3; comp++) { // Convert RGB components
- _palette[col * 4 + comp] = (p[col * 3 + comp] * destMax) / srcMax;
+ _palette[col * 3 + comp] = (p[col * 3 + comp] * destMax) / srcMax;
}
- _palette[col * 4 + 3] = 0; // Set alpha to zero
}
}
@@ -928,11 +927,11 @@ static const byte appleIIgsMouseCursor[] = {
};
/**
- * RGBA-palette for the black and white SCI and Apple IIGS arrow cursors.
+ * RGB-palette for the black and white SCI and Apple IIGS arrow cursors.
*/
static const byte sciMouseCursorPalette[] = {
- 0x00, 0x00, 0x00, 0x00, // Black
- 0xFF, 0xFF, 0xFF, 0x00 // White
+ 0x00, 0x00, 0x00, // Black
+ 0xFF, 0xFF, 0xFF // White
};
/**
@@ -957,13 +956,13 @@ static const byte amigaMouseCursor[] = {
};
/**
- * RGBA-palette for the Amiga-style arrow cursor
+ * RGB-palette for the Amiga-style arrow cursor
* and the Amiga-style busy cursor.
*/
static const byte amigaMouseCursorPalette[] = {
- 0x00, 0x00, 0x00, 0x00, // Black
- 0xDE, 0x20, 0x21, 0x00, // Red
- 0xFF, 0xCF, 0xAD, 0x00 // Light red
+ 0x00, 0x00, 0x00, // Black
+ 0xDE, 0x20, 0x21, // Red
+ 0xFF, 0xCF, 0xAD // Light red
};
/**
@@ -994,17 +993,17 @@ static const byte busyAmigaMouseCursor[] = {
void GfxMgr::setCursor(bool amigaStyleCursor, bool busy) {
if (busy) {
- CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4);
+ CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 3);
CursorMan.replaceCursor(busyAmigaMouseCursor, 13, 16, 7, 8, 0);
return;
}
if (!amigaStyleCursor) {
- CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4);
+ CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 3);
CursorMan.replaceCursor(sciMouseCursor, 11, 16, 1, 1, 0);
} else { // amigaStyleCursor
- CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4);
+ CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 3);
CursorMan.replaceCursor(amigaMouseCursor, 8, 11, 1, 1, 0);
}
}
@@ -1012,12 +1011,12 @@ void GfxMgr::setCursor(bool amigaStyleCursor, bool busy) {
void GfxMgr::setCursorPalette(bool amigaStyleCursor) {
if (!amigaStyleCursor) {
if (_currentCursorPalette != 1) {
- CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4);
+ CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 3);
_currentCursorPalette = 1;
}
} else { // amigaStyleCursor
if (_currentCursorPalette != 2) {
- CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4);
+ CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 3);
_currentCursorPalette = 2;
}
}
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index 18f323d596..60fbea2285 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -41,7 +41,7 @@ class GfxMgr {
private:
AgiBase *_vm;
- uint8 _palette[256 * 4];
+ uint8 _palette[256 * 3];
uint8 *_agiScreen;
unsigned char *_screen;
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index fe864d7659..7457a317c2 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -42,8 +42,7 @@ namespace Agi {
PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) {
// Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ syncSoundSettings();
_rnd = new Common::RandomSource();
@@ -122,9 +121,6 @@ void PreAgiEngine::initialize() {
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- //_timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, NULL);
-
debugC(2, kDebugLevelMain, "Detect game");
// clear all resources and events
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index ea041a93c7..10ca797587 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -1003,7 +1003,7 @@ bool Mickey::loadGame() {
if (_vm->getSelection(kSelAnyKey) == 0)
return false;
} else {
- if (infile->readUint32BE() != MKID_BE('MICK')) {
+ if (infile->readUint32BE() != MKTAG('M','I','C','K')) {
warning("Mickey::loadGame wrong save game format");
return false;
}
@@ -1120,7 +1120,7 @@ void Mickey::saveGame() {
if (_vm->getSelection(kSelAnyKey) == 0)
return;
} else {
- outfile->writeUint32BE(MKID_BE('MICK')); // header
+ outfile->writeUint32BE(MKTAG('M','I','C','K')); // header
outfile->writeByte(MSA_SAVEGAME_VERSION);
outfile->writeByte(_game.iRoom);
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index 643cbd86a9..e97c144872 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -1159,7 +1159,7 @@ void Winnie::saveGame() {
if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile)))
return;
- outfile->writeUint32BE(MKID_BE('WINN')); // header
+ outfile->writeUint32BE(MKTAG('W','I','N','N')); // header
outfile->writeByte(WTP_SAVEGAME_VERSION);
outfile->writeByte(_game.fSound);
@@ -1195,7 +1195,7 @@ void Winnie::loadGame() {
if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile)))
return;
- if (infile->readUint32BE() == MKID_BE('WINN')) {
+ if (infile->readUint32BE() == MKTAG('W','I','N','N')) {
saveVersion = infile->readByte();
if (saveVersion != WTP_SAVEGAME_VERSION)
warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, WTP_SAVEGAME_VERSION);
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 94df063609..9194cc642c 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -53,7 +53,7 @@
namespace Agi {
-static const uint32 AGIflag = MKID_BE('AGI:');
+static const uint32 AGIflag = MKTAG('A','G','I',':');
int AgiEngine::saveGame(const char *fileName, const char *description) {
char gameIDstring[8] = "gameIDX";
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index 4ed4fb7bab..11bf5a9034 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -766,7 +766,7 @@ bool SoundGen2GS::loadInstruments() {
// load the instrument headers and their sample data.
// None of the tested SIERRASTANDARD-files have zeroes in them so
// there's no need to check for prematurely ending samples here.
- setProgramChangeMapping(&exeInfo->instSet.progToInst);
+ setProgramChangeMapping(exeInfo->instSet->progToInst);
return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo);
}
@@ -792,29 +792,29 @@ static const MidiProgramChangeMapping progToInstMappingV2 = {
/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */
static const InstrumentSetInfo instSetV1 = {
- 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1
+ 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", &progToInstMappingV1
};
/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */
static const InstrumentSetInfo instSetV2 = {
- 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2
+ 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", &progToInstMappingV2
};
/** Information about different Apple IIGS AGI executables. */
static const IIgsExeInfo IIgsExeInfos[] = {
- {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1},
- {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2},
- {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2},
- {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2},
- {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2},
- {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2},
- {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2},
- {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2},
- {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2},
- {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2},
- {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2},
- {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2},
- {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2}
+ {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, &instSetV1},
+ {GID_LSL1, "LL", 0x1003, 141003, 0x844E, &instSetV2},
+ {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, &instSetV2},
+ {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, &instSetV2},
+ {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, &instSetV2},
+ {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, &instSetV2},
+ {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, &instSetV2},
+ {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, &instSetV2},
+ {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, &instSetV2},
+ {GID_MH1, "MH", 0x2004, 147678, 0x8979, &instSetV2},
+ {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, &instSetV2},
+ {GID_BC, "BC", 0x3001, 148192, 0x8979, &instSetV2},
+ {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, &instSetV2}
};
/**
@@ -844,20 +844,20 @@ bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIg
file.close();
// Check that we got enough data to be able to parse the instruments
- if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) {
+ if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet->byteCount)) {
// Check instrument set's length (The info's saved in the executable)
data->seek(exeInfo.instSetStart - 4);
uint16 instSetByteCount = data->readUint16LE();
- if (instSetByteCount != exeInfo.instSet.byteCount) {
+ if (instSetByteCount != exeInfo.instSet->byteCount) {
debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
- instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str());
+ instSetByteCount, exeInfo.instSet->byteCount, exePath.getPath().c_str());
}
// Check instrument set's md5sum
data->seek(exeInfo.instSetStart);
- Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet.byteCount);
- if (md5str != exeInfo.instSet.md5) {
+ Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet->byteCount);
+ if (md5str != exeInfo.instSet->md5) {
warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
md5str.c_str(), exePath.getPath().c_str());
}
@@ -867,20 +867,20 @@ bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIg
// Load the instruments
_instruments.clear();
- _instruments.reserve(exeInfo.instSet.instCount);
+ _instruments.reserve(exeInfo.instSet->instCount);
IIgsInstrumentHeader instrument;
- for (uint i = 0; i < exeInfo.instSet.instCount; i++) {
+ for (uint i = 0; i < exeInfo.instSet->instCount; i++) {
if (!instrument.read(*data)) {
warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
- i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str());
+ i + 1, exeInfo.instSet->instCount, exePath.getPath().c_str());
break;
}
_instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array
}
// Loading was successful only if all instruments were loaded successfully
- loadedOk = (_instruments.size() == exeInfo.instSet.instCount);
+ loadedOk = (_instruments.size() == exeInfo.instSet->instCount);
} else // Couldn't read enough data from the executable file
warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str());
@@ -899,7 +899,7 @@ bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo
if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) {
// Check wave file's md5sum
Common::String md5str = Common::computeStreamMD5AsString(*uint8Wave, SIERRASTANDARD_SIZE);
- if (md5str != exeInfo.instSet.waveFileMd5) {
+ if (md5str != exeInfo.instSet->waveFileMd5) {
warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
"Please report the information on the previous line to the ScummVM team.\n" \
"Using the wave file as it is - music may sound weird", md5str.c_str(), exeInfo.exePrefix);
diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h
index 391646d6ce..76f0642b7b 100644
--- a/engines/agi/sound_2gs.h
+++ b/engines/agi/sound_2gs.h
@@ -238,7 +238,7 @@ struct InstrumentSetInfo {
uint instCount; ///< Amount of instrument in the set
const char *md5; ///< MD5 hex digest of the whole instrument set
const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
- const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping
+ const MidiProgramChangeMapping *progToInst; ///< Program change to instrument number mapping
};
/** Apple IIGS AGI executable file information. */
@@ -248,7 +248,7 @@ struct IIgsExeInfo {
uint agiVer; ///< Apple IIGS AGI version number, not strictly needed
uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes
uint instSetStart; ///< Starting offset of the instrument set inside the executable file
- const InstrumentSetInfo &instSet; ///< Information about the used instrument set
+ const InstrumentSetInfo *instSet; ///< Information about the used instrument set
};
class IIgsMidiChannel {
diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp
index 47cab0019f..986715721f 100644
--- a/engines/agi/sound_midi.cpp
+++ b/engines/agi/sound_midi.cpp
@@ -71,134 +71,47 @@ MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A
warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len);
}
-SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) {
- DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
- _driver = MidiDriver::createMidi(dev);
-
- if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) {
- _nativeMT32 = true;
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- } else {
- _nativeMT32 = false;
- }
-
- memset(_channel, 0, sizeof(_channel));
- memset(_channelVolume, 127, sizeof(_channelVolume));
- _masterVolume = 0;
- this->open();
- _smfParser = MidiParser::createParser_SMF();
- _midiMusicData = NULL;
-}
-
-SoundGenMIDI::~SoundGenMIDI() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _smfParser->setMidiDriver(NULL);
- delete _smfParser;
- delete[] _midiMusicData;
-}
-
-void SoundGenMIDI::setChannelVolume(int channel) {
- int newVolume = _channelVolume[channel] * _masterVolume / 255;
- _channel[channel]->volume(newVolume);
-}
-
-void SoundGenMIDI::setVolume(int volume) {
- Common::StackLock lock(_mutex);
-
- volume = CLIP(volume, 0, 255);
- if (_masterVolume == volume)
- return;
- _masterVolume = volume;
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- setChannelVolume(i);
- }
- }
-}
-
-int SoundGenMIDI::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _isGM(false) {
+ MidiPlayer::createDriver(MDT_MIDI | MDT_ADLIB);
int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- return 0;
-}
-
-void SoundGenMIDI::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ // FIXME: We need to cast "this" here due to the effects of
+ // multiple inheritance. This hack can go away once this
+ // setTimerCallback() has been moved inside Audio::MidiPlayer code.
+ _driver->setTimerCallback(static_cast<Audio::MidiPlayer *>(this), &timerCallback);
+ }
}
void SoundGenMIDI::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (_channel[b & 0x0F])
- return;
- }
- if (!_channel[channel]) {
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ Audio::MidiPlayer::send(b);
+}
+
+void SoundGenMIDI::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
// If a new channel is allocated during the playback, make sure
// its volume is correctly initialized.
- if (_channel[channel])
- setChannelVolume(channel);
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
}
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void SoundGenMIDI::metaEvent(byte type, byte *data, uint16 length) {
-
- switch (type) {
- case 0x2F: // End of Track
- stop();
- _vm->_sound->soundIsFinished();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
-void SoundGenMIDI::onTimer(void *refCon) {
- SoundGenMIDI *music = (SoundGenMIDI *)refCon;
- Common::StackLock lock(music->_mutex);
-
- if (music->_parser)
- music->_parser->onTimer();
+void SoundGenMIDI::endOfTrack() {
+ stop();
+ _vm->_sound->soundIsFinished();
}
void SoundGenMIDI::play(int resnum) {
@@ -211,13 +124,13 @@ void SoundGenMIDI::play(int resnum) {
track = (MIDISound *)_vm->_game.sounds[resnum];
// Convert AGI Sound data to MIDI
- int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData);
+ int midiMusicSize = convertSND2MIDI(track->_data, &_midiData);
- if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) {
- MidiParser *parser = _smfParser;
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_midiData, midiMusicSize)) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_parser = parser;
@@ -225,40 +138,11 @@ void SoundGenMIDI::play(int resnum) {
syncVolume();
_isPlaying = true;
+ } else {
+ delete parser;
}
}
-void SoundGenMIDI::stop() {
- Common::StackLock lock(_mutex);
-
- if (!_isPlaying)
- return;
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
- }
-}
-
-void SoundGenMIDI::pause() {
- setVolume(-1);
- _isPlaying = false;
-}
-
-void SoundGenMIDI::resume() {
- syncVolume();
- _isPlaying = true;
-}
-
-void SoundGenMIDI::syncVolume() {
- int volume = ConfMan.getInt("music_volume");
- if (ConfMan.getBool("mute")) {
- volume = -1;
- }
- setVolume(volume);
-}
-
/* channel / intrument setup: */
/* most songs are good with this: */
diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h
index 059d41208c..5733358fee 100644
--- a/engines/agi/sound_midi.h
+++ b/engines/agi/sound_midi.h
@@ -28,9 +28,9 @@
#ifndef AGI_SOUND_MIDI_H
#define AGI_SOUND_MIDI_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "common/mutex.h"
+#include "agi/sound.h"
+
+#include "audio/midiplayer.h"
namespace Agi {
@@ -46,65 +46,24 @@ protected:
uint16 _type; ///< Sound resource type
};
-class SoundGenMIDI : public SoundGen, public MidiDriver {
+class SoundGenMIDI : public SoundGen, public Audio::MidiPlayer {
public:
SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer);
- ~SoundGenMIDI();
void play(int resnum);
- void stop();
-
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
- void syncVolume();
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
- void pause();
- void resume();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
- void setGM(bool isGM) { _isGM = isGM; }
-
- // MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
+ // We must overload stop() here to implement the pure virtual
+ // stop() method of the SoundGen class.
+ void stop() { Audio::MidiPlayer::stop(); }
- void metaEvent(byte type, byte *data, uint16 length);
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- // Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
+ // Overload Audio::MidiPlayer method
+ virtual void sendToChannel(byte channel, uint32 b);
+ virtual void endOfTrack();
private:
-
- static void onTimer(void *data);
- void setChannelVolume(int channel);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_smfParser;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
-
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
-
- byte *_midiMusicData;
SoundMgr *_manager;
};
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index ae95bb0d2b..498c7e4961 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -470,7 +470,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_planarBuf = 0;
_midiEnabled = false;
- _nativeMT32 = false;
_vgaTickCounter = 0;
@@ -555,30 +554,13 @@ Common::Error AGOSEngine::init() {
((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) ||
(getPlatform() == Common::kPlatformPC)) {
- // Setup midi driver
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
- _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-
- _driver = MidiDriver::createMidi(dev);
-
- if (_nativeMT32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _midi.setNativeMT32(_nativeMT32);
- _midi.mapMT32toGM(getGameType() != GType_SIMON2 && !_nativeMT32);
-
- _midi.setDriver(_driver);
-
- int ret = _midi.open();
+ int ret = _midi.open(getGameType());
if (ret)
- warning("MIDI Player init failed: \"%s\"", _midi.getErrorName (ret));
+ warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName(ret));
_midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
-
_midiEnabled = true;
- } else {
- _driver = NULL;
}
// Setup mixer
@@ -734,7 +716,7 @@ void AGOSEngine_Simon2::setupGame() {
_itemMemSize = 20000;
_tableMemSize = 100000;
// Check whether to use MT-32 MIDI tracks in Simon the Sorcerer 2
- if (getGameType() == GType_SIMON2 && _nativeMT32)
+ if (getGameType() == GType_SIMON2 && _midi.hasNativeMT32())
_musicIndexBase = (1128 + 612) / 4;
else
_musicIndexBase = 1128 / 4;
@@ -895,9 +877,6 @@ void AGOSEngine::setupGame() {
}
AGOSEngine::~AGOSEngine() {
- _midi.close();
- delete _driver;
-
_system->getAudioCDManager()->stop();
for (uint i = 0; i < _itemHeap.size(); i++) {
@@ -1045,18 +1024,15 @@ uint32 AGOSEngine::getTime() const {
}
void AGOSEngine::syncSoundSettings() {
- // Sync the engine with the config manager
- int soundVolumeMusic = ConfMan.getInt("music_volume");
- int soundVolumeSFX = ConfMan.getInt("sfx_volume");
- int soundVolumeSpeech = ConfMan.getInt("speech_volume");
+ Engine::syncSoundSettings();
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : (_musicPaused ? 0 : soundVolumeMusic)));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech));
+ // Sync the engine with the config manager
+ int soundVolumeMusic = ConfMan.getInt("music_volume");
+ int soundVolumeSFX = ConfMan.getInt("sfx_volume");
if (_midiEnabled)
_midi.setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX));
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index a2962cd827..bf51b31c43 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -529,8 +529,8 @@ protected:
uint16 _PVCount1;
uint16 _GPVCount1;
- uint8 _currentPalette[1024];
- uint8 _displayPalette[1024];
+ uint8 _currentPalette[768];
+ uint8 _displayPalette[768];
byte *_planarBuf;
byte _videoBuf1[32000];
@@ -550,9 +550,7 @@ protected:
byte _lettersToPrintBuf[80];
MidiPlayer _midi;
- MidiDriver *_driver;
bool _midiEnabled;
- bool _nativeMT32;
int _vgaTickCounter;
@@ -2018,7 +2016,7 @@ protected:
void scrollOracleUp();
void scrollOracleDown();
- void listSaveGames(int n);
+ void listSaveGamesFeeble();
void saveUserGame(int slot);
void windowBackSpace(WindowBlock *window);
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 4c01f6b826..acdc0084c4 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -87,7 +87,7 @@ void MoviePlayer::play() {
if (_vm->getBitFlag(41)) {
_vm->fillBackFromFront();
} else {
- uint8 palette[1024];
+ uint8 palette[768];
memset(palette, 0, sizeof(palette));
_vm->clearSurfaces();
_vm->_system->getPaletteManager()->setPalette(palette, 0, 256);
@@ -301,7 +301,7 @@ void MoviePlayerDXA::stopVideo() {
void MoviePlayerDXA::startSound() {
uint32 offset, size;
- if (getSoundTag() == MKID_BE('WAVE')) {
+ if (getSoundTag() == MKTAG('W','A','V','E')) {
size = _fileStream->readUint32BE();
if (_sequenceNum) {
@@ -368,7 +368,7 @@ void MoviePlayerDXA::handleNextFrame() {
bool MoviePlayerDXA::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
+ copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
Common::Rational soundTime(_mixer->getSoundElapsedTime(_bgSound), 1000);
@@ -482,7 +482,7 @@ void MoviePlayerSMK::nextFrame() {
bool MoviePlayerSMK::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
+ copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
uint32 waitTime = getTimeToNextFrame();
diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp
index 5ff2f014a6..cf42fe1f36 100644
--- a/engines/agos/cursor.cpp
+++ b/engines/agos/cursor.cpp
@@ -781,8 +781,8 @@ void AGOSEngine_Simon1::initMouse() {
}
static const byte mouseCursorPalette[] = {
- 0x00, 0x00, 0x00, 0x00, // Black
- 0xFF, 0xFF, 0xFF, 0x00, // White
+ 0x00, 0x00, 0x00, // Black
+ 0xFF, 0xFF, 0xFF // White
};
void AGOSEngine::initMouse() {
@@ -792,7 +792,7 @@ void AGOSEngine::initMouse() {
memset(_mouseData, 0xFF, _maxCursorWidth * _maxCursorHeight);
- CursorMan.replaceCursorPalette(mouseCursorPalette, 0, ARRAYSIZE(mouseCursorPalette) / 4);
+ CursorMan.replaceCursorPalette(mouseCursorPalette, 0, ARRAYSIZE(mouseCursorPalette) / 3);
}
void AGOSEngine::drawMousePointer() {
diff --git a/engines/agos/debug.cpp b/engines/agos/debug.cpp
index cb11d65218..d0dc8cc42e 100644
--- a/engines/agos/debug.cpp
+++ b/engines/agos/debug.cpp
@@ -436,7 +436,7 @@ static const byte bmp_hdr[] = {
0x00, 0x01, 0x00, 0x00,
};
-void dumpBMP(const char *filename, int16 w, int16 h, const byte *bytes, const uint32 *palette) {
+void dumpBMP(const char *filename, int16 w, int16 h, const byte *bytes, const byte *palette) {
Common::DumpFile out;
byte my_hdr[sizeof(bmp_hdr)];
int i;
@@ -454,11 +454,11 @@ void dumpBMP(const char *filename, int16 w, int16 h, const byte *bytes, const ui
out.write(my_hdr, sizeof(my_hdr));
- for (i = 0; i != 256; i++, palette++) {
+ for (i = 0; i != 256; i++, palette += 3) {
byte color[4];
- color[0] = (byte)(*palette >> 16);
- color[1] = (byte)(*palette >> 8);
- color[2] = (byte)(*palette);
+ color[0] = palette[2];
+ color[1] = palette[1];
+ color[2] = palette[0];
color[3] = 0;
out.write(color, 4);
}
@@ -565,7 +565,7 @@ void AGOSEngine::dumpBitmap(const char *filename, const byte *offs, uint16 w, ui
}
}
- dumpBMP(filename, w, h, imageBuffer, (const uint32 *)palette);
+ dumpBMP(filename, w, h, imageBuffer, palette);
free(imageBuffer);
}
@@ -594,7 +594,7 @@ void AGOSEngine::palLoad(byte *pal, const byte *vga1, int a, int b) {
}
if (getGameType() == GType_PN && (getFeatures() & GF_EGA)) {
- memcpy(palptr, _displayPalette, 64);
+ memcpy(palptr, _displayPalette, 3 * 16);
} else if (getGameType() == GType_PN || getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
src = vga1 + READ_BE_UINT16(vga1 + 6) + b * 32;
@@ -603,9 +603,8 @@ void AGOSEngine::palLoad(byte *pal, const byte *vga1, int a, int b) {
palptr[0] = ((color & 0xf00) >> 8) * 32;
palptr[1] = ((color & 0x0f0) >> 4) * 32;
palptr[2] = ((color & 0x00f) >> 0) * 32;
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
src += 2;
} while (--num);
} else {
@@ -615,9 +614,8 @@ void AGOSEngine::palLoad(byte *pal, const byte *vga1, int a, int b) {
palptr[0] = src[0] << 2;
palptr[1] = src[1] << 2;
palptr[2] = src[2] << 2;
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
src += 3;
} while (--num);
}
@@ -627,7 +625,7 @@ void AGOSEngine::dumpVgaBitmaps(uint16 zoneNum) {
uint16 width, height, flags;
uint32 offs, curOffs = 0;
const byte *p2;
- byte pal[1024];
+ byte pal[768];
uint16 zone = (getGameType() == GType_PN) ? 0 : zoneNum;
VgaPointersEntry *vpe = &_vgaBufferPointers[zone];
diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp
index 37abe9324c..317c68d31a 100644
--- a/engines/agos/draw.cpp
+++ b/engines/agos/draw.cpp
@@ -779,8 +779,8 @@ void AGOSEngine::setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height) {
void AGOSEngine::displayScreen() {
if (_fastFadeInFlag == 0 && _paletteFlag == 1) {
_paletteFlag = 0;
- if (memcmp(_displayPalette, _currentPalette, 1024)) {
- memcpy(_currentPalette, _displayPalette, 1024);
+ if (memcmp(_displayPalette, _currentPalette, sizeof(_currentPalette))) {
+ memcpy(_currentPalette, _displayPalette, sizeof(_displayPalette));
_system->getPaletteManager()->setPalette(_displayPalette, 0, 256);
}
}
@@ -860,7 +860,7 @@ void AGOSEngine::fastFadeIn() {
slowFadeIn();
} else {
_paletteFlag = false;
- memcpy(_currentPalette, _displayPalette, 1024);
+ memcpy(_currentPalette, _displayPalette, sizeof(_displayPalette));
_system->getPaletteManager()->setPalette(_displayPalette, 0, _fastFadeInFlag);
_fastFadeInFlag = 0;
}
@@ -879,15 +879,15 @@ void AGOSEngine::slowFadeIn() {
src = _displayPalette;
dst = _currentPalette;
- for (p = _fastFadeInFlag; p !=0; p -= 3) {
+ for (p = _fastFadeInFlag; p != 0; p -= 3) {
if (src[0] >= c)
dst[0] += 4;
if (src[1] >= c)
dst[1] += 4;
if (src[2] >= c)
dst[2] += 4;
- src += 4;
- dst += 4;
+ src += 3;
+ dst += 3;
}
_system->getPaletteManager()->setPalette(_currentPalette, 0, _fastFadeCount);
delay(5);
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index b784e4fcb3..710c9ddd7e 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -1041,7 +1041,7 @@ void AGOSEngine::paletteFadeOut(byte *palPtr, uint num, uint size) {
p[2] -= size;
else
p[2] = 0;
- p += 4;
+ p += 3;
} while (--num);
}
diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp
index 08a3d4e2f0..ca603db1fa 100644
--- a/engines/agos/icons.cpp
+++ b/engines/agos/icons.cpp
@@ -484,7 +484,7 @@ void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask)
Item *item_ptr_org = itemRef;
WindowBlock *window;
uint width, height;
- uint k, i, curWidth;
+ uint k, curWidth;
bool item_again, showArrows;
uint x_pos, y_pos;
const int iconSize = (getGameType() == GType_SIMON2) ? 20 : 1;
@@ -502,8 +502,6 @@ void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask)
height = window->height / 3;
}
- i = 0;
-
if (window == NULL)
return;
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index fe2d1cd25b..a37c96a787 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -25,6 +25,7 @@
+#include "common/config-manager.h"
#include "common/file.h"
#include "common/system.h"
@@ -44,7 +45,6 @@ MidiPlayer::MidiPlayer() {
// between songs.
_driver = 0;
_map_mt32_to_gm = false;
- _passThrough = false;
_enable_sfx = true;
_current = 0;
@@ -62,16 +62,34 @@ MidiPlayer::MidiPlayer() {
}
MidiPlayer::~MidiPlayer() {
- _mutex.lock();
- close();
- _mutex.unlock();
+ stop();
+
+ Common::StackLock lock(_mutex);
+ if (_driver) {
+ _driver->close();
+ delete _driver;
+ }
+ _driver = NULL;
+ clearConstructs();
}
-int MidiPlayer::open() {
- // Don't ever call open without first setting the output driver!
+int MidiPlayer::open(int gameType) {
+ // Don't call open() twice!
+ assert(!_driver);
+
+ // Setup midi driver
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (gameType == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+
+ _driver = MidiDriver::createMidi(dev);
if (!_driver)
return 255;
+ if (_nativeMT32)
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
+ _map_mt32_to_gm = (gameType != GType_SIMON2 && !_nativeMT32);
+
int ret = _driver->open();
if (ret)
return ret;
@@ -85,25 +103,10 @@ int MidiPlayer::open() {
return 0;
}
-void MidiPlayer::close() {
- stop();
-// _system->lockMutex(_mutex);
- if (_driver)
- _driver->close();
- _driver = NULL;
- clearConstructs();
-// _system->unlockMutex(_mutex);
-}
-
void MidiPlayer::send(uint32 b) {
if (!_current)
return;
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
byte channel = (byte)(b & 0x0F);
if ((b & 0xFFF0) == 0x07B0) {
// Adjust volume changes by master music and master sfx volume.
@@ -205,6 +208,8 @@ void MidiPlayer::onTimer(void *data) {
}
void MidiPlayer::startTrack(int track) {
+ Common::StackLock lock(_mutex);
+
if (track == _currentTrack)
return;
@@ -212,8 +217,6 @@ void MidiPlayer::startTrack(int track) {
if (track >= _music.num_songs)
return;
- _mutex.lock();
-
if (_music.parser) {
_current = &_music;
delete _music.parser;
@@ -234,9 +237,7 @@ void MidiPlayer::startTrack(int track) {
_currentTrack = (byte)track;
_music.parser = parser; // That plugs the power cord into the wall
} else if (_music.parser) {
- _mutex.lock();
if (!_music.parser->setTrack(track)) {
- _mutex.unlock();
return;
}
_currentTrack = (byte)track;
@@ -244,8 +245,6 @@ void MidiPlayer::startTrack(int track) {
_music.parser->jumpToTick(0);
_current = 0;
}
-
- _mutex.unlock();
}
void MidiPlayer::stop() {
@@ -301,19 +300,6 @@ void MidiPlayer::setVolume(int musicVol, int sfxVol) {
}
}
-void MidiPlayer::setDriver(MidiDriver *md) {
- // Don't try to set this more than once.
- if (_driver)
- return;
- _driver = md;
-}
-
-void MidiPlayer::mapMT32toGM(bool map) {
- Common::StackLock lock(_mutex);
-
- _map_mt32_to_gm = map;
-}
-
void MidiPlayer::setLoop(bool loop) {
Common::StackLock lock(_mutex);
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index 9c8303ba3c..ad69a3ddde 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -55,12 +55,11 @@ struct MusicInfo {
}
};
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
protected:
Common::Mutex _mutex;
MidiDriver *_driver;
bool _map_mt32_to_gm;
- bool _passThrough;
bool _nativeMT32;
MusicInfo _music;
@@ -97,8 +96,7 @@ public:
void loadXMIDI(Common::File *in, bool sfx = false);
void loadS1D(Common::File *in, bool sfx = false);
- void mapMT32toGM(bool map);
- void setNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
+ bool hasNativeMT32() const { return _nativeMT32; }
void setLoop(bool loop);
void startTrack(int track);
void queueTrack(int track, bool loop);
@@ -107,27 +105,17 @@ public:
void stop();
void pause(bool b);
- int getMusicVolume() { return _musicVolume; }
- int getSFXVolume() { return _sfxVolume; }
+ int getMusicVolume() const { return _musicVolume; }
+ int getSFXVolume() const { return _sfxVolume; }
void setVolume(int musicVol, int sfxVol);
- void setDriver(MidiDriver *md);
public:
- // MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
+ int open(int gameType);
- void metaEvent(byte type, byte *data, uint16 length);
- void setPassThrough(bool b) { _passThrough = b; }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
- // Timing functions - MidiDriver now operates timers
- void setTimerCallback(void *timer_param, void (*timer_proc) (void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- // Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
};
} // End of namespace AGOS
diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp
index 0a4ab8246f..8ff79965e4 100644
--- a/engines/agos/oracle.cpp
+++ b/engines/agos/oracle.cpp
@@ -369,7 +369,7 @@ void AGOSEngine_Feeble::swapCharacterLogo() {
}
}
-void AGOSEngine_Feeble::listSaveGames(int n) {
+void AGOSEngine_Feeble::listSaveGamesFeeble() {
char b[108];
Common::InSaveFile *in;
uint16 j, k, z, maxFiles;
@@ -377,8 +377,8 @@ void AGOSEngine_Feeble::listSaveGames(int n) {
memset(b, 0, 108);
maxFiles = countSaveGames() - 1;
- j = maxFiles - n + 1;
- k = maxFiles - j + 1;
+ j = maxFiles;
+ k = 1;
z = maxFiles;
if (getBitFlag(95)) {
j++;
diff --git a/engines/agos/pn.cpp b/engines/agos/pn.cpp
index 7471b73d16..62d65de219 100644
--- a/engines/agos/pn.cpp
+++ b/engines/agos/pn.cpp
@@ -128,12 +128,7 @@ Common::Error AGOSEngine_PN::go() {
if (getFeatures() & GF_EGA) {
// Set EGA Palette
- for (int i = 0; i < 16; i++) {
- _displayPalette[i * 4 + 0] = egaPalette[i * 3 + 0];
- _displayPalette[i * 4 + 1] = egaPalette[i * 3 + 1];
- _displayPalette[i * 4 + 2] = egaPalette[i * 3 + 2];
- _displayPalette[i * 4 + 3] = 0;
- }
+ memcpy(_displayPalette, egaPalette, sizeof(egaPalette));
_paletteFlag = 1;
}
diff --git a/engines/agos/script_ff.cpp b/engines/agos/script_ff.cpp
index 5d640af6ad..dbd89cebf5 100644
--- a/engines/agos/script_ff.cpp
+++ b/engines/agos/script_ff.cpp
@@ -430,8 +430,7 @@ void AGOSEngine_Feeble::off_loadUserGame() {
}
void AGOSEngine_Feeble::off_listSaveGames() {
- // 134: dummy opcode?
- listSaveGames(1);
+ listSaveGamesFeeble();
}
void AGOSEngine_Feeble::off_checkCD() {
@@ -640,7 +639,7 @@ void AGOSEngine_Feeble::off_restartClock() {
void AGOSEngine_Feeble::off_setColor() {
// 195: set palette color
- uint16 c = getVarOrByte() * 4;
+ uint16 c = getVarOrByte() * 3;
uint8 r = getVarOrByte();
uint8 g = getVarOrByte();
uint8 b = getVarOrByte();
diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp
index 9dd1e3c5ab..05a725cb50 100644
--- a/engines/agos/script_s1.cpp
+++ b/engines/agos/script_s1.cpp
@@ -578,13 +578,13 @@ void AGOSEngine_Simon1::os1_specialFade() {
for (i = 32; i != 0; --i) {
paletteFadeOut(_currentPalette, 32, 8);
- paletteFadeOut(_currentPalette + 4 * 48, 144, 8);
- paletteFadeOut(_currentPalette + 4 * 208, 48, 8);
+ paletteFadeOut(_currentPalette + 3 * 48, 144, 8);
+ paletteFadeOut(_currentPalette + 3 * 208, 48, 8);
_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
delay(5);
}
- memcpy(_displayPalette, _currentPalette, 1024);
+ memcpy(_displayPalette, _currentPalette, sizeof(_currentPalette));
}
void AGOSEngine::scriptMouseOff() {
diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp
index ed56cbd266..bda605a84a 100644
--- a/engines/agos/string.cpp
+++ b/engines/agos/string.cpp
@@ -725,12 +725,11 @@ void AGOSEngine_Feeble::printScreenText(uint vgaSpriteId, uint color, const char
const char *string2 = string;
int16 height, talkDelay;
int stringLength = strlen(string);
- int lettersPerRow, lettersPerRowJustified;
+ int lettersPerRow;
const int textHeight = 15;
height = textHeight;
lettersPerRow = width / 6;
- lettersPerRowJustified = stringLength / (stringLength / lettersPerRow + 1) + 1;
talkDelay = (stringLength + 3) / 3;
if (_variableArray[86] == 0)
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index 8b8b16c9bb..83ee05036c 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -935,8 +935,8 @@ void AGOSEngine::vc22_setPalette() {
if (getGameType() == GType_PN) {
if (b > 128) {
- b-= 128;
- palptr = _displayPalette + 64;
+ b -= 128;
+ palptr = _displayPalette + 3 * 16;
}
} else if (getGameType() == GType_ELVIRA1) {
if (b >= 1000) {
@@ -956,24 +956,22 @@ void AGOSEngine::vc22_setPalette() {
num = 13;
for (int i = 0; i < 19; i++) {
- palptr[(13 + i) * 4 + 0] = extraColors[i * 3 + 0] * 4;
- palptr[(13 + i) * 4 + 1] = extraColors[i * 3 + 1] * 4;
- palptr[(13 + i) * 4 + 2] = extraColors[i * 3 + 2] * 4;
- palptr[(13 + i) * 4 + 3] = 0;
+ palptr[(13 + i) * 3 + 0] = extraColors[i * 3 + 0] * 4;
+ palptr[(13 + i) * 3 + 1] = extraColors[i * 3 + 1] * 4;
+ palptr[(13 + i) * 3 + 2] = extraColors[i * 3 + 2] * 4;
}
}
}
if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST) {
// Custom palette used for icon area
- palptr = &_displayPalette[13 * 64];
+ palptr = &_displayPalette[13 * 3 * 16];
for (uint8 c = 0; c < 16; c++) {
palptr[0] = iconPalette[c * 3 + 0] * 2;
palptr[1] = iconPalette[c * 3 + 1] * 2;
palptr[2] = iconPalette[c * 3 + 2] * 2;
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
};
palptr = _displayPalette;
}
@@ -986,9 +984,8 @@ void AGOSEngine::vc22_setPalette() {
palptr[0] = ((color & 0xf00) >> 8) * 32;
palptr[1] = ((color & 0x0f0) >> 4) * 32;
palptr[2] = ((color & 0x00f) >> 0) * 32;
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
src += 2;
} while (--num);
@@ -1212,10 +1209,9 @@ void AGOSEngine::vc33_setMouseOn() {
_mouseHideCount = 1;
if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
// Set mouse palette
- _displayPalette[65 * 4 + 0] = 48 * 4;
- _displayPalette[65 * 4 + 1] = 48 * 4;
- _displayPalette[65 * 4 + 2] = 40 * 4;
- _displayPalette[65 * 4 + 3] = 0;
+ _displayPalette[65 * 3 + 0] = 48 * 4;
+ _displayPalette[65 * 3 + 1] = 48 * 4;
+ _displayPalette[65 * 3 + 2] = 40 * 4;
_paletteFlag = 1;
}
mouseOn();
@@ -1313,11 +1309,10 @@ void AGOSEngine::vc37_pokePalette() {
if (getGameType() == GType_PN && (getFeatures() & GF_EGA))
return;
- byte *palptr = _displayPalette + offs * 4;
+ byte *palptr = _displayPalette + offs * 3;
palptr[0] = ((color & 0xf00) >> 8) * 32;
palptr[1] = ((color & 0x0f0) >> 4) * 32;
palptr[2] = ((color & 0x00f) >> 0) * 32;
- palptr[3] = 0;
if (!(_videoLockOut & 0x20)) {
_paletteFlag = 1;
diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp
index a01e79ff99..b0431db801 100644
--- a/engines/agos/vga_e2.cpp
+++ b/engines/agos/vga_e2.cpp
@@ -115,7 +115,7 @@ void AGOSEngine::setPaletteSlot(uint16 srcOffs, uint8 dstOffs) {
byte *offs, *palptr, *src;
uint16 num;
- palptr = _displayPalette + dstOffs * 64;
+ palptr = _displayPalette + dstOffs * 3 * 16;
offs = _curVgaFile1 + READ_BE_UINT16(_curVgaFile1 + 6);
src = offs + srcOffs * 32;
num = 16;
@@ -125,9 +125,8 @@ void AGOSEngine::setPaletteSlot(uint16 srcOffs, uint8 dstOffs) {
palptr[0] = ((color & 0xf00) >> 8) * 32;
palptr[1] = ((color & 0x0f0) >> 4) * 32;
palptr[2] = ((color & 0x00f) >> 0) * 32;
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
src += 2;
} while (--num);
@@ -371,7 +370,7 @@ void AGOSEngine::fullFade() {
if (dstPal[2] != b)
dstPal[2] += 4;
srcPal += 3;
- dstPal += 4;
+ dstPal += 3;
}
_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
delay(5);
diff --git a/engines/agos/vga_s1.cpp b/engines/agos/vga_s1.cpp
index bb13d211fe..a2306d3cdb 100644
--- a/engines/agos/vga_s1.cpp
+++ b/engines/agos/vga_s1.cpp
@@ -112,7 +112,7 @@ void AGOSEngine_Simon1::vc22_setPalette() {
num = a == 0 ? 32 : 16;
palSize = 96;
- palptr = &_displayPalette[(a * 64)];
+ palptr = &_displayPalette[(a * 3 * 16)];
}
offs = _curVgaFile1 + 6;
@@ -122,22 +122,20 @@ void AGOSEngine_Simon1::vc22_setPalette() {
palptr[0] = src[0] * 4;
palptr[1] = src[1] * 4;
palptr[2] = src[2] * 4;
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
src += 3;
} while (--num);
if (getFeatures() & GF_32COLOR) {
// Custom palette used for verb area
- palptr = &_displayPalette[(13 * 64)];
+ palptr = &_displayPalette[(13 * 3 * 16)];
for (uint8 c = 0; c < 32; c++) {
palptr[0] = customPalette[c * 3 + 0];
palptr[1] = customPalette[c * 3 + 1];
palptr[2] = customPalette[c * 3 + 2];
- palptr[3] = 0;
- palptr += 4;
+ palptr += 3;
};
}
diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp
index 54e7928f38..a03c7e178a 100644
--- a/engines/agos/window.cpp
+++ b/engines/agos/window.cpp
@@ -151,13 +151,13 @@ void AGOSEngine::colorWindow(WindowBlock *window) {
if (getGameType() == GType_ELVIRA2 && window->y == 146) {
if (window->fillColor == 1) {
- _displayPalette[33 * 4 + 0] = 48 * 4;
- _displayPalette[33 * 4 + 1] = 40 * 4;
- _displayPalette[33 * 4 + 2] = 32 * 4;
+ _displayPalette[33 * 3 + 0] = 48 * 4;
+ _displayPalette[33 * 3 + 1] = 40 * 4;
+ _displayPalette[33 * 3 + 2] = 32 * 4;
} else {
- _displayPalette[33 * 4 + 0] = 56 * 4;
- _displayPalette[33 * 4 + 1] = 56 * 4;
- _displayPalette[33 * 4 + 2] = 40 * 4;
+ _displayPalette[33 * 3 + 0] = 56 * 4;
+ _displayPalette[33 * 3 + 1] = 56 * 4;
+ _displayPalette[33 * 3 + 2] = 40 * 4;
}
y--;
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index 1c6a55c270..b3171de918 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -39,7 +39,6 @@ int16 currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0;
byte loadCtFW(const char *ctName) {
debugC(1, kCineDebugCollision, "loadCtFW(\"%s\")", ctName);
- uint16 header[32];
byte *ptr, *dataPtr;
int16 foundFileIdx = findFileInBundle(ctName);
@@ -59,12 +58,6 @@ byte loadCtFW(const char *ctName) {
assert(strstr(ctName, ".NEO"));
- Common::MemoryReadStream readS(ptr, 32);
-
- for (int i = 0; i < 16; i++) {
- header[i] = readS.readUint16BE();
- }
-
gfxConvertSpriteToRaw(collisionPage, ptr + 0x80, 160, 200);
free(dataPtr);
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index d80ab70660..54d113d69c 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -50,20 +50,15 @@ Sound *g_sound = 0;
CineEngine *g_cine = 0;
CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+ // Setup mixer
+ syncSoundSettings();
+
DebugMan.addDebugChannel(kCineDebugScript, "Script", "Script debug level");
DebugMan.addDebugChannel(kCineDebugPart, "Part", "Part debug level");
DebugMan.addDebugChannel(kCineDebugSound, "Sound", "Sound debug level");
DebugMan.addDebugChannel(kCineDebugCollision, "Collision", "Collision debug level");
_console = new CineConsole(this);
- // Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
- // Use music volume for plain sound types (At least the AdLib player uses a plain sound type
- // so previously the music and sfx volume controls didn't affect it at all).
- // FIXME: Make AdLib player differentiate between playing sound effects and music and remove this.
- _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("music_volume"));
-
g_cine = this;
g_eventRec.registerRandomSource(_rnd, "cine");
@@ -78,6 +73,20 @@ CineEngine::~CineEngine() {
delete _console;
}
+void CineEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ // Use music volume for plain sound types (At least the AdLib player uses a plain sound type
+ // so previously the music and sfx volume controls didn't affect it at all).
+ // FIXME: Make AdLib player differentiate between playing sound effects and music and remove this.
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType,
+ mute ? 0 : ConfMan.getInt("music_volume"));
+}
+
Common::Error CineEngine::run() {
// Initialize backend
initGraphics(320, 200, false);
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 5f49a2907f..7de0bdc86f 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -117,6 +117,8 @@ public:
CineEngine(OSystem *syst, const CINEGameDescription *gameDesc);
virtual ~CineEngine();
+ virtual void syncSoundSettings();
+
int getGameType() const;
uint32 getFeatures() const;
Common::Language getLanguage() const;
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index a074bd3f09..3c8ffc295b 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -185,16 +185,16 @@ const Graphics::PixelFormat &Palette::colorFormat() const {
}
void Palette::setGlobalOSystemPalette() const {
- byte buf[256 * 4]; // Allocate space for the largest possible palette
+ byte buf[256 * 3]; // Allocate space for the largest possible palette
// The color format used by OSystem's setPalette-function:
- save(buf, sizeof(buf), Graphics::PixelFormat(4, 8, 8, 8, 0, 0, 8, 16, 0), CINE_LITTLE_ENDIAN);
+ save(buf, sizeof(buf), Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), CINE_LITTLE_ENDIAN);
if (g_cine->getPlatform() == Common::kPlatformAmiga && colorCount() == 16) {
// The Amiga version of Future Wars does use the upper 16 colors for a darkened
// game palette to allow transparent dialog boxes. To support that in our code
// we do calculate that palette over here and append it to the screen palette.
- for (uint i = 0; i < 16 * 4; ++i)
- buf[16 * 4 + i] = buf[i] >> 1;
+ for (uint i = 0; i < 16 * 3; ++i)
+ buf[16 * 3 + i] = buf[i] >> 1;
g_system->getPaletteManager()->setPalette(buf, 0, colorCount() * 2);
} else {
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index fd426be66a..4911f78da9 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -996,9 +996,8 @@ void CineEngine::makeSave(char *saveFileName) {
* at a time.
*/
void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat) {
- int16 currentAnim, foundFileIdx, frame;
+ int16 currentAnim, foundFileIdx;
char *animName, part[256], name[10];
- uint16 width, height, bpp, var1;
strcpy(part, currentPartName);
@@ -1012,10 +1011,10 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
// Seek to the start of the current animation's entry
fHandle.seek(fileStartPos + currentAnim * entrySize);
// Read in the current animation entry
- width = fHandle.readUint16BE();
- var1 = fHandle.readUint16BE();
- bpp = fHandle.readUint16BE();
- height = fHandle.readUint16BE();
+ fHandle.readUint16BE(); // width
+ fHandle.readUint16BE();
+ fHandle.readUint16BE(); // bpp
+ fHandle.readUint16BE(); // height
bool validPtr = false;
// Handle variables only present in animation entries of size 30
@@ -1025,7 +1024,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
}
foundFileIdx = fHandle.readSint16BE();
- frame = fHandle.readSint16BE();
+ fHandle.readSint16BE(); // frame
fHandle.read(name, 10);
// Handle variables only present in animation entries of size 23
diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h
index a6e0e3f1ab..f88338ed82 100644
--- a/engines/cine/saveload.h
+++ b/engines/cine/saveload.h
@@ -71,14 +71,14 @@ enum CineSaveGameFormat {
};
/** Identifier for the temporary Operation Stealth savegame format. */
-static const uint32 TEMP_OS_FORMAT_ID = MKID_BE('TEMP');
+static const uint32 TEMP_OS_FORMAT_ID = MKTAG('T','E','M','P');
/** The current version number of Operation Stealth's savegame format. */
static const uint32 CURRENT_OS_SAVE_VER = 1;
/** Chunk header used by the temporary Operation Stealth savegame format. */
struct ChunkHeader {
- uint32 id; ///< Identifier (e.g. MKID_BE('TEMP'))
+ uint32 id; ///< Identifier (e.g. MKTAG('T','E','M','P'))
uint32 version; ///< Version number
uint32 size; ///< Size of the chunk after this header in bytes
};
diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp
index ab1ad7ff9c..9ee3a892a9 100644
--- a/engines/cine/script_os.cpp
+++ b/engines/cine/script_os.cpp
@@ -124,7 +124,7 @@ void OSScript::setupTable() {
{ 0, 0 },
{ &FWScript::o2_loadPart, "s" },
/* 40 */
- { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
+ { &FWScript::o1_closePart, "" },
{ &FWScript::o1_loadNewPrcName, "bs" },
{ &FWScript::o1_requestCheckPendingDataLoad, "" },
{ 0, 0 },
diff --git a/engines/cruise/backgroundIncrust.cpp b/engines/cruise/backgroundIncrust.cpp
index 6bd8b270e0..1685044c9d 100644
--- a/engines/cruise/backgroundIncrust.cpp
+++ b/engines/cruise/backgroundIncrust.cpp
@@ -198,17 +198,13 @@ void regenerateBackgroundIncrust(backgroundIncrustStruct *pHead) {
while (pl) {
backgroundIncrustStruct* pl2 = pl->next;
- bool bLoad = false;
int frame = pl->frame;
//int screen = pl->backgroundIdx;
if ((filesDatabase[frame].subData.ptr == NULL) || (strcmp(pl->name, filesDatabase[frame].subData.name))) {
frame = NUM_FILE_ENTRIES - 1;
- if (loadFile(pl->name, frame, pl->spriteId) >= 0) {
- bLoad = true;
- } else {
+ if (loadFile(pl->name, frame, pl->spriteId) < 0)
frame = -1;
- }
}
if (frame >= 0) {
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index c1ea711228..2c5659c4d9 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -52,16 +52,13 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc
DebugMan.addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level");
DebugMan.addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level");
- // Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType,
- ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType,
- ConfMan.getInt("music_volume"));
-
_vm = this;
_debugger = new Debugger();
_sound = new PCSound(_mixer, this);
+ // Setup mixer
+ syncSoundSettings();
+
g_eventRec.registerRandomSource(_rnd, "cruise");
}
@@ -235,6 +232,8 @@ const char *CruiseEngine::getSavegameFile(int saveGameIdx) {
}
void CruiseEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
_sound->syncSounds();
}
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 6b487fadc9..b1d7a594fe 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -1004,18 +1004,7 @@ bool findRelation(int objOvl, int objIdx, int x, int y) {
if (!obj2Ovl) obj2Ovl = j;
char verbe_name[80];
- char obj1_name[80];
- char obj2_name[80];
- char r_verbe_name[80];
- char r_obj1_name[80];
- char r_obj2_name[80];
-
verbe_name[0] = 0;
- obj1_name[0] = 0;
- obj2_name[0] = 0;
- r_verbe_name[0] = 0;
- r_obj1_name[0] = 0;
- r_obj2_name[0] = 0;
ovlDataStruct *ovl2 = NULL;
ovlDataStruct *ovl3 = NULL;
@@ -1889,7 +1878,7 @@ void CruiseEngine::mainLoop() {
// FIXME: I suspect that the original game does multiple script executions between game frames; the bug with
// Raoul appearing when looking at the book is being there are 3 script iterations separation between the
// scene being changed to the book, and the Raoul actor being frozen/disabled. This loop is a hack to ensure
- // that when a background changes, a few extra script executions are done
+ // that does a few extra script executions for that scene
bool bgChanged;
int numIterations = 1;
@@ -1902,7 +1891,8 @@ void CruiseEngine::mainLoop() {
removeFinishedScripts(&relHead);
removeFinishedScripts(&procHead);
- if (!bgChanged && backgroundChanged[masterScreen]) {
+ if (!bgChanged && backgroundChanged[masterScreen] &&
+ !strcmp(backgroundTable[0].name, "S06B.PI1")) {
bgChanged = true;
numIterations += 2;
}
diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp
index 03a2117f07..b9e4ca8bc9 100644
--- a/engines/cruise/dataLoader.cpp
+++ b/engines/cruise/dataLoader.cpp
@@ -358,7 +358,7 @@ int loadFNTSub(uint8 *ptr, int destIdx) {
uint8 *ptr2 = ptr;
uint8 *destPtr;
int fileIndex;
- uint32 fontSize;
+ //uint32 fontSize;
ptr2 += 4;
loadFileVar1 = READ_BE_UINT32(ptr2);
@@ -373,7 +373,7 @@ int loadFNTSub(uint8 *ptr, int destIdx) {
memcpy(destPtr, ptr2, loadFileVar1);
- fontSize = READ_BE_UINT32(ptr2);
+ //fontSize = READ_BE_UINT32(ptr2);
if (destPtr != NULL) {
int32 i;
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index 00e44465f8..f9ab193399 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -273,16 +273,15 @@ static void mergeClipRects() {
}
void gfxModuleData_updatePalette() {
- byte paletteRGBA[256 * 4];
+ byte paletteRGB[256 * 3];
if (palDirtyMax != -1) {
for (int i = palDirtyMin; i <= palDirtyMax; i++) {
- paletteRGBA[i * 4 + 0] = lpalette[i].R;
- paletteRGBA[i * 4 + 1] = lpalette[i].G;
- paletteRGBA[i * 4 + 2] = lpalette[i].B;
- paletteRGBA[i * 4 + 3] = 0xFF;
+ paletteRGB[i * 3 + 0] = lpalette[i].R;
+ paletteRGB[i * 3 + 1] = lpalette[i].G;
+ paletteRGB[i * 3 + 2] = lpalette[i].B;
}
- g_system->getPaletteManager()->setPalette(paletteRGBA + palDirtyMin*4, palDirtyMin, palDirtyMax - palDirtyMin + 1);
+ g_system->getPaletteManager()->setPalette(paletteRGB + palDirtyMin*3, palDirtyMin, palDirtyMax - palDirtyMin + 1);
palDirtyMin = 256;
palDirtyMax = -1;
}
diff --git a/engines/cruise/linker.cpp b/engines/cruise/linker.cpp
index 49e97ebc11..afc7992493 100644
--- a/engines/cruise/linker.cpp
+++ b/engines/cruise/linker.cpp
@@ -147,8 +147,6 @@ int updateScriptImport(int ovlIdx) {
const char *ptrImportName;
uint8 *ptrData;
- int var_22 = 0;
-
if (param == 0) {
pScript = getOvlData3Entry(ovlIdx, i);
} else {
@@ -159,8 +157,6 @@ int updateScriptImport(int ovlIdx) {
ptrImportName = (const char*)(pScript->dataPtr + pScript->offsetToImportName); // import name
ptrData = pScript->dataPtr;
- var_22 = 0;
-
if (pScript->numRelocGlob > 0) {
int counter = pScript->numRelocGlob;
diff --git a/engines/cruise/mainDraw.cpp b/engines/cruise/mainDraw.cpp
index aaa6f987b6..f6b04e6d9d 100644
--- a/engines/cruise/mainDraw.cpp
+++ b/engines/cruise/mainDraw.cpp
@@ -1081,8 +1081,6 @@ void mainDrawPolygons(int fileIndex, cellStruct *plWork, int X, int scale, int Y
int newScale;
char *newFrame;
- int var_8; // unused
-
int sizeTable[4]; // 0 = left, 1 = right, 2 = bottom, 3 = top
// this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
@@ -1125,8 +1123,6 @@ void mainDrawPolygons(int fileIndex, cellStruct *plWork, int X, int scale, int Y
gfxModuleData_addDirtyRect(Common::Rect(spriteX2, spriteY2, spriteX1, spriteY1));
- var_8 = 0;
-
memset(polygonMask, 0xFF, (320*200) / 8);
int numPasses = 0;
diff --git a/engines/cruise/mouse.cpp b/engines/cruise/mouse.cpp
index 521ba3a54e..24309030da 100644
--- a/engines/cruise/mouse.cpp
+++ b/engines/cruise/mouse.cpp
@@ -52,8 +52,8 @@ static const MouseCursor mouseCursors[] = {
CursorType currentCursor = CURSOR_NOMOUSE;
static const byte cursorPalette[] = {
- 0, 0, 0, 0xff,
- 0xff, 0xff, 0xff, 0xff
+ 0, 0, 0,
+ 0xff, 0xff, 0xff
};
void changeCursor(CursorType eType) {
diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp
index 317dcfbbe6..aae4dba475 100644
--- a/engines/cruise/script.cpp
+++ b/engines/cruise/script.cpp
@@ -619,13 +619,13 @@ int executeScripts(scriptInstanceStruct *ptr) {
positionInStack = 0;
do {
-//#ifdef SKIP_INTRO
+#ifdef SKIP_INTRO
if (currentScriptPtr->scriptOffset == 290
&& currentScriptPtr->overlayNumber == 4
&& currentScriptPtr->scriptNumber == 0) {
currentScriptPtr->scriptOffset = 923;
}
-//#endif
+#endif
opcodeType = getByteFromScript();
debugC(5, kCruiseDebugScript, "Script %s/%d ip=%d opcode=%d",
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 8a4b1d0d2b..2826a34351 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -283,9 +283,21 @@ void PCSoundDriver::resetChannel(int channel) {
}
void PCSoundDriver::syncSounds() {
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ bool music_mute = mute;
+ bool sfx_mute = mute;
+
+ if (!mute) {
+ music_mute = ConfMan.getBool("music_mute");
+ sfx_mute = ConfMan.getBool("sfx_mute");
+ }
+
// Get the new music and sfx volumes
- _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume"));
- _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
+ _musicVolume = music_mute ? 0 : MIN(255, ConfMan.getInt("music_volume"));
+ _sfxVolume = sfx_mute ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
}
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index d0eb511cbd..45d17ea24f 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -162,18 +162,10 @@ int DraciEngine::init() {
_dubbingArchive = openAnyPossibleDubbing();
_sound = new Sound(_mixer);
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
+ _music = new MusicPlayer(musicPathMask);
- _midiDriver = MidiDriver::createMidi(dev);
- if (native_mt32)
- _midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _music = new MusicPlayer(_midiDriver, musicPathMask);
- _music->setNativeMT32(native_mt32);
- _music->open();
- //_music->setAdLib(adlib);
+ // Setup mixer
+ syncSoundSettings();
// Load the game's fonts
_smallFont = new Font(kFontSmall);
@@ -401,7 +393,6 @@ DraciEngine::~DraciEngine() {
delete _sound;
delete _music;
- delete _midiDriver;
delete _soundsArchive;
delete _dubbingArchive;
diff --git a/engines/draci/draci.h b/engines/draci/draci.h
index aa6080ca05..6a597e123e 100644
--- a/engines/draci/draci.h
+++ b/engines/draci/draci.h
@@ -85,7 +85,6 @@ public:
AnimationManager *_anims;
Sound *_sound;
MusicPlayer *_music;
- MidiDriver *_midiDriver;
Font *_smallFont;
Font *_bigFont;
diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp
index caa82c2cc0..750410b329 100644
--- a/engines/draci/music.cpp
+++ b/engines/draci/music.cpp
@@ -36,133 +36,41 @@
namespace Draci {
-MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0), _driver(driver), _pathMask(pathMask), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false), _track(-1) {
- memset(_channel, 0, sizeof(_channel));
- memset(_channelVolume, 127, sizeof(_channelVolume));
- _masterVolume = 0;
- _smfParser = MidiParser::createParser_SMF();
- _midiMusicData = NULL;
-}
-
-MusicPlayer::~MusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _smfParser->setMidiDriver(NULL);
- delete _smfParser;
- delete[] _midiMusicData;
-}
-
-void MusicPlayer::setChannelVolume(int channel) {
- int newVolume = _channelVolume[channel] * _masterVolume / 255;
- debugC(3, kDraciSoundDebugLevel, "Music channel %d: volume %d->%d",
- channel, _channelVolume[channel], newVolume);
- _channel[channel]->volume(newVolume);
-}
-
-void MusicPlayer::setVolume(int volume) {
- Common::StackLock lock(_mutex);
-
- volume = CLIP(volume, 0, 255);
- if (_masterVolume == volume)
- return;
- _masterVolume = volume;
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- setChannelVolume(i);
- }
- }
-}
+MusicPlayer::MusicPlayer(const char *pathMask) : _pathMask(pathMask), _isGM(false), _track(-1) {
-int MusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+ MidiPlayer::createDriver();
int ret = _driver->open();
- if (ret)
- return ret;
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- // TODO: Load cmf.ins with the instrument table. It seems that an
- // interface for such an operation is supported for AdLib. Maybe for
- // this card, setting instruments is necessary.
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
-
-void MusicPlayer::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
-}
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
-void MusicPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
+ // TODO: Load cmf.ins with the instrument table. It seems that an
+ // interface for such an operation is supported for AdLib. Maybe for
+ // this card, setting instruments is necessary.
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
- b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
- }
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (_channel[b & 0x0F])
- return;
+ _driver->setTimerCallback(this, &timerCallback);
}
+}
- if (!_channel[channel]) {
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+void MusicPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
// If a new channel is allocated during the playback, make sure
// its volume is correctly initialized.
- if (_channel[channel])
- setChannelVolume(channel);
- }
-
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
-
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stop();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
}
-}
-
-void MusicPlayer::onTimer(void *refCon) {
- MusicPlayer *music = (MusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
- if (music->_parser)
- music->_parser->onTimer();
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
void MusicPlayer::playSMF(int track, bool loop) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying && track == _track) {
debugC(2, kDraciSoundDebugLevel, "Already plaing track %d", track);
return;
@@ -172,76 +80,46 @@ void MusicPlayer::playSMF(int track, bool loop) {
_isGM = true;
-
// Load MIDI resource data
Common::File musicFile;
char musicFileName[40];
- sprintf(musicFileName, _pathMask.c_str(), track);
+ snprintf(musicFileName, sizeof(musicFileName), _pathMask.c_str(), track);
musicFile.open(musicFileName);
if (!musicFile.isOpen()) {
debugC(2, kDraciSoundDebugLevel, "Cannot open track %d", track);
return;
}
int midiMusicSize = musicFile.size();
- delete[] _midiMusicData;
- _midiMusicData = new byte[midiMusicSize];
- musicFile.read(_midiMusicData, midiMusicSize);
+ free(_midiData);
+ _midiData = (byte *)malloc(midiMusicSize);
+ musicFile.read(_midiData, midiMusicSize);
musicFile.close();
- if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) {
- MidiParser *parser = _smfParser;
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_midiData, midiMusicSize)) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_parser = parser;
syncVolume();
- _looping = loop;
+ _isLooping = loop;
_isPlaying = true;
_track = track;
debugC(2, kDraciSoundDebugLevel, "Playing track %d", track);
} else {
debugC(2, kDraciSoundDebugLevel, "Cannot play track %d", track);
+ delete parser;
}
}
void MusicPlayer::stop() {
- Common::StackLock lock(_mutex);
-
- if (!_isPlaying)
- return;
-
+ Audio::MidiPlayer::stop();
debugC(2, kDraciSoundDebugLevel, "Stopping track %d", _track);
_track = -1;
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
- }
-}
-
-void MusicPlayer::pause() {
- debugC(2, kDraciSoundDebugLevel, "Pausing track %d", _track);
- setVolume(-1);
- _isPlaying = false;
-}
-
-void MusicPlayer::resume() {
- debugC(2, kDraciSoundDebugLevel, "Resuming track %d", _track);
- syncVolume();
- _isPlaying = true;
-}
-
-void MusicPlayer::syncVolume() {
- int volume = ConfMan.getInt("music_volume");
- if (ConfMan.getBool("mute")) {
- volume = -1;
- }
- debugC(2, kDraciSoundDebugLevel, "Syncing music volume to %d", volume);
- setVolume(volume);
}
} // End of namespace Draci
diff --git a/engines/draci/music.h b/engines/draci/music.h
index f6f3a5ae50..c0228074e5 100644
--- a/engines/draci/music.h
+++ b/engines/draci/music.h
@@ -28,74 +28,27 @@
#ifndef DRACI_MUSIC_H
#define DRACI_MUSIC_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "common/mutex.h"
+#include "audio/midiplayer.h"
namespace Draci {
// Taken from MADE, which took it from SAGA.
-class MusicPlayer : public MidiDriver {
+class MusicPlayer : public Audio::MidiPlayer {
public:
- MusicPlayer(MidiDriver *driver, const char *pathMask);
- ~MusicPlayer();
+ MusicPlayer(const char *pathMask);
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
- void syncVolume();
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
void playSMF(int track, bool loop);
void stop();
- void pause();
- void resume();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
- void setGM(bool isGM) { _isGM = isGM; }
-
- // MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
+ // Overload Audio::MidiPlayer method
+ virtual void sendToChannel(byte channel, uint32 b);
protected:
-
- static void onTimer(void *data);
- void setChannelVolume(int channel);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_smfParser;
Common::String _pathMask;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
int _track;
-
- byte *_midiMusicData;
};
} // End of namespace Draci
diff --git a/engines/draci/screen.cpp b/engines/draci/screen.cpp
index bb7a093d8f..dbe3fd98b8 100644
--- a/engines/draci/screen.cpp
+++ b/engines/draci/screen.cpp
@@ -36,7 +36,7 @@ namespace Draci {
Screen::Screen(DraciEngine *vm) : _vm(vm) {
_surface = new Surface(kScreenWidth, kScreenHeight);
- _palette = new byte[4 * kNumColours];
+ _palette = new byte[3 * kNumColours];
_blackPalette = new byte[3 * kNumColours];
for (int i = 0; i < 3 * kNumColours; ++i) {
_blackPalette[i] = 0;
@@ -63,15 +63,14 @@ void Screen::setPalette(const byte *data, uint16 start, uint16 num) {
// Copy the palette
for (uint16 i = start; i < start + num; ++i) {
- _palette[i * 4] = pal.readByte();
- _palette[i * 4 + 1] = pal.readByte();
- _palette[i * 4 + 2] = pal.readByte();
- _palette[i * 4 + 3] = 0;
+ _palette[i * 3] = pal.readByte();
+ _palette[i * 3 + 1] = pal.readByte();
+ _palette[i * 3 + 2] = pal.readByte();
}
// Shift the palette two bits to the left to make it brighter. The
// original game only uses 6-bit colors 0..63.
- for (int i = start * 4; i < (start + num) * 4; ++i) {
+ for (int i = start * 3; i < (start + num) * 3; ++i) {
_palette[i] <<= 2;
}
@@ -86,14 +85,13 @@ void Screen::interpolatePalettes(const byte *first, const byte *second, uint16 s
// Interpolate the palettes
for (uint16 i = start; i < start + num; ++i) {
- _palette[i * 4] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number);
- _palette[i * 4 + 1] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number);
- _palette[i * 4 + 2] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number);
- _palette[i * 4 + 3] = 0;
+ _palette[i * 3] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number);
+ _palette[i * 3 + 1] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number);
+ _palette[i * 3 + 2] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number);
}
// Shift the palette two bits to the left to make it brighter
- for (int i = start * 4; i < (start + num) * 4; ++i) {
+ for (int i = start * 3; i < (start + num) * 3; ++i) {
_palette[i] <<= 2;
}
diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp
index dc8f548d6b..c8646fff67 100644
--- a/engines/draci/sound.cpp
+++ b/engines/draci/sound.cpp
@@ -408,6 +408,9 @@ void Sound::stopVoice() {
}
void Sound::setVolume() {
+ _showSubtitles = ConfMan.getBool("subtitles");
+ _talkSpeed = ConfMan.getInt("talkspeed");
+
if (_mixer->isReady()) {
_muteSound = ConfMan.getBool("sfx_mute");
_muteVoice = ConfMan.getBool("speech_mute");
@@ -417,10 +420,10 @@ void Sound::setVolume() {
if (ConfMan.getBool("mute")) {
_muteSound = _muteVoice = true;
}
- _showSubtitles = ConfMan.getBool("subtitles");
- _talkSpeed = ConfMan.getInt("talkspeed");
- const int soundVolume = ConfMan.getInt("sfx_volume");
- const int speechVolume = ConfMan.getInt("speech_volume");
+
+ const int soundVolume = _muteSound ? 0: ConfMan.getInt("sfx_volume");
+ const int speechVolume = _muteVoice ? 0 : ConfMan.getInt("speech_volume");
+
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolume);
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, speechVolume);
}
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index e84e80ccd3..19395dcd3f 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -195,8 +195,7 @@ Common::Error DrasculaEngine::run() {
loadArchives();
// Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ syncSoundSettings();
currentChapter = 1; // values from 1 to 6 will start each part of game
loadedDifferentChapter = 0;
@@ -512,7 +511,7 @@ bool DrasculaEngine::runCurrentChapter() {
checkObjects();
#ifdef _WIN32_WCE
- if (rightMouseButton)
+ if (rightMouseButton) {
if (_menuScreen) {
#else
if (rightMouseButton == 1 && _menuScreen) {
@@ -570,6 +569,9 @@ bool DrasculaEngine::runCurrentChapter() {
#endif
selectVerb(kVerbNone);
}
+#ifdef _WIN32_WCE
+ }
+#endif
if (leftMouseButton == 1 && _menuBar) {
delay(100);
diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp
index 67597efd0c..b521c0313b 100644
--- a/engines/drascula/palette.cpp
+++ b/engines/drascula/palette.cpp
@@ -65,15 +65,12 @@ void DrasculaEngine::black() {
}
void DrasculaEngine::setPalette(byte *PalBuf) {
- byte pal[256 * 4];
- int i;
-
- for (i = 0; i < 256; i++) {
- pal[i * 4 + 0] = PalBuf[i * 3 + 0] * 4;
- pal[i * 4 + 1] = PalBuf[i * 3 + 1] * 4;
- pal[i * 4 + 2] = PalBuf[i * 3 + 2] * 4;
- pal[i * 4 + 3] = 0;
+ byte pal[256 * 3];
+
+ for (int i = 0; i < 3 * 256; ++i) {
+ pal[i] = PalBuf[i] * 4;
}
+
_system->getPaletteManager()->setPalette(pal, 0, 256);
_system->updateScreen();
}
diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp
index 884697dec7..7744374518 100644
--- a/engines/drascula/rooms.cpp
+++ b/engines/drascula/rooms.cpp
@@ -182,11 +182,11 @@ bool DrasculaEngine::roomParse(int rN, int fl) {
}
bool DrasculaEngine::room_0(int fl) {
+ (void)fl;
+
static const int lookExcuses[3] = {100, 101, 54};
static const int actionExcuses[6] = {11, 109, 111, 110, 115, 116};
- fl = -1; // avoid warning
-
// non-default actions
if (currentChapter == 2 || currentChapter == 4 ||
currentChapter == 5 || currentChapter == 6) {
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 0d92c1aef1..0e5e58bc72 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -145,7 +145,11 @@ void initCommonGFX(bool defaultTo1XScaler) {
assert(transientDomain);
const bool useDefaultGraphicsMode =
- !transientDomain->contains("gfx_mode") &&
+ (!transientDomain->contains("gfx_mode") ||
+ !scumm_stricmp(transientDomain->getVal("gfx_mode").c_str(), "normal") ||
+ !scumm_stricmp(transientDomain->getVal("gfx_mode").c_str(), "default")
+ )
+ &&
(
!gameDomain ||
!gameDomain->contains("gfx_mode") ||
@@ -155,10 +159,7 @@ void initCommonGFX(bool defaultTo1XScaler) {
// See if the game should default to 1x scaler
if (useDefaultGraphicsMode && defaultTo1XScaler) {
- // FIXME: As a hack, we use "1x" here. Would be nicer to use
- // getDefaultGraphicsMode() instead, but right now, we do not specify
- // whether that is a 1x scaler or not...
- g_system->setGraphicsMode("1x");
+ g_system->resetGraphicsScale();
} else {
// Override global scaler with any game-specific define
if (ConfMan.hasKey("gfx_mode")) {
@@ -280,7 +281,7 @@ void initGraphics(int width, int height, bool defaultTo1xScaler) {
initGraphics(width, height, defaultTo1xScaler, &format);
}
-void GUIErrorMessage(const Common::String msg) {
+void GUIErrorMessage(const Common::String &msg) {
g_system->setWindowCaption("Error");
g_system->beginGFXTransaction();
initCommonGFX(false);
@@ -429,7 +430,6 @@ int Engine::runDialog(GUI::Dialog &dialog) {
}
void Engine::syncSoundSettings() {
-
// Sync the engine with the config manager
int soundVolumeMusic = ConfMan.getInt("music_volume");
int soundVolumeSFX = ConfMan.getInt("sfx_volume");
@@ -439,6 +439,7 @@ void Engine::syncSoundSettings() {
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (mute ? 0 : Audio::Mixer::kMaxMixerVolume));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : soundVolumeMusic));
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech));
diff --git a/engines/engine.h b/engines/engine.h
index b4764319b8..168a1dc2a0 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -47,7 +47,7 @@ namespace GUI {
/**
* Initializes graphics and shows error message.
*/
-void GUIErrorMessage(const Common::String msg);
+void GUIErrorMessage(const Common::String &msg);
class Engine {
@@ -163,6 +163,15 @@ public:
* Notify the engine that the sound settings in the config manager may have
* changed and that it hence should adjust any internal volume etc. values
* accordingly.
+ * The default implementation sets the volume levels of all mixer sound
+ * types according to the config entries of the active domain.
+ * When overwriting, call the default implementation first, then adjust the
+ * volumes further (if required).
+ *
+ * @note When setting volume levels, respect the "mute" config entry.
+ * @note The volume for the plain sound type is reset to the maximum
+ * volume. If the engine can associate its own value for this
+ * type, it needs to overwrite this member and set it accordingly.
* @todo find a better name for this
*/
virtual void syncSoundSettings();
diff --git a/engines/engines.mk b/engines/engines.mk
index b0f57135aa..f8ff823c13 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -97,6 +97,18 @@ endif
ifdef ENABLE_MOHAWK
DEFINES += -DENABLE_MOHAWK=$(ENABLE_MOHAWK)
MODULES += engines/mohawk
+
+ifdef ENABLE_CSTIME
+DEFINES += -DENABLE_CSTIME
+endif
+
+ifdef ENABLE_MYST
+DEFINES += -DENABLE_MYST
+endif
+
+ifdef ENABLE_RIVEN
+DEFINES += -DENABLE_RIVEN
+endif
endif
ifdef ENABLE_PARALLACTION
diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
index 43f15b8845..b12fb81be1 100644
--- a/engines/gob/detection_tables.h
+++ b/engines/gob/detection_tables.h
@@ -3723,6 +3723,20 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640x480 | kFeaturesTrueColor,
0, 0, 0
},
+ { // Supplied by Collector9 in bug report #3228040
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "6ce3d878178932053267237ec4843ce1", 1252518),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+ },
{ // Supplied by gamin in the forums
{
"urban",
@@ -3751,6 +3765,20 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640x480 | kFeaturesTrueColor,
0, 0, 0
},
+ { // Supplied by Alex on the gobsmacked blog
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "9ea647085a16dd0fb9ecd84cd8778ec9", 1253436),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+ },
{ // Supplied by goodoldgeorg in bug report #2770340
{
"urban",
@@ -4921,7 +4949,7 @@ static const GOBGameDescription fallbackDescs[] = {
GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
- kFeaturesCD | kFeaturesTrueColor,
+ kFeatures640x480 | kFeaturesTrueColor,
0, 0, 0
},
{ //13
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index b65bbe0d0f..12914163c2 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -575,6 +575,9 @@ bool GobEngine::initGameParts() {
return false;
}
+ // Setup mixer
+ syncSoundSettings();
+
_inter->setupOpcodes();
return true;
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 63b2d7f681..6a42b5ecd4 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1172,12 +1172,11 @@ void Inter_v2::o2_addHotspot(OpFuncParams &params) {
top = 0;
}
- int16 index;
if (id < 0)
- index = _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
+ _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
left + width + 3, top + height + 3, flags, key, 0, 0, funcPos);
else
- index = _vm->_game->_hotspots->add(0xE000 + id, left, top,
+ _vm->_game->_hotspots->add(0xE000 + id, left, top,
left + width - 1, top + height - 1, flags, key, 0, 0, funcPos);
}
diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h
index eeee03847a..22eb79f4bf 100644
--- a/engines/gob/save/savefile.h
+++ b/engines/gob/save/savefile.h
@@ -48,8 +48,8 @@ class SaveHeader {
public:
/** The size of the header. */
static const int kSize = 20;
- static const uint32 kID1 = MKID_BE('\0SCV');
- static const uint32 kID2 = MKID_BE('MGOB');
+ static const uint32 kID1 = MKTAG(0,'S','C','V');
+ static const uint32 kID2 = MKTAG('M','G','O','B');
SaveHeader(uint32 type = 0, uint32 version = 0, uint32 size = 0);
@@ -106,7 +106,7 @@ protected:
class SavePartMem : public SavePart {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('PMEM');
+ static const uint32 kID = MKTAG('P','M','E','M');
SavePartMem(uint32 size);
~SavePartMem();
@@ -128,7 +128,7 @@ private:
class SavePartVars : public SavePart {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('VARS');
+ static const uint32 kID = MKTAG('V','A','R','S');
SavePartVars(GobEngine *vm, uint32 size);
~SavePartVars();
@@ -155,7 +155,7 @@ private:
class SavePartSprite : public SavePart {
public:
static const uint32 kVersion = 2;
- static const uint32 kID = MKID_BE('SPRT');
+ static const uint32 kID = MKTAG('S','P','R','T');
SavePartSprite(uint32 width, uint32 height, bool trueColor = false);
~SavePartSprite();
@@ -193,7 +193,7 @@ private:
class SavePartInfo : public SavePart {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('INFO');
+ static const uint32 kID = MKTAG('I','N','F','O');
/**
* The constructor.
@@ -235,7 +235,7 @@ private:
class SaveContainer {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('CONT');
+ static const uint32 kID = MKTAG('C','O','N','T');
/**
* The constructor.
diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h
index c231c1dbbb..dc1c184504 100644
--- a/engines/gob/save/saveload.h
+++ b/engines/gob/save/saveload.h
@@ -305,7 +305,7 @@ protected:
int getSlot(int32 offset) const;
int getSlotRemainder(int32 offset) const;
- void buildIndex(byte *buffer) const;
+ void buildScreenshotIndex(byte *buffer) const;
protected:
uint32 _shotSize;
@@ -430,7 +430,7 @@ protected:
int getSlot(int32 offset) const;
int getSlotRemainder(int32 offset) const;
- void buildIndex(byte *buffer) const;
+ void buildScreenshotIndex(byte *buffer) const;
};
File *_file;
diff --git a/engines/gob/save/saveload_inca2.cpp b/engines/gob/save/saveload_inca2.cpp
index 68c76c3f2b..5fa1b69fa7 100644
--- a/engines/gob/save/saveload_inca2.cpp
+++ b/engines/gob/save/saveload_inca2.cpp
@@ -260,7 +260,7 @@ int SaveLoad_Inca2::ScreenshotHandler::File::getSlotRemainder(int32 offset) cons
return (offset - 80) % 15168;
}
-void SaveLoad_Inca2::ScreenshotHandler::File::buildIndex(byte *buffer) const {
+void SaveLoad_Inca2::ScreenshotHandler::File::buildScreenshotIndex(byte *buffer) const {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
@@ -306,7 +306,7 @@ bool SaveLoad_Inca2::ScreenshotHandler::load(int16 dataVar, int32 size, int32 of
}
// Create/Fake the index
- _file->buildIndex(_index + 40);
+ _file->buildScreenshotIndex(_index + 40);
_vm->_inter->_variables->copyFrom(dataVar, _index + offset, size);
diff --git a/engines/gob/save/saveload_v3.cpp b/engines/gob/save/saveload_v3.cpp
index 098b8e1160..39edddb66f 100644
--- a/engines/gob/save/saveload_v3.cpp
+++ b/engines/gob/save/saveload_v3.cpp
@@ -367,7 +367,7 @@ int SaveLoad_v3::ScreenshotHandler::File::getSlotRemainder(int32 offset) const {
return ((offset - _shotIndexSize) % _shotSize);
}
-void SaveLoad_v3::ScreenshotHandler::File::buildIndex(byte *buffer) const {
+void SaveLoad_v3::ScreenshotHandler::File::buildScreenshotIndex(byte *buffer) const {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
@@ -418,12 +418,12 @@ bool SaveLoad_v3::ScreenshotHandler::load(int16 dataVar, int32 size, int32 offse
if (_sShotType == kScreenshotTypeGob3) {
// Create/Fake the index
- _file->buildIndex(_index + 40);
+ _file->buildScreenshotIndex(_index + 40);
// The last 10 bytes are 0
memset(_index + 70, 0, 10);
} else if (_sShotType == kScreenshotTypeLost) {
// Create/Fake the index
- _file->buildIndex(_index);
+ _file->buildScreenshotIndex(_index);
// The last byte is 0
_index[30] = 0;
}
diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp
index f0977aa45b..8850a727d3 100644
--- a/engines/gob/sound/bgatmosphere.cpp
+++ b/engines/gob/sound/bgatmosphere.cpp
@@ -47,7 +47,7 @@ BackgroundAtmosphere::~BackgroundAtmosphere() {
queueClear();
}
-void BackgroundAtmosphere::play() {
+void BackgroundAtmosphere::playBA() {
Common::StackLock slock(_mutex);
_queuePos = -1;
@@ -59,7 +59,7 @@ void BackgroundAtmosphere::play() {
SoundMixer::play(*_queue[_queuePos], 1, 0);
}
-void BackgroundAtmosphere::stop() {
+void BackgroundAtmosphere::stopBA() {
SoundMixer::stop(0);
}
diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h
index 71a2263341..7e58c0b4e9 100644
--- a/engines/gob/sound/bgatmosphere.h
+++ b/engines/gob/sound/bgatmosphere.h
@@ -46,8 +46,8 @@ public:
BackgroundAtmosphere(Audio::Mixer &mixer);
~BackgroundAtmosphere();
- void play();
- void stop();
+ void playBA();
+ void stopBA();
void setPlayMode(PlayMode mode);
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index 5950388c28..1aa63eb940 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -648,7 +648,7 @@ void Sound::bgPlay(const char *file, SoundType type) {
debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\"", file);
- _bgatmos->stop();
+ _bgatmos->stopBA();
_bgatmos->queueClear();
SoundDesc *sndDesc = new SoundDesc;
@@ -658,7 +658,7 @@ void Sound::bgPlay(const char *file, SoundType type) {
}
_bgatmos->queueSample(*sndDesc);
- _bgatmos->play();
+ _bgatmos->playBA();
}
void Sound::bgPlay(const char *base, const char *ext, SoundType type, int count) {
@@ -667,7 +667,7 @@ void Sound::bgPlay(const char *base, const char *ext, SoundType type, int count)
debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\" (%d)", base, count);
- _bgatmos->stop();
+ _bgatmos->stopBA();
_bgatmos->queueClear();
int length = strlen(base) + 7;
@@ -684,7 +684,7 @@ void Sound::bgPlay(const char *base, const char *ext, SoundType type, int count)
delete sndDesc;
}
- _bgatmos->play();
+ _bgatmos->playBA();
}
void Sound::bgStop() {
@@ -693,7 +693,7 @@ void Sound::bgStop() {
debugC(1, kDebugSound, "BackgroundAtmosphere: Stopping playback");
- _bgatmos->stop();
+ _bgatmos->stopBA();
_bgatmos->queueClear();
}
diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index 8d06ca8d63..c3e8cd9ff5 100644
--- a/engines/gob/surface.cpp
+++ b/engines/gob/surface.cpp
@@ -420,25 +420,25 @@ void Surface::blit(const Surface &from, int16 left, int16 top, int16 right, int1
return;
if ((left == 0) && (_width == from._width) && (_width == width) && (transp == -1)) {
- // If these conditions are met, we can directly use memcpy
+ // If these conditions are met, we can directly use memmove
// Pointers to the blit destination and source start points
byte *dst = getData(x , y);
const byte *src = from.getData(left, top);
- memcpy(dst, src, width * height * _bpp);
+ memmove(dst, src, width * height * _bpp);
return;
}
if (transp == -1) {
- // We don't have to look for transparency => we can use memcpy line-wise
+ // We don't have to look for transparency => we can use memmove line-wise
// Pointers to the blit destination and source start points
byte *dst = getData(x , y);
const byte *src = from.getData(left, top);
while (height-- > 0) {
- memcpy(dst, src, width * _bpp);
+ memmove(dst, src, width * _bpp);
dst += _width * _bpp;
src += from._width * from._bpp;
@@ -521,7 +521,7 @@ void Surface::blitScaled(const Surface &from, int16 left, int16 top, int16 right
posW = 0;
for (uint16 i = 0; i < width; i++, dstRow += _bpp) {
- memcpy(dstRow, srcRow, _bpp);
+ memmove(dstRow, srcRow, _bpp);
posW += step;
while (posW >= ((frac_t) FRAC_ONE)) {
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index f0b475f65b..4d51b3d61f 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -318,13 +318,13 @@ void Util::forceMouseUp(bool onlyWhenSynced) {
void Util::clearPalette() {
int16 i;
- byte colors[1024];
+ byte colors[768];
_vm->validateVideoMode(_vm->_global->_videoMode);
if (_vm->_global->_setAllPalette) {
if (_vm->getPixelFormat().bytesPerPixel == 1) {
- memset(colors, 0, 1024);
+ memset(colors, 0, sizeof(colors));
g_system->getPaletteManager()->setPalette(colors, 0, 256);
}
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 4a32489138..444ff8ed9e 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -345,7 +345,7 @@ void Video::drawPackedSprite(const char *path, Surface &dest, int width) {
void Video::setPalElem(int16 index, char red, char green, char blue,
int16 unused, int16 vidMode) {
- byte pal[4];
+ byte pal[3];
_vm->validateVideoMode(vidMode);
@@ -359,14 +359,14 @@ void Video::setPalElem(int16 index, char red, char green, char blue,
}
void Video::setPalette(PalDesc *palDesc) {
- byte pal[1024];
+ byte pal[768];
int16 numcolors;
_vm->validateVideoMode(_vm->_global->_videoMode);
numcolors = _vm->_global->_setAllPalette ? 256 : 16;
for (int i = 0; i < numcolors; i++)
- setPalColor(pal + i * 4, palDesc->vgaPal[i]);
+ setPalColor(pal + i * 3, palDesc->vgaPal[i]);
if (_vm->getPixelFormat().bytesPerPixel == 1)
g_system->getPaletteManager()->setPalette(pal, 0, numcolors);
@@ -374,14 +374,14 @@ void Video::setPalette(PalDesc *palDesc) {
void Video::setFullPalette(PalDesc *palDesc) {
if (_vm->_global->_setAllPalette) {
- byte pal[1024];
+ byte pal[768];
Color *colors = palDesc->vgaPal;
for (int i = 0; i < 256; i++) {
_vm->_global->_redPalette[i] = colors[i].red;
_vm->_global->_greenPalette[i] = colors[i].green;
_vm->_global->_bluePalette[i] = colors[i].blue;
- setPalColor(pal + i * 4, colors[i]);
+ setPalColor(pal + i * 3, colors[i]);
}
if (_vm->getPixelFormat().bytesPerPixel == 1)
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 8828b666b3..69cdfe49ed 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -125,7 +125,6 @@ public:
pal[0] = red << 2;
pal[1] = green << 2;
pal[2] = blue << 2;
- pal[3] = 0;
}
void setPalColor(byte *pal, Color &color) {
setPalColor(pal, color.red, color.green, color.blue);
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 2d0a2df245..db4134ccb0 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -226,13 +226,8 @@ byte *GrvCursorMan_t7g::loadImage(Common::SeekableReadStream &file) {
}
byte *GrvCursorMan_t7g::loadPalette(Common::SeekableReadStream &file) {
- byte *palette = new byte[4 * 32];
- for (uint8 colournum = 0; colournum < 32; colournum++) {
- palette[colournum * 4 + 0] = file.readByte();
- palette[colournum * 4 + 1] = file.readByte();
- palette[colournum * 4 + 2] = file.readByte();
- palette[colournum * 4 + 3] = 0;
- }
+ byte *palette = new byte[3 * 32];
+ file.read(palette, 3 * 32);
return palette;
}
@@ -409,7 +404,7 @@ GrvCursorMan_v2::GrvCursorMan_v2(OSystem *system) :
// Verify the signature
uint32 tmp32 = iconsFile.readUint32BE();
uint16 tmp16 = iconsFile.readUint16LE();
- if (tmp32 != MKID_BE('icon') || tmp16 != 1)
+ if (tmp32 != MKTAG('i','c','o','n') || tmp16 != 1)
error("Groovie::Cursor: icons.ph signature failed: %s %d", tag2str(tmp32), tmp16);
diff --git a/engines/groovie/debug.cpp b/engines/groovie/debug.cpp
index 92afbb0115..bd4b671e11 100644
--- a/engines/groovie/debug.cpp
+++ b/engines/groovie/debug.cpp
@@ -137,11 +137,11 @@ bool Debugger::cmd_playref(int argc, const char **argv) {
bool Debugger::cmd_dumppal(int argc, const char **argv) {
uint16 i;
- byte palettedump[256 * 4];
+ byte palettedump[256 * 3];
_vm->_system->getPaletteManager()->grabPalette(palettedump, 0, 256);
for (i = 0; i < 256; i++) {
- DebugPrintf("%3d: %3d,%3d,%3d,%3d\n", i, palettedump[(i * 4)], palettedump[(i * 4) + 1], palettedump[(i * 4) + 2], palettedump[(i * 4) + 3]);
+ DebugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]);
}
return true;
}
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index 9d6da81fb6..3ceeeb6018 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -106,11 +106,7 @@ void GraphicsMan::fadeIn(byte *pal) {
_fadeStartTime = _vm->_system->getMillis();
// Copy the target palette
- for (int i = 0; i < 256; i++) {
- _paletteFull[(i * 4) + 0] = pal[(i * 3) + 0];
- _paletteFull[(i * 4) + 1] = pal[(i * 3) + 1];
- _paletteFull[(i * 4) + 2] = pal[(i * 3) + 2];
- }
+ memcpy(_paletteFull, pal, 3 * 256);
// Set the current fading
_fading = 1;
@@ -151,11 +147,11 @@ void GraphicsMan::applyFading(int step) {
}
// Calculate the new palette
- byte newpal[256 * 4];
+ byte newpal[256 * 3];
for (int i = 0; i < 256; i++) {
- newpal[(i * 4) + 0] = (_paletteFull[(i * 4) + 0] * factorR) / 256;
- newpal[(i * 4) + 1] = (_paletteFull[(i * 4) + 1] * factorG) / 256;
- newpal[(i * 4) + 2] = (_paletteFull[(i * 4) + 2] * factorB) / 256;
+ newpal[(i * 3) + 0] = (_paletteFull[(i * 3) + 0] * factorR) / 256;
+ newpal[(i * 3) + 1] = (_paletteFull[(i * 3) + 1] * factorG) / 256;
+ newpal[(i * 3) + 2] = (_paletteFull[(i * 3) + 2] * factorB) / 256;
}
// Set the screen palette
diff --git a/engines/groovie/graphics.h b/engines/groovie/graphics.h
index c9bade9538..a405822c9c 100644
--- a/engines/groovie/graphics.h
+++ b/engines/groovie/graphics.h
@@ -58,7 +58,7 @@ private:
// Palette fading
void applyFading(int step);
int _fading;
- byte _paletteFull[256 * 4];
+ byte _paletteFull[256 * 3];
uint32 _fadeStartTime;
};
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 4a4f5e0de5..67c8f3dbc7 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -322,6 +322,8 @@ void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf
}
void GroovieEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
bool mute = ConfMan.getBool("mute");
// Set the music volume
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 011409155c..45f9800211 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -247,25 +247,12 @@ MusicPlayerMidi::~MusicPlayerMidi() {
delete _midiParser;
// Unload the MIDI Driver
- if (_driver)
+ if (_driver) {
_driver->close();
- delete _driver;
-}
-
-int MusicPlayerMidi::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- int ret = _driver->open();
- if (ret)
- return ret;
-
- return 0;
+ delete _driver;
+ }
}
-void MusicPlayerMidi::close() {}
-
void MusicPlayerMidi::send(uint32 b) {
if ((b & 0xFFF0) == 0x07B0) { // Volume change
// Save the specific channel volume
@@ -294,32 +281,6 @@ void MusicPlayerMidi::metaEvent(byte type, byte *data, uint16 length) {
}
}
-void MusicPlayerMidi::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
- if (_driver)
- _driver->setTimerCallback(timer_param, timer_proc);
-}
-
-uint32 MusicPlayerMidi::getBaseTempo() {
- if (_driver)
- return _driver->getBaseTempo();
- else
- return 0;
-}
-
-MidiChannel *MusicPlayerMidi::allocateChannel() {
- if (_driver)
- return _driver->allocateChannel();
- else
- return 0;
-}
-
-MidiChannel *MusicPlayerMidi::getPercussionChannel() {
- if (_driver)
- return _driver->getPercussionChannel();
- else
- return 0;
-}
-
void MusicPlayerMidi::updateChanVolume(byte channel) {
// Generate a MIDI Control change message for the volume
uint32 b = 0x7B0;
@@ -402,8 +363,10 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
// Create the driver
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = createMidi(dev);
- this->open();
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
+
+ _driver->open(); // TODO: Handle return value != 0 (indicating an error)
// Set the parser's driver
_midiParser->setMidiDriver(this);
@@ -702,8 +665,10 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) {
// Create the driver
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = createMidi(dev);
- this->open();
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
+
+ _driver->open(); // TODO: Handle return value != 0 (indicating an error)
// Set the parser's driver
_midiParser->setMidiDriver(this);
@@ -719,7 +684,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) {
debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref);
// First try for compressed MIDI
- Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF);
+ Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKTAG('c','m','i','d'), fileref & 0x3FF);
if (file) {
// Found the resource, decompress it
@@ -728,7 +693,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) {
file = tmp;
} else {
// Otherwise, it's uncompressed
- file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF);
+ file = _vm->_macResFork->getResource(MKTAG('M','i','d','i'), fileref & 0x3FF);
if (!file)
error("Groovie::Music: Couldn't find resource 0x%04X", fileref);
}
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 74bb6f98e5..bde0a7a16f 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -88,20 +88,14 @@ protected:
virtual void unload();
};
-class MusicPlayerMidi : public MusicPlayer, public MidiDriver {
+class MusicPlayerMidi : public MusicPlayer, public MidiDriver_BASE {
public:
MusicPlayerMidi(GroovieEngine *vm);
~MusicPlayerMidi();
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
- uint32 getBaseTempo();
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel();
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
private:
// Channel volumes
@@ -115,7 +109,7 @@ protected:
MidiParser *_midiParser;
MidiDriver *_driver;
- void onTimerInternal();
+ virtual void onTimerInternal();
void updateVolume();
void unload();
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 540465050d..4d7157c797 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -53,46 +53,37 @@ ROQPlayer::ROQPlayer(GroovieEngine *vm) :
_prevBuf = new Graphics::Surface();
if (_vm->_mode8bit) {
- byte pal[256 * 4];
+ byte pal[256 * 3];
#ifdef DITHER
- byte pal3[256 * 3];
// Initialize to a black palette
- for (int i = 0; i < 256 * 3; i++) {
- pal3[i] = 0;
- }
+ memset(pal, 0, 256 * 3);
// Build a basic color palette
for (int r = 0; r < 4; r++) {
for (int g = 0; g < 4; g++) {
for (int b = 0; b < 4; b++) {
byte col = (r << 4) | (g << 2) | (b << 0);
- pal3[3 * col + 0] = r << 6;
- pal3[3 * col + 1] = g << 6;
- pal3[3 * col + 2] = b << 6;
+ pal[3 * col + 0] = r << 6;
+ pal[3 * col + 1] = g << 6;
+ pal[3 * col + 2] = b << 6;
}
}
}
// Initialize the dithering algorithm
_paletteLookup = new Graphics::PaletteLUT(8, Graphics::PaletteLUT::kPaletteYUV);
- _paletteLookup->setPalette(pal3, Graphics::PaletteLUT::kPaletteRGB, 8);
+ _paletteLookup->setPalette(pal, Graphics::PaletteLUT::kPaletteRGB, 8);
for (int i = 0; (i < 64) && !_vm->shouldQuit(); i++) {
debug("Groovie::ROQ: Building palette table: %02d/63", i);
_paletteLookup->buildNext();
}
- // Prepare the palette to show
- for (int i = 0; i < 256; i++) {
- pal[(i * 4) + 0] = pal3[(i * 3) + 0];
- pal[(i * 4) + 1] = pal3[(i * 3) + 1];
- pal[(i * 4) + 2] = pal3[(i * 3) + 2];
- }
#else // !DITHER
// Set a grayscale palette
for (int i = 0; i < 256; i++) {
- pal[(i * 4) + 0] = i;
- pal[(i * 4) + 1] = i;
- pal[(i * 4) + 2] = i;
+ pal[(i * 3) + 0] = i;
+ pal[(i * 3) + 1] = i;
+ pal[(i * 3) + 2] = i;
}
#endif // DITHER
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index 10177dad34..1b4a2b7800 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -555,15 +555,8 @@ void VDXPlayer::setPalette(uint8 *palette) {
if (_flagSkipPalette)
return;
- uint8 palBuf[4 * 256];
debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Setting palette");
- for (int i = 0; i < 256; i++) {
- palBuf[(i * 4) + 0] = palette[(i * 3) + 0];
- palBuf[(i * 4) + 1] = palette[(i * 3) + 1];
- palBuf[(i * 4) + 2] = palette[(i * 3) + 2];
- palBuf[(i * 4) + 3] = 0;
- }
- _syst->getPaletteManager()->setPalette(palBuf, 0, 256);
+ _syst->getPaletteManager()->setPalette(palette, 0, 256);
}
} // End of Groovie namespace
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index c99db2433f..e862e339ce 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -292,6 +292,11 @@ SaveStateDescriptor HugoMetaEngine::querySaveMetaInfos(const char *target, int s
desc.setSaveTime(hour, minutes);
+ // Slot 0 is used for the 'restart game' save in all Hugo games, thus
+ // we prevent it from being deleted.
+ desc.setDeletableFlag(slot != 0);
+ desc.setWriteProtectedFlag(slot == 0);
+
delete file;
return desc;
}
diff --git a/engines/hugo/menu.cpp b/engines/hugo/dialogs.cpp
index 065d68bdc5..ead432c5df 100644
--- a/engines/hugo/menu.cpp
+++ b/engines/hugo/dialogs.cpp
@@ -109,7 +109,7 @@ void TopMenu::reflowLayout() {
_inventButton->resize(x * scale, y * scale, kButtonWidth * scale, kButtonHeight * scale);
x += kButtonWidth + kButtonPad;
- // Set the graphics to the 'on' buttons, except for the variable ones
+ // Set the graphics to the 'on' buttons, except for the variable ones
_whatButton->setGfx(arrayBmp[4 * kMenuWhat + scale - 1]);
_musicButton->setGfx(arrayBmp[4 * kMenuMusic + scale - 1 + ((_vm->_config.musicFl) ? 0 : 2)]);
_soundFXButton->setGfx(arrayBmp[4 * kMenuSoundFX + scale - 1 + ((_vm->_config.soundFl) ? 0 : 2)]);
@@ -129,7 +129,7 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) {
for (int i = 0; i < arraySize; i++) {
uint16 bmpSize = in.readUint16BE();
uint32 filPos = in.pos();
- Common::SeekableSubReadStream stream(&in, filPos, filPos + bmpSize);
+ Common::SeekableSubReadStream stream(&in, filPos, filPos + bmpSize);
arrayBmp[i * 2] = Graphics::ImageDecoder::loadFile(stream, g_system->getOverlayFormat());
arrayBmp[i * 2 + 1] = new Graphics::Surface();
arrayBmp[i * 2 + 1]->create(arrayBmp[i * 2]->w * 2, arrayBmp[i * 2]->h * 2, arrayBmp[i * 2]->bytesPerPixel);
@@ -188,7 +188,7 @@ void TopMenu::handleCommand(GUI::CommandSender *sender, uint32 command, uint32 d
close();
if (_vm->getGameStatus().viewState == kViewPlay) {
if (_vm->getGameStatus().gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
_vm->_file->saveGame(-1, Common::String());
}
@@ -196,8 +196,6 @@ void TopMenu::handleCommand(GUI::CommandSender *sender, uint32 command, uint32 d
case kCmdLoad:
close();
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- _vm->getGameStatus().viewState = kViewPlay;
break;
case kCmdRecall:
close();
@@ -232,4 +230,33 @@ void TopMenu::handleMouseUp(int x, int y, int button, int clickCount) {
Dialog::handleMouseUp(x, y, button, clickCount);
}
+EntryDialog::EntryDialog(const Common::String &title, const Common::String &buttonLabel, const Common::String &defaultValue) : GUI::Dialog(20, 20, 100, 50) {
+ new GUI::StaticTextWidget(this, 0, 0, 10, 10, title, Graphics::kTextAlignCenter);
+
+ _text = new GUI::EditTextWidget(this, 0, 0, 50, 10, "");
+ _text->setEditString(defaultValue);
+
+ new GUI::ButtonWidget(this, 20, 20, 30, 10, buttonLabel, 0, kCmdButton);
+}
+
+EntryDialog::~EntryDialog() {
+}
+
+void EntryDialog::handleCommand(GUI::CommandSender *sender, uint32 command, uint32 data) {
+ switch (command) {
+ case kCmdButton:
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, command, data);
+ }
+}
+
+void EntryDialog::reflowLayout() {
+}
+
+void EntryDialog::init() {
+}
+
+
} // End of namespace Hugo
diff --git a/engines/hugo/menu.h b/engines/hugo/dialogs.h
index 6e2a9063bc..f870414a93 100644
--- a/engines/hugo/menu.h
+++ b/engines/hugo/dialogs.h
@@ -23,10 +23,11 @@
*
*/
-#ifndef HUGO_TOPMENU_H
-#define HUGO_TOPMENU_H
+#ifndef HUGO_DIALOGS_H
+#define HUGO_DIALOGS_H
#include "gui/dialog.h"
+#include "gui/widgets/edittext.h"
namespace Hugo {
@@ -54,6 +55,7 @@ enum {
};
enum {
+ // TopMenu commands
kCmdWhat = 'WHAT',
kCmdMusic = 'MUZK',
kCmdSoundFX = 'SOUN',
@@ -62,7 +64,10 @@ enum {
kCmdRecall = 'RECL',
kCmdTurbo = 'TURB',
kCmdLook = 'LOOK',
- kCmdInvent = 'INVT'
+ kCmdInvent = 'INVT',
+
+ // EntryDialog commands
+ kCmdButton = 'BTNP'
};
class TopMenu : public GUI::Dialog {
@@ -95,6 +100,22 @@ protected:
uint16 arraySize;
};
+class EntryDialog : public GUI::Dialog {
+public:
+ EntryDialog(const Common::String &title, const Common::String &buttonLabel, const Common::String &defaultValue);
+ virtual ~EntryDialog();
+
+ void reflowLayout();
+ void handleCommand(GUI::CommandSender *sender, uint32 command, uint32 data);
+
+ const Common::String &getEditString() const { return _text->getEditString(); }
+
+protected:
+ void init();
+
+ GUI::EditTextWidget *_text;
+};
+
}
-#endif // HUGO_TOPMENU_H
+#endif // HUGO_DIALOGS_H
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp
index a2902e3b9d..333eb59707 100644
--- a/engines/hugo/display.cpp
+++ b/engines/hugo/display.cpp
@@ -105,17 +105,37 @@ Screen::Screen(HugoEngine *vm) : _vm(vm) {
Screen::~Screen() {
}
+icondib_t &Screen::getIconBuffer() {
+ return _iconBuffer;
+}
+
+viewdib_t &Screen::getBackBuffer() {
+ return _backBuffer;
+}
+
+viewdib_t &Screen::getBackBufferBackup() {
+ return _backBufferBackup;
+}
+
+viewdib_t &Screen::getFrontBuffer() {
+ return _frontBuffer;
+}
+
+viewdib_t &Screen::getGUIBuffer() {
+ return _GUIBuffer;
+}
+
/**
* Replace the palette by the main palette
*/
void Screen::createPal() {
debugC(1, kDebugDisplay, "createPal");
-
- g_system->getPaletteManager()->setPalette(_mainPalette, 0, _paletteSize / 4);
+ g_system->getPaletteManager()->setPalette(_mainPalette, 0, _paletteSize / 3);
}
void Screen::setCursorPal() {
- CursorMan.replaceCursorPalette(_curPalette, 0, _paletteSize / 4);
+ debugC(1, kDebugDisplay, "setCursorPal");
+ CursorMan.replaceCursorPalette(_curPalette, 0, _paletteSize / 3);
}
/**
@@ -169,16 +189,13 @@ void Screen::displayRect(const int16 x, const int16 y, const int16 dx, const int
* Alse save the new color in the current palette.
*/
void Screen::remapPal(const uint16 oldIndex, const uint16 newIndex) {
- debugC(1, kDebugDisplay, "Remap_pal(%d, %d)", oldIndex, newIndex);
+ debugC(1, kDebugDisplay, "RemapPal(%d, %d)", oldIndex, newIndex);
- byte pal[4];
+ _curPalette[3 * oldIndex + 0] = _mainPalette[newIndex * 3 + 0];
+ _curPalette[3 * oldIndex + 1] = _mainPalette[newIndex * 3 + 1];
+ _curPalette[3 * oldIndex + 2] = _mainPalette[newIndex * 3 + 2];
- pal[0] = _curPalette[4 * oldIndex + 0] = _mainPalette[newIndex * 4 + 0];
- pal[1] = _curPalette[4 * oldIndex + 1] = _mainPalette[newIndex * 4 + 1];
- pal[2] = _curPalette[4 * oldIndex + 2] = _mainPalette[newIndex * 4 + 2];
- pal[3] = _curPalette[4 * oldIndex + 3] = _mainPalette[newIndex * 4 + 3];
-
- g_system->getPaletteManager()->setPalette(pal, oldIndex, 1);
+ g_system->getPaletteManager()->setPalette(_curPalette, 0, _paletteSize / 3);
}
/**
@@ -194,21 +211,13 @@ void Screen::savePal(Common::WriteStream *f) const {
/**
* Restore the current palette from a savegame
*/
-void Screen::restorePal(Common::SeekableReadStream *f) {
+void Screen::restorePal(Common::ReadStream *f) {
debugC(1, kDebugDisplay, "restorePal()");
- byte pal[4];
-
for (int i = 0; i < _paletteSize; i++)
_curPalette[i] = f->readByte();
- for (int i = 0; i < _paletteSize / 4; i++) {
- pal[0] = _curPalette[i * 4 + 0];
- pal[1] = _curPalette[i * 4 + 1];
- pal[2] = _curPalette[i * 4 + 2];
- pal[3] = _curPalette[i * 4 + 3];
- g_system->getPaletteManager()->setPalette(pal, i, 1);
- }
+ g_system->getPaletteManager()->setPalette(_curPalette, 0, _paletteSize / 3);
}
@@ -224,24 +233,6 @@ void Screen::setBackgroundColor(const uint16 color) {
}
/**
- * Return the overlay state (Foreground/Background) of the currently
- * processed object by looking down the current column for an overlay
- * base bit set (in which case the object is foreground).
- */
-overlayState_t Screen::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
- debugC(4, kDebugDisplay, "findOvl()");
-
- for (; y < seq_p->lines; y++) { // Each line in object
- byte ovb = _vm->_object->getBaseBoundary((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits
- if (ovb & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set
- return kOvlForeground; // Found a bit - must be foreground
- dst_p += kXPix;
- }
-
- return kOvlBackground; // No bits set, must be background
-}
-
-/**
* Merge an object frame into _frontBuffer at sx, sy and update rectangle list.
* If fore TRUE, force object above any overlay
*/
@@ -252,7 +243,7 @@ void Screen::displayFrame(const int sx, const int sy, seq_t *seq, const bool for
image_pt subFrontBuffer = &_frontBuffer[sy * kXPix + sx]; // Ptr to offset in _frontBuffer
int16 frontBufferwrap = kXPix - seq->x2 - 1; // Wraps dest_p after each line
int16 imageWrap = seq->bytesPerLine8 - seq->x2 - 1;
- overlayState_t overlayState = kOvlUndef; // Overlay state of object
+ overlayState_t overlayState = (foreFl) ? kOvlForeground : kOvlUndef; // Overlay state of object
for (uint16 y = 0; y < seq->lines; y++) { // Each line in object
for (uint16 x = 0; x <= seq->x2; x++) {
if (*image) { // Non-transparent
@@ -260,7 +251,7 @@ void Screen::displayFrame(const int sx, const int sy, seq_t *seq, const bool for
if (ovlBound & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
if (overlayState == kOvlUndef) // Overlay defined yet?
overlayState = findOvl(seq, subFrontBuffer, y);// No, find it.
- if (foreFl || overlayState == kOvlForeground) // Object foreground
+ if (overlayState == kOvlForeground) // Object foreground
*subFrontBuffer = *image; // Copy pixel
} else { // No overlay
*subFrontBuffer = *image; // Copy pixel
@@ -488,7 +479,7 @@ void Screen::shadowStr(int16 sx, const int16 sy, const char *s, const byte color
* present in the DOS versions
*/
void Screen::userHelp() const {
- Utils::Box(kBoxAny , "%s",
+ Utils::notifyBox(
"F1 - Press F1 again\n"
" for instructions\n"
"F2 - Sound on/off\n"
@@ -585,17 +576,12 @@ void Screen::loadPalette(Common::ReadStream &in) {
}
/**
- * Free main and current palettes
+ * Free fonts, main and current palettes
*/
-void Screen::freePalette() {
+void Screen::freeScreen() {
free(_curPalette);
free(_mainPalette);
-}
-/**
- * Free fonts
- */
-void Screen::freeFonts() {
for (int i = 0; i < kNumFonts; i++) {
if (_arrayFont[i])
free(_arrayFont[i]);
@@ -607,11 +593,7 @@ void Screen::selectInventoryObjId(const int16 objId) {
_vm->_inventory->setInventoryObjId(objId); // Select new object
// Find index of icon
- int16 iconId = 0; // Find index of dragged icon
- for (; iconId < _vm->_maxInvent; iconId++) {
- if (objId == _vm->_invent[iconId])
- break;
- }
+ int16 iconId = _vm->_inventory->findIconId(objId);
// Compute source coordinates in dib_u
int16 ux = (iconId + kArrowNumb) * kInvDx % kXPix;
@@ -654,7 +636,7 @@ bool Screen::isInY(const int16 y, const rect_t *rect) const {
* Check if two rectangles are overlapping
*/
bool Screen::isOverlapping(const rect_t *rectA, const rect_t *rectB) const {
- return (isInX(rectA->x, rectB) || isInX(rectA->x + rectA->dx, rectB) || isInX(rectB->x, rectA) || isInX(rectB->x + rectB->dx, rectA)) &&
+ return (isInX(rectA->x, rectB) || isInX(rectA->x + rectA->dx, rectB) || isInX(rectB->x, rectA) || isInX(rectB->x + rectB->dx, rectA)) &&
(isInY(rectA->y, rectB) || isInY(rectA->y + rectA->dy, rectB) || isInY(rectB->y, rectA) || isInY(rectB->y + rectB->dy, rectA));
}
@@ -674,7 +656,7 @@ void Screen::drawBoundaries() {
object_t *obj = &_vm->_object->_objects[i]; // Get pointer to object
if (obj->screenIndex == *_vm->_screen_p) {
if ((obj->currImagePtr != 0) && (obj->cycling != kCycleInvisible))
- drawRectangle(false, obj->x + obj->currImagePtr->x1, obj->y + obj->currImagePtr->y1,
+ drawRectangle(false, obj->x + obj->currImagePtr->x1, obj->y + obj->currImagePtr->y1,
obj->x + obj->currImagePtr->x2, obj->y + obj->currImagePtr->y2, _TLIGHTGREEN);
else if ((obj->currImagePtr == 0) && (obj->vxPath != 0) && !obj->carriedFl)
drawRectangle(false, obj->oldx, obj->oldy, obj->oldx + obj->vxPath, obj->oldy + obj->vyPath, _TBRIGHTWHITE);
@@ -740,6 +722,25 @@ void Screen_v1d::loadFontArr(Common::ReadStream &in) {
}
}
+/**
+ * Return the overlay state (Foreground/Background) of the currently
+ * processed object by looking down the current column for an overlay
+ * base byte set (in which case the object is foreground).
+ */
+overlayState_t Screen_v1d::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
+ debugC(4, kDebugDisplay, "findOvl()");
+
+ uint16 index = (uint16)(dst_p - _frontBuffer) >> 3;
+
+ for (int i = 0; i < seq_p->lines-y; i++) { // Each line in object
+ if (_vm->_object->getBaseBoundary(index)) // If any overlay base byte is non-zero then the object is foreground, else back.
+ return kOvlForeground;
+ index += kCompLineSize;
+ }
+
+ return kOvlBackground; // No bits set, must be background
+}
+
Screen_v1w::Screen_v1w(HugoEngine *vm) : Screen(vm) {
}
@@ -790,5 +791,23 @@ void Screen_v1w::loadFontArr(Common::ReadStream &in) {
}
}
+/**
+ * Return the overlay state (Foreground/Background) of the currently
+ * processed object by looking down the current column for an overlay
+ * base bit set (in which case the object is foreground).
+ */
+overlayState_t Screen_v1w::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
+ debugC(4, kDebugDisplay, "findOvl()");
+
+ for (; y < seq_p->lines; y++) { // Each line in object
+ byte ovb = _vm->_object->getBaseBoundary((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits
+ if (ovb & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set
+ return kOvlForeground; // Found a bit - must be foreground
+ dst_p += kXPix;
+ }
+
+ return kOvlBackground; // No bits set, must be background
+}
+
} // End of namespace Hugo
diff --git a/engines/hugo/display.h b/engines/hugo/display.h
index 21e9fe2e9c..91e1752df0 100644
--- a/engines/hugo/display.h
+++ b/engines/hugo/display.h
@@ -65,8 +65,7 @@ public:
void drawRectangle(const bool filledFl, const int16 x1, const int16 y1, const int16 x2, const int16 y2, const int color);
void drawShape(const int x, const int y, const int color1, const int color2);
void drawStatusText();
- void freeFonts();
- void freePalette();
+ void freeScreen();
void hideCursor();
void initDisplay();
void initNewScreenDisplay();
@@ -74,7 +73,7 @@ public:
void moveImage(image_pt srcImage, const int16 x1, const int16 y1, const int16 dx, int16 dy, const int16 width1, image_pt dstImage, const int16 x2, const int16 y2, const int16 width2);
void remapPal(uint16 oldIndex, uint16 newIndex);
void resetInventoryObjId();
- void restorePal(Common::SeekableReadStream *f);
+ void restorePal(Common::ReadStream *f);
void savePal(Common::WriteStream *f) const;
void setBackgroundColor(const uint16 color);
void setCursorPal();
@@ -84,25 +83,11 @@ public:
void userHelp() const;
void writeStr(int16 sx, const int16 sy, const char *s, const byte color);
- icondib_t &getIconBuffer() {
- return _iconBuffer;
- }
-
- viewdib_t &getBackBuffer() {
- return _backBuffer;
- }
-
- viewdib_t &getBackBufferBackup() {
- return _backBufferBackup;
- }
-
- viewdib_t &getFrontBuffer() {
- return _frontBuffer;
- }
-
- viewdib_t &getGUIBuffer() {
- return _GUIBuffer;
- }
+ icondib_t &getIconBuffer();
+ viewdib_t &getBackBuffer();
+ viewdib_t &getBackBufferBackup();
+ viewdib_t &getFrontBuffer();
+ viewdib_t &getGUIBuffer();
protected:
HugoEngine *_vm;
@@ -116,10 +101,6 @@ protected:
static const byte stdMouseCursorHeight = 20;
static const byte stdMouseCursorWidth = 12;
- inline bool isInX(const int16 x, const rect_t *rect) const;
- inline bool isInY(const int16 y, const rect_t *rect) const;
- inline bool isOverlapping(const rect_t *rectA, const rect_t *rectB) const;
-
bool fontLoadedFl[kNumFonts];
// Fonts used in dib (non-GDI)
@@ -130,6 +111,14 @@ protected:
byte *_mainPalette;
int16 _arrayFontSize[kNumFonts];
+ viewdib_t _frontBuffer;
+
+ inline bool isInX(const int16 x, const rect_t *rect) const;
+ inline bool isInY(const int16 y, const rect_t *rect) const;
+ inline bool isOverlapping(const rect_t *rectA, const rect_t *rectB) const;
+
+ virtual overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) = 0;
+
private:
byte *_curPalette;
byte _iconImage[kInvDx * kInvDy];
@@ -140,9 +129,6 @@ private:
int16 mergeLists(rect_t *list, rect_t *blist, const int16 len, int16 blen);
int16 center(const char *s) const;
- overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y);
-
- viewdib_t _frontBuffer;
viewdib_t _backBuffer;
viewdib_t _GUIBuffer; // User interface images
viewdib_t _backBufferBackup; // Backup _backBuffer during inventory
@@ -166,6 +152,8 @@ public:
void loadFont(int16 fontId);
void loadFontArr(Common::ReadStream &in);
+protected:
+ overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y);
};
class Screen_v1w : public Screen {
@@ -175,6 +163,8 @@ public:
void loadFont(int16 fontId);
void loadFontArr(Common::ReadStream &in);
+protected:
+ overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y);
};
} // End of namespace Hugo
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index 7427771906..a0e3ff05ce 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -46,15 +46,49 @@
#include "hugo/mouse.h"
namespace Hugo {
+
+namespace {
+static const char s_bootCypher[] = "Copyright 1992, David P Gray, Gray Design Associates";
+static const int s_bootCypherLen = sizeof(s_bootCypher) - 1;
+}
+
+
FileManager::FileManager(HugoEngine *vm) : _vm(vm) {
has_read_header = false;
- firstUIFFl = true;
+ firstUIFFl = true;
}
FileManager::~FileManager() {
}
/**
+ * Name scenery and objects picture databases
+ */
+const char *FileManager::getBootFilename() const {
+ return "HUGO.BSF";
+}
+
+const char *FileManager::getObjectFilename() const {
+ return "objects.dat";
+}
+
+const char *FileManager::getSceneryFilename() const {
+ return "scenery.dat";
+}
+
+const char *FileManager::getSoundFilename() const {
+ return "sounds.dat";
+}
+
+const char *FileManager::getStringFilename() const {
+ return "strings.dat";
+}
+
+const char *FileManager::getUifFilename() const {
+ return "uif.dat";
+}
+
+/**
* Convert 4 planes (RGBI) data to 8-bit DIB format
* Return original plane data ptr
*/
@@ -369,31 +403,22 @@ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) {
for (int i = 0; i < _vm->_numScreens; i++)
out->writeByte(_vm->_screenStates[i]);
- // Save points table
- for (int i = 0; i < _vm->_numBonuses; i++) {
- out->writeByte(_vm->_points[i].score);
- out->writeByte((_vm->_points[i].scoredFl) ? 1 : 0);
- }
-
- // Now save current time and all current events in event queue
- _vm->_scheduler->saveEvents(out);
-
- // Now save current actions
- _vm->_scheduler->saveActions(out);
-
+ _vm->_scheduler->saveSchedulerData(out);
// Save palette table
_vm->_screen->savePal(out);
// Save maze status
- out->writeByte((_maze.enabledFl) ? 1 : 0);
- out->writeByte(_maze.size);
- out->writeSint16BE(_maze.x1);
- out->writeSint16BE(_maze.y1);
- out->writeSint16BE(_maze.x2);
- out->writeSint16BE(_maze.y2);
- out->writeSint16BE(_maze.x3);
- out->writeSint16BE(_maze.x4);
- out->writeByte(_maze.firstScreenIndex);
+ out->writeByte((_vm->_maze.enabledFl) ? 1 : 0);
+ out->writeByte(_vm->_maze.size);
+ out->writeSint16BE(_vm->_maze.x1);
+ out->writeSint16BE(_vm->_maze.y1);
+ out->writeSint16BE(_vm->_maze.x2);
+ out->writeSint16BE(_vm->_maze.y2);
+ out->writeSint16BE(_vm->_maze.x3);
+ out->writeSint16BE(_vm->_maze.x4);
+ out->writeByte(_vm->_maze.firstScreenIndex);
+
+ out->writeByte((byte)_vm->getGameStatus().viewState);
out->finalize();
@@ -475,33 +500,26 @@ bool FileManager::restoreGame(const int16 slot) {
for (int i = 0; i < _vm->_numScreens; i++)
_vm->_screenStates[i] = in->readByte();
- // Restore points table
- for (int i = 0; i < _vm->_numBonuses; i++) {
- _vm->_points[i].score = in->readByte();
- _vm->_points[i].scoredFl = (in->readByte() == 1);
- }
-
- _vm->_object->restoreAllSeq();
-
- // Now restore time of the save and the event queue
- _vm->_scheduler->restoreEvents(in);
-
- // Now restore actions
- _vm->_scheduler->restoreActions(in);
+ _vm->_scheduler->restoreSchedulerData(in);
// Restore palette and change it if necessary
_vm->_screen->restorePal(in);
// Restore maze status
- _maze.enabledFl = (in->readByte() == 1);
- _maze.size = in->readByte();
- _maze.x1 = in->readSint16BE();
- _maze.y1 = in->readSint16BE();
- _maze.x2 = in->readSint16BE();
- _maze.y2 = in->readSint16BE();
- _maze.x3 = in->readSint16BE();
- _maze.x4 = in->readSint16BE();
- _maze.firstScreenIndex = in->readByte();
+ _vm->_maze.enabledFl = (in->readByte() == 1);
+ _vm->_maze.size = in->readByte();
+ _vm->_maze.x1 = in->readSint16BE();
+ _vm->_maze.y1 = in->readSint16BE();
+ _vm->_maze.x2 = in->readSint16BE();
+ _vm->_maze.y2 = in->readSint16BE();
+ _vm->_maze.x3 = in->readSint16BE();
+ _vm->_maze.x4 = in->readSint16BE();
+ _vm->_maze.firstScreenIndex = in->readByte();
+
+ _vm->_scheduler->restoreScreen(*_vm->_screen_p);
+ if ((_vm->getGameStatus().viewState = (vstate_t) in->readByte()) != kViewPlay)
+ _vm->_screen->hideCursor();
+
delete in;
return true;
@@ -512,34 +530,38 @@ bool FileManager::restoreGame(const int16 slot) {
*/
void FileManager::printBootText() {
debugC(1, kDebugFile, "printBootText()");
- static const char *cypher = getBootCypher();
Common::File ofp;
if (!ofp.open(getBootFilename())) {
- if (_vm->_gameVariant == kGameVariantH1Dos) {
+ if (_vm->getPlatform() == Common::kPlatformPC) {
//TODO initialize properly _boot structure
- warning("printBootText - Skipping as H1 Dos may be a freeware");
+ warning("printBootText - Skipping as Dos versions may be a freeware or shareware");
return;
} else {
- error("Missing startup file");
+ Utils::notifyBox(Common::String::format("Missing startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
}
}
// Allocate space for the text and print it
- char *buf = (char *)malloc(_boot.exit_len + 1);
+ char *buf = (char *)malloc(_vm->_boot.exit_len + 1);
if (buf) {
// Skip over the boot structure (already read) and read exit text
- ofp.seek((long)sizeof(_boot), SEEK_SET);
- if (ofp.read(buf, _boot.exit_len) != (size_t)_boot.exit_len)
- error("Error while reading startup file");
+ ofp.seek((long)sizeof(_vm->_boot), SEEK_SET);
+ if (ofp.read(buf, _vm->_boot.exit_len) != (size_t)_vm->_boot.exit_len) {
+ Utils::notifyBox(Common::String::format("Error while reading startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
+ }
// Decrypt the exit text, using CRYPT substring
int i;
- for (i = 0; i < _boot.exit_len; i++)
- buf[i] ^= cypher[i % strlen(cypher)];
+ for (i = 0; i < _vm->_boot.exit_len; i++)
+ buf[i] ^= s_bootCypher[i % s_bootCypherLen];
buf[i] = '\0';
- Utils::Box(kBoxOk, "%s", buf);
+ Utils::notifyBox(buf);
}
free(buf);
@@ -552,39 +574,52 @@ void FileManager::printBootText() {
*/
void FileManager::readBootFile() {
debugC(1, kDebugFile, "readBootFile()");
- static const char *cypher = getBootCypher();
Common::File ofp;
if (!ofp.open(getBootFilename())) {
if (_vm->_gameVariant == kGameVariantH1Dos) {
//TODO initialize properly _boot structure
warning("readBootFile - Skipping as H1 Dos may be a freeware");
+ memset(_vm->_boot.distrib, '\0', sizeof(_vm->_boot.distrib));
+ _vm->_boot.registered = kRegFreeware;
+ return;
+ } else if (_vm->getPlatform() == Common::kPlatformPC) {
+ warning("readBootFile - Skipping as H2 and H3 Dos may be shareware");
+ memset(_vm->_boot.distrib, '\0', sizeof(_vm->_boot.distrib));
+ _vm->_boot.registered = kRegShareware;
return;
} else {
- error("Missing startup file");
+ Utils::notifyBox(Common::String::format("Missing startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
}
}
- if (ofp.size() < (int32)sizeof(_boot))
- error("Corrupted startup file");
+ if (ofp.size() < (int32)sizeof(_vm->_boot)) {
+ Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
+ }
- _boot.checksum = ofp.readByte();
- _boot.registered = ofp.readByte();
- ofp.read(_boot.pbswitch, sizeof(_boot.pbswitch));
- ofp.read(_boot.distrib, sizeof(_boot.distrib));
- _boot.exit_len = ofp.readUint16LE();
+ _vm->_boot.checksum = ofp.readByte();
+ _vm->_boot.registered = ofp.readByte();
+ ofp.read(_vm->_boot.pbswitch, sizeof(_vm->_boot.pbswitch));
+ ofp.read(_vm->_boot.distrib, sizeof(_vm->_boot.distrib));
+ _vm->_boot.exit_len = ofp.readUint16LE();
- byte *p = (byte *)&_boot;
+ byte *p = (byte *)&_vm->_boot;
byte checksum = 0;
- for (uint32 i = 0; i < sizeof(_boot); i++) {
+ for (uint32 i = 0; i < sizeof(_vm->_boot); i++) {
checksum ^= p[i];
- p[i] ^= cypher[i % strlen(cypher)];
+ p[i] ^= s_bootCypher[i % s_bootCypherLen];
}
ofp.close();
- if (checksum)
- error("Corrupted startup file");
+ if (checksum) {
+ Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ }
}
/**
@@ -656,8 +691,5 @@ void FileManager::readUIFImages() {
readUIFItem(UIF_IMAGES, _vm->_screen->getGUIBuffer()); // Read all uif images
}
-const char *FileManager::getBootCypher() const {
- return "Copyright 1992, David P Gray, Gray Design Associates";
-}
} // End of namespace Hugo
diff --git a/engines/hugo/file.h b/engines/hugo/file.h
index f62c78e580..0e131348f9 100644
--- a/engines/hugo/file.h
+++ b/engines/hugo/file.h
@@ -39,6 +39,12 @@ namespace Hugo {
*/
enum ovl_t {kOvlBoundary, kOvlOverlay, kOvlBase};
+struct uif_hdr_t { // UIF font/image look up
+ uint16 size; // Size of uif item
+ uint32 offset; // Offset of item in file
+};
+
+
class FileManager {
public:
FileManager(HugoEngine *vm);
@@ -54,12 +60,12 @@ public:
bool saveGame(const int16 slot, const Common::String &descrip);
// Name scenery and objects picture databases
- const char *getBootFilename() const { return "HUGO.BSF"; }
- const char *getObjectFilename() const { return "objects.dat"; }
- const char *getSceneryFilename() const { return "scenery.dat"; }
- const char *getSoundFilename() const { return "sounds.dat"; }
- const char *getStringFilename() const { return "strings.dat"; }
- const char *getUifFilename() const { return "uif.dat"; }
+ const char *getBootFilename() const;
+ const char *getObjectFilename() const;
+ const char *getSceneryFilename() const;
+ const char *getSoundFilename() const;
+ const char *getStringFilename() const;
+ const char *getUifFilename() const;
virtual void openDatabaseFiles() = 0;
virtual void closeDatabaseFiles() = 0;
@@ -76,6 +82,7 @@ protected:
static const int kMaxSounds = 64; // Max number of sounds
static const int kRepeatMask = 0xC0; // Top 2 bits mean a repeat code
static const int kLengthMask = 0x3F; // Lower 6 bits are length
+ static const int kNumColors = 16; // Num colors to save in palette
/**
* Structure of scenery file lookup entry
@@ -91,8 +98,6 @@ protected:
uint32 ob_len;
};
- static const int kNumColors = 16; // Num colors to save in palette
-
struct PCC_header_t { // Structure of PCX file header
byte mfctr, vers, enc, bpx;
uint16 x1, y1, x2, y2; // bounding box
@@ -113,7 +118,6 @@ protected:
PCC_header_t PCC_header;
seq_t *readPCX(Common::ReadStream &f, seq_t *seqPtr, byte *imagePtr, const bool firstFl, const char *name);
- const char *getBootCypher() const;
// If this is the first call, read the lookup table
bool has_read_header;
diff --git a/engines/hugo/file_v1d.cpp b/engines/hugo/file_v1d.cpp
index be23edb7b4..48f274e88a 100644
--- a/engines/hugo/file_v1d.cpp
+++ b/engines/hugo/file_v1d.cpp
@@ -63,8 +63,7 @@ void FileManager_v1d::readOverlay(const int screenNum, image_pt image, const ovl
Common::String buf = Common::String(_vm->_text->getScreenNames(screenNum)) + Common::String(ovl_ext[overlayType]);
if (!Common::File::exists(buf)) {
- for (int i = 0; i < kOvlSize; i++)
- image[i] = 0;
+ memset(image, 0, sizeof(image));
warning("File not found: %s", buf.c_str());
return;
}
@@ -122,7 +121,7 @@ void FileManager_v1d::instructions() const {
f.read(wrkLine, 1);
} while (*wrkLine++ != '#'); // '#' is EOP
wrkLine[-2] = '\0'; // Remove EOP and previous CR
- Utils::Box(kBoxAny, "%s", line);
+ Utils::notifyBox(line);
wrkLine = line;
f.read(readBuf, 2); // Remove CRLF after EOP
}
diff --git a/engines/hugo/file_v1w.cpp b/engines/hugo/file_v1w.cpp
index b902e50f15..dbb093752a 100644
--- a/engines/hugo/file_v1w.cpp
+++ b/engines/hugo/file_v1w.cpp
@@ -81,8 +81,7 @@ void FileManager_v1w::readOverlay(const int screenNum, image_pt image, ovl_t ove
break;
}
if (i == 0) {
- for (int idx = 0; idx < kOvlSize; idx++)
- image[idx] = 0;
+ memset(image, 0, sizeof(image));
return;
}
_sceneryArchive1.read(tmpImage, kOvlSize);
diff --git a/engines/hugo/file_v2d.cpp b/engines/hugo/file_v2d.cpp
index 9c66f6375f..ffadd17481 100644
--- a/engines/hugo/file_v2d.cpp
+++ b/engines/hugo/file_v2d.cpp
@@ -137,8 +137,7 @@ void FileManager_v2d::readOverlay(const int screenNum, image_pt image, ovl_t ove
break;
}
if (i == 0) {
- for (int idx = 0; idx < kOvlSize; idx++)
- image[idx] = 0;
+ memset(image, 0, sizeof(image));
return;
}
diff --git a/engines/hugo/file_v2w.cpp b/engines/hugo/file_v2w.cpp
index b917d81bd5..245d4d017e 100644
--- a/engines/hugo/file_v2w.cpp
+++ b/engines/hugo/file_v2w.cpp
@@ -48,7 +48,7 @@ FileManager_v2w::~FileManager_v2w() {
* Same comment than in SCI: maybe in the future we can implement this, but for now this message should suffice
*/
void FileManager_v2w::instructions() const {
- Utils::Box(kBoxAny, "Please use an external viewer to open the game's help file: HUGOWIN%d.HLP", _vm->_gameVariant + 1);
+ Utils::notifyBox(Common::String::format("Please use an external viewer to open the game's help file: HUGOWIN%d.HLP", _vm->_gameVariant + 1));
}
} // End of namespace Hugo
diff --git a/engines/hugo/file_v3d.cpp b/engines/hugo/file_v3d.cpp
index ec0d736bb9..2f3e5af3f0 100644
--- a/engines/hugo/file_v3d.cpp
+++ b/engines/hugo/file_v3d.cpp
@@ -144,8 +144,7 @@ void FileManager_v3d::readOverlay(const int screenNum, image_pt image, ovl_t ove
break;
}
if (i == 0) {
- for (int idx = 0; idx < kOvlSize; idx++)
- image[idx] = 0;
+ memset(image, 0, sizeof(image));
return;
}
@@ -158,7 +157,7 @@ void FileManager_v3d::readOverlay(const int screenNum, image_pt image, ovl_t ove
else if (data >= 0) { // Copy next data+1 literally
for (i = 0; i <= (byte)data; i++, k++)
*tmpImage++ = _sceneryArchive1.readByte();
- } else { // Repeat next byte -data+1 times
+ } else { // Repeat next byte -data+1 times
int16 j = _sceneryArchive1.readByte();
for (i = 0; i < (byte)(-data + 1); i++, k++)
@@ -184,8 +183,7 @@ void FileManager_v3d::readOverlay(const int screenNum, image_pt image, ovl_t ove
break;
}
if (i == 0) {
- for (int idx = 0; idx < kOvlSize; idx++)
- image[idx] = 0;
+ memset(image, 0, sizeof(image));
return;
}
diff --git a/engines/hugo/game.h b/engines/hugo/game.h
index bd62a4bc14..08e8deb001 100644
--- a/engines/hugo/game.h
+++ b/engines/hugo/game.h
@@ -86,64 +86,6 @@ enum path_t {
kPathWander2 // Same as WANDER, except keeps cycling when stationary
};
-/**
- * Following defines the action types and action list
- */
-enum action_t { // Parameters:
- ANULL = 0xff, // Special NOP used to 'delete' events in DEL_EVENTS
- ASCHEDULE = 0, // 0 - Ptr to action list to be rescheduled
- START_OBJ, // 1 - Object number
- INIT_OBJXY, // 2 - Object number, x,y
- PROMPT, // 3 - index of prompt & response string, ptrs to action
- // lists. First if response matches, 2nd if not.
- BKGD_COLOR, // 4 - new background color
- INIT_OBJVXY, // 5 - Object number, vx, vy
- INIT_CARRY, // 6 - Object number, carried status
- INIT_HF_COORD, // 7 - Object number (gets hero's 'feet' coordinates)
- NEW_SCREEN, // 8 - New screen number
- INIT_OBJSTATE, // 9 - Object number, new object state
- INIT_PATH, // 10 - Object number, new path type
- COND_R, // 11 - Conditional on object state - req state, 2 act_lists
- TEXT, // 12 - Simple text box
- SWAP_IMAGES, // 13 - Swap 2 object images
- COND_SCR, // 14 - Conditional on current screen
- AUTOPILOT, // 15 - Set object to home in on another (stationary) object
- INIT_OBJ_SEQ, // 16 - Object number, sequence index to set curr_seq_p to
- SET_STATE_BITS, // 17 - Objnum, mask to OR with obj states word
- CLEAR_STATE_BITS, // 18 - Objnum, mask to ~AND with obj states word
- TEST_STATE_BITS, // 19 - Objnum, mask to test obj states word
- DEL_EVENTS, // 20 - Action type to delete all occurrences of
- GAMEOVER, // 21 - Disable hero & commands. Game is over
- INIT_HH_COORD, // 22 - Object number (gets hero's actual coordinates)
- EXIT, // 23 - Exit game back to DOS
- BONUS, // 24 - Get score bonus for an action
- COND_BOX, // 25 - Conditional on object within bounding box
- SOUND, // 26 - Set currently playing sound
- ADD_SCORE, // 27 - Add object's value to current score
- SUB_SCORE, // 28 - Subtract object's value from current score
- COND_CARRY, // 29 - Conditional on carrying object
- INIT_MAZE, // 30 - Start special maze hotspot processing
- EXIT_MAZE, // 31 - Exit special maze processing
- INIT_PRIORITY, // 32 - Initialize fbg field
- INIT_SCREEN, // 33 - Initialise screen field of object
- AGSCHEDULE, // 34 - Global schedule - lasts over new screen
- REMAPPAL, // 35 - Remappe palette - palette index, color
- COND_NOUN, // 36 - Conditional on noun appearing in line
- SCREEN_STATE, // 37 - Set new screen state - used for comments
- INIT_LIPS, // 38 - Position lips object for supplied object
- INIT_STORY_MODE, // 39 - Set story mode TRUE/FALSE (user can't type)
- WARN, // 40 - Same as TEXT but can't dismiss box by typing
- COND_BONUS, // 41 - Conditional on bonus having been scored
- TEXT_TAKE, // 42 - Issue text box with "take" info string
- YESNO, // 43 - Prompt user for Yes or No
- STOP_ROUTE, // 44 - Skip any route in progress (hero still walks)
- COND_ROUTE, // 45 - Conditional on route in progress
- INIT_JUMPEXIT, // 46 - Initialize status.jumpexit
- INIT_VIEW, // 47 - Initialize viewx, viewy, dir
- INIT_OBJ_FRAME, // 48 - Object number, seq,frame to set curr_seq_p to
- OLD_SONG = 49 // Added by Strangerke - Set currently playing sound, old way: that is, using a string index instead of a reference in a file
-};
-
struct hugo_boot_t { // Common HUGO boot file
char checksum; // Checksum for boot structure (not exit text)
char registered; // TRUE if registered version, else FALSE
@@ -152,11 +94,6 @@ struct hugo_boot_t { // Common HUGO boot file
uint16 exit_len; // Length of exit text (next in file)
} PACKED_STRUCT;
-struct uif_hdr_t { // UIF font/image look up
- uint16 size; // Size of uif item
- uint32 offset; // Offset of item in file
-};
-
/**
* Game specific type definitions
*/
@@ -164,14 +101,6 @@ typedef byte *image_pt; // ptr to an object image (s
typedef byte *sound_pt; // ptr to sound (or music) data
/**
- * Following are points for achieving certain actions.
- */
-struct point_t {
- byte score; // The value of the point
- bool scoredFl; // Whether scored yet
-};
-
-/**
* Structure for initializing maze processing
*/
struct maze_t {
@@ -183,20 +112,6 @@ struct maze_t {
};
/**
- * The following determines how a verb is acted on, for an object
- */
-struct cmd {
- uint16 verbIndex; // the verb
- uint16 reqIndex; // ptr to list of required objects
- uint16 textDataNoCarryIndex; // ptr to string if any of above not carried
- byte reqState; // required state for verb to be done
- byte newState; // new states if verb done
- uint16 textDataWrongIndex; // ptr to string if wrong state
- uint16 textDataDoneIndex; // ptr to string if verb done
- uint16 actIndex; // Ptr to action list if verb done
-};
-
-/**
* The following is a linked list of images in an animation sequence
* The image data is in 8-bit DIB format, i.e. 1 byte = 1 pixel
*/
@@ -216,38 +131,6 @@ struct seqList_t {
seq_t *seqPtr; // Ptr to sequence structure
};
-/**
- * Following is structure of verbs and nouns for 'background' objects
- * These are objects that appear in the various screens, but nothing
- * interesting ever happens with them. Rather than just be dumb and say
- * "don't understand" we produce an interesting msg to keep user sane.
- */
-struct background_t {
- uint16 verbIndex;
- uint16 nounIndex;
- int commentIndex; // Index of comment produced on match
- bool matchFl; // TRUE if noun must match when present
- byte roomState; // "State" of room. Comments might differ.
- byte bonusIndex; // Index of bonus score (0 = no bonus)
-};
-
-typedef background_t *objectList_t;
-
-struct target_t { // Secondary target for action
- uint16 nounIndex; // Secondary object
- uint16 verbIndex; // Action on secondary object
-};
-
-struct uses_t { // Define uses of certain objects
- int16 objId; // Primary object
- uint16 dataIndex; // String if no secondary object matches
- target_t *targets; // List of secondary targets
-};
-
-// Global externs
-extern maze_t _maze; // Maze control structure
-extern hugo_boot_t _boot; // Boot info structure
-
#include "common/pack-start.h" // START STRUCT PACKING
struct sound_hdr_t { // Sound file lookup entry
uint16 size; // Size of sound data in bytes
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index 4a8b74fc1c..ba87f58150 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -28,6 +28,7 @@
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/debug-channels.h"
+#include "common/config-manager.h"
#include "hugo/hugo.h"
#include "hugo/game.h"
@@ -50,14 +51,9 @@ namespace Hugo {
HugoEngine *HugoEngine::s_Engine = 0;
-maze_t _maze; // Default to not in maze
-hugo_boot_t _boot; // Boot info structure file
-
HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(syst), _gameDescription(gd),
- _arrayReqs(0), _invent(0), _uses(0), _catchallList(0), _backgroundObjects(0), _points(0), _cmdList(0),
- _screenActs(0), _hero(0), _heroImage(0), _defltTunes(0), _introX(0), _introY(0), _maxInvent(0), _numBonuses(0),
- _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0), _screenStates(0), _score(0), _maxscore(0),
- _backgroundObjectsSize(0), _screenActsSize(0), _usesSize(0), _lastTime(0), _curTime(0)
+ _hero(0), _heroImage(0), _defltTunes(0), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0),
+ _screenStates(0), _score(0), _maxscore(0), _lastTime(0), _curTime(0), _episode(0)
{
_system = syst;
DebugMan.addDebugChannel(kDebugSchedule, "Schedule", "Script Schedule debug level");
@@ -76,61 +72,22 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy
}
HugoEngine::~HugoEngine() {
- shutdown();
-
- _screen->freePalette();
- _text->freeAllTexts();
-
- free(_introX);
- free(_introY);
-
- if (_arrayReqs) {
- for (int i = 0; _arrayReqs[i] != 0; i++)
- free(_arrayReqs[i]);
- free(_arrayReqs);
- }
+ _file->closeDatabaseFiles();
+ _intro->freeIntroData();
+ _inventory->freeInvent();
_mouse->freeHotspots();
- free(_invent);
-
- if (_uses) {
- for (int i = 0; i < _usesSize; i++)
- free(_uses[i].targets);
- free(_uses);
- }
-
- free(_catchallList);
-
- if (_backgroundObjects) {
- for (int i = 0; i < _backgroundObjectsSize; i++)
- free(_backgroundObjects[i]);
- free(_backgroundObjects);
- }
-
- free(_points);
-
- if (_cmdList) {
- for (int i = 0; i < _cmdListSize; i++)
- free(_cmdList[i]);
- free(_cmdList);
- }
-
- if (_screenActs) {
- for (int i = 0; i < _screenActsSize; i++)
- free(_screenActs[i]);
- free(_screenActs);
- }
-
- _object->freeObjectArr();
- _scheduler->freeActListArr();
+ _object->freeObjects();
+ _parser->freeParser();
+ _scheduler->freeScheduler();
+ _screen->freeScreen();
+ _text->freeAllTexts();
free(_defltTunes);
free(_screenStates);
- _screen->freeFonts();
delete _topMenu;
-
delete _object;
delete _sound;
delete _route;
@@ -148,6 +105,50 @@ HugoEngine::~HugoEngine() {
delete _rnd;
}
+GUI::Debugger *HugoEngine::getDebugger() {
+ return _console;
+}
+
+status_t &HugoEngine::getGameStatus() {
+ return _status;
+}
+
+int HugoEngine::getScore() const {
+ return _score;
+}
+
+void HugoEngine::setScore(const int newScore) {
+ _score = newScore;
+}
+
+void HugoEngine::adjustScore(const int adjustment) {
+ _score += adjustment;
+}
+
+int HugoEngine::getMaxScore() const {
+ return _maxscore;
+}
+
+void HugoEngine::setMaxScore(const int newScore) {
+ _maxscore = newScore;
+}
+
+Common::Error HugoEngine::saveGameState(int slot, const char *desc) {
+ return (_file->saveGame(slot, desc) ? Common::kWritingFailed : Common::kNoError);
+}
+
+Common::Error HugoEngine::loadGameState(int slot) {
+ return (_file->restoreGame(slot) ? Common::kReadingFailed : Common::kNoError);
+}
+
+bool HugoEngine::hasFeature(EngineFeature f) const {
+ return (f == kSupportsRTL) || (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime);
+}
+
+const char *HugoEngine::getCopyrightString() const {
+ return "Copyright 1989-1997 David P Gray, All Rights Reserved.";
+}
+
GameType HugoEngine::getGameType() const {
return _gameType;
}
@@ -160,6 +161,13 @@ bool HugoEngine::isPacked() const {
return _packedFl;
}
+/**
+ * Print options for user when dead
+ */
+void HugoEngine::gameOverMsg() {
+ Utils::notifyBox(_text->getTextUtil(kGameOver));
+}
+
Common::Error HugoEngine::run() {
s_Engine = this;
initGraphics(320, 200, false);
@@ -168,6 +176,10 @@ Common::Error HugoEngine::run() {
_inventory = new InventoryHandler(this);
_route = new Route(this);
_sound = new SoundHandler(this);
+
+ // Setup mixer
+ syncSoundSettings();
+
_text = new TextHandler(this);
_topMenu = new TopMenu(this);
@@ -236,23 +248,32 @@ Common::Error HugoEngine::run() {
_screen->setCursorPal();
_screen->resetInventoryObjId();
+ _scheduler->initCypher();
+
initStatus(); // Initialize game status
initConfig(); // Initialize user's config
- initialize();
- resetConfig(); // Reset user's config
-
- initMachine();
-
- // Start the state machine
- _status.viewState = kViewIntroInit;
-
- _status.doQuitFl = false;
+ if (!_status.doQuitFl) {
+ initialize();
+ resetConfig(); // Reset user's config
+ initMachine();
+
+ // Start the state machine
+ _status.viewState = kViewIntroInit;
+
+ int16 loadSlot = Common::ConfigManager::instance().getInt("save_slot");
+ if (loadSlot >= 0) {
+ _status.skipIntroFl = true;
+ _file->restoreGame(loadSlot);
+ } else {
+ _file->saveGame(0, "New Game");
+ }
+ }
while (!_status.doQuitFl) {
_screen->drawBoundaries();
-
g_system->updateScreen();
runMachine();
+
// Handle input
Common::Event event;
while (_eventMan->pollEvent(event)) {
@@ -277,6 +298,7 @@ Common::Error HugoEngine::run() {
break;
}
}
+
_mouse->mouseHandler(); // Mouse activity - adds to display list
_screen->displayList(kDisplayDisplay); // Blit the display list to screen
_status.doQuitFl |= shouldQuit(); // update game quit flag
@@ -388,209 +410,28 @@ bool HugoEngine::loadHugoDat() {
}
_numVariant = in.readUint16BE();
+
_screen->loadPalette(in);
+ _screen->loadFontArr(in);
_text->loadAllTexts(in);
-
- // Read x_intro and y_intro
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- int numRows = in.readUint16BE();
- if (varnt == _gameVariant) {
- _introXSize = numRows;
- _introX = (byte *)malloc(sizeof(byte) * _introXSize);
- _introY = (byte *)malloc(sizeof(byte) * _introXSize);
- for (int i = 0; i < _introXSize; i++) {
- _introX[i] = in.readByte();
- _introY[i] = in.readByte();
- }
- } else {
- for (int i = 0; i < numRows; i++) {
- in.readByte();
- in.readByte();
- }
- }
- }
-
- // Read _arrayReqs
- _arrayReqs = loadLongArray(in);
-
+ _intro->loadIntroData(in);
+ _parser->loadArrayReqs(in);
+ _parser->loadCatchallList(in);
+ _parser->loadBackgroundObjects(in);
+ _parser->loadCmdList(in);
_mouse->loadHotspots(in);
-
- int numElem, numSubElem;
- //Read _invent
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
- if (varnt == _gameVariant) {
- _maxInvent = numElem;
- _invent = (int16 *)malloc(sizeof(int16) * numElem);
- for (int i = 0; i < numElem; i++)
- _invent[i] = in.readSint16BE();
- } else {
- for (int i = 0; i < numElem; i++)
- in.readSint16BE();
- }
- }
-
- //Read _uses
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
- uses_t *wrkUses = (uses_t *)malloc(sizeof(uses_t) * numElem);
-
- for (int i = 0; i < numElem; i++) {
- wrkUses[i].objId = in.readSint16BE();
- wrkUses[i].dataIndex = in.readUint16BE();
- numSubElem = in.readUint16BE();
- wrkUses[i].targets = (target_t *)malloc(sizeof(target_t) * numSubElem);
- for (int j = 0; j < numSubElem; j++) {
- wrkUses[i].targets[j].nounIndex = in.readUint16BE();
- wrkUses[i].targets[j].verbIndex = in.readUint16BE();
- }
- }
-
- if (varnt == _gameVariant) {
- _usesSize = numElem;
- _uses = wrkUses;
- } else {
- for (int i = 0; i < numElem; i++)
- free(wrkUses[i].targets);
- free(wrkUses);
- }
- }
-
- //Read _catchallList
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
- background_t *wrkCatchallList = (background_t *)malloc(sizeof(background_t) * numElem);
-
- for (int i = 0; i < numElem; i++) {
- wrkCatchallList[i].verbIndex = in.readUint16BE();
- wrkCatchallList[i].nounIndex = in.readUint16BE();
- wrkCatchallList[i].commentIndex = in.readSint16BE();
- wrkCatchallList[i].matchFl = (in.readByte() != 0);
- wrkCatchallList[i].roomState = in.readByte();
- wrkCatchallList[i].bonusIndex = in.readByte();
- }
-
- if (varnt == _gameVariant)
- _catchallList = wrkCatchallList;
- else
- free(wrkCatchallList);
- }
-
- // Read _background_objects
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
-
- background_t **wrkBackgroundObjects = (background_t **)malloc(sizeof(background_t *) * numElem);
-
- for (int i = 0; i < numElem; i++) {
- numSubElem = in.readUint16BE();
- wrkBackgroundObjects[i] = (background_t *)malloc(sizeof(background_t) * numSubElem);
- for (int j = 0; j < numSubElem; j++) {
- wrkBackgroundObjects[i][j].verbIndex = in.readUint16BE();
- wrkBackgroundObjects[i][j].nounIndex = in.readUint16BE();
- wrkBackgroundObjects[i][j].commentIndex = in.readSint16BE();
- wrkBackgroundObjects[i][j].matchFl = (in.readByte() != 0);
- wrkBackgroundObjects[i][j].roomState = in.readByte();
- wrkBackgroundObjects[i][j].bonusIndex = in.readByte();
- }
- }
-
- if (varnt == _gameVariant) {
- _backgroundObjectsSize = numElem;
- _backgroundObjects = wrkBackgroundObjects;
- } else {
- for (int i = 0; i < numElem; i++)
- free(wrkBackgroundObjects[i]);
- free(wrkBackgroundObjects);
- }
- }
-
- // Read _points
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
- if (varnt == _gameVariant) {
- _numBonuses = numElem;
- _points = (point_t *)malloc(sizeof(point_t) * _numBonuses);
- for (int i = 0; i < _numBonuses; i++) {
- _points[i].score = in.readByte();
- _points[i].scoredFl = false;
- }
- } else {
- for (int i = 0; i < numElem; i++)
- in.readByte();
- }
- }
-
- // Read _cmdList
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
- if (varnt == _gameVariant) {
- _cmdListSize = numElem;
- _cmdList = (cmd **)malloc(sizeof(cmd *) * _cmdListSize);
- for (int i = 0; i < _cmdListSize; i++) {
- numSubElem = in.readUint16BE();
- _cmdList[i] = (cmd *)malloc(sizeof(cmd) * numSubElem);
- for (int j = 0; j < numSubElem; j++) {
- _cmdList[i][j].verbIndex = in.readUint16BE();
- _cmdList[i][j].reqIndex = in.readUint16BE();
- _cmdList[i][j].textDataNoCarryIndex = in.readUint16BE();
- _cmdList[i][j].reqState = in.readByte();
- _cmdList[i][j].newState = in.readByte();
- _cmdList[i][j].textDataWrongIndex = in.readUint16BE();
- _cmdList[i][j].textDataDoneIndex = in.readUint16BE();
- _cmdList[i][j].actIndex = in.readUint16BE();
- }
- }
- } else {
- for (int i = 0; i < numElem; i++) {
- numSubElem = in.readUint16BE();
- for (int j = 0; j < numSubElem; j++) {
- in.readUint16BE();
- in.readUint16BE();
- in.readUint16BE();
- in.readByte();
- in.readByte();
- in.readUint16BE();
- in.readUint16BE();
- in.readUint16BE();
- }
- }
- }
- }
-
- // Read _screenActs
- for (int varnt = 0; varnt < _numVariant; varnt++) {
- numElem = in.readUint16BE();
-
- uint16 **wrkScreenActs = (uint16 **)malloc(sizeof(uint16 *) * numElem);
- for (int i = 0; i < numElem; i++) {
- numSubElem = in.readUint16BE();
- if (numSubElem == 0) {
- wrkScreenActs[i] = 0;
- } else {
- wrkScreenActs[i] = (uint16 *)malloc(sizeof(uint16) * numSubElem);
- for (int j = 0; j < numSubElem; j++)
- wrkScreenActs[i][j] = in.readUint16BE();
- }
- }
-
- if (varnt == _gameVariant) {
- _screenActsSize = numElem;
- _screenActs = wrkScreenActs;
- } else {
- for (int i = 0; i < numElem; i++)
- free(wrkScreenActs[i]);
- free(wrkScreenActs);
- }
- }
+ _inventory->loadInvent(in);
+ _object->loadObjectUses(in);
_object->loadObjectArr(in);
-
+ _object->loadNumObj(in);
+ _scheduler->loadPoints(in);
+ _scheduler->loadScreenAct(in);
+ _scheduler->loadActListArr(in);
+ _scheduler->loadAlNewscrIndex(in);
_hero = &_object->_objects[kHeroIndex]; // This always points to hero
_screen_p = &(_object->_objects[kHeroIndex].screenIndex); // Current screen is hero's
_heroImage = kHeroIndex; // Current in use hero image
- _scheduler->loadActListArr(in);
-
for (int varnt = 0; varnt < _numVariant; varnt++) {
if (varnt == _gameVariant) {
_tunesNbr = in.readSByte();
@@ -603,6 +444,8 @@ bool HugoEngine::loadHugoDat() {
}
}
+ int numElem;
+
//Read _defltTunes
for (int varnt = 0; varnt < _numVariant; varnt++) {
numElem = in.readUint16BE();
@@ -621,8 +464,7 @@ bool HugoEngine::loadHugoDat() {
numElem = in.readUint16BE();
if (varnt == _gameVariant) {
_screenStates = (byte *)malloc(sizeof(byte) * numElem);
- for (int i = 0; i < numElem; i++)
- _screenStates[i] = 0;
+ memset(_screenStates, 0, sizeof(_screenStates));
}
}
@@ -639,16 +481,13 @@ bool HugoEngine::loadHugoDat() {
}
}
- _object->loadNumObj(in);
- _scheduler->loadAlNewscrIndex(in);
_sound->loadIntroSong(in);
- _screen->loadFontArr(in);
_topMenu->loadBmpArr(in);
return true;
}
-uint16 **HugoEngine::loadLongArray(Common::ReadStream &in) {
+uint16 **HugoEngine::loadLongArray(Common::SeekableReadStream &in) {
uint16 **resArray = 0;
for (int varnt = 0; varnt < _numVariant; varnt++) {
@@ -665,8 +504,7 @@ uint16 **HugoEngine::loadLongArray(Common::ReadStream &in) {
resRow[j] = in.readUint16BE();
resArray[i] = resRow;
} else {
- for (int j = 0; j < numElems; j++)
- in.readUint16BE();
+ in.skip(numElems * sizeof(uint16));
}
}
}
@@ -792,16 +630,6 @@ void HugoEngine::initialize() {
}
/**
- * Restore all resources before termination
- */
-void HugoEngine::shutdown() {
- debugC(1, kDebugEngine, "shutdown");
-
- _file->closeDatabaseFiles();
- _object->freeObjects();
-}
-
-/**
* Read scenery, overlay files for given screen number
*/
void HugoEngine::readScreenFiles(const int screenNum) {
@@ -809,6 +637,13 @@ void HugoEngine::readScreenFiles(const int screenNum) {
_file->readBackground(screenNum); // Scenery file
memcpy(_screen->getBackBuffer(), _screen->getFrontBuffer(), sizeof(_screen->getFrontBuffer())); // Make a copy
+
+ // Workaround for graphic glitches in DOS versions. Cleaning the overlays fix the problem
+ memset(_object->_objBound, '\0', sizeof(overlay_t));
+ memset(_object->_boundary, '\0', sizeof(overlay_t));
+ memset(_object->_overlay, '\0', sizeof(overlay_t));
+ memset(_object->_ovlBase, '\0', sizeof(overlay_t));
+
_file->readOverlay(screenNum, _object->_boundary, kOvlBoundary); // Boundary file
_file->readOverlay(screenNum, _object->_overlay, kOvlOverlay); // Overlay file
_file->readOverlay(screenNum, _object->_ovlBase, kOvlBase); // Overlay base file
@@ -820,37 +655,6 @@ void HugoEngine::readScreenFiles(const int screenNum) {
}
/**
- * Search background command list for this screen for supplied object.
- * Return first associated verb (not "look") or 0 if none found.
- */
-const char *HugoEngine::useBG(const char *name) {
- debugC(1, kDebugEngine, "useBG(%s)", name);
-
- objectList_t p = _backgroundObjects[*_screen_p];
- for (int i = 0; p[i].verbIndex != 0; i++) {
- if ((name == _text->getNoun(p[i].nounIndex, 0) &&
- p[i].verbIndex != _look) &&
- ((p[i].roomState == kStateDontCare) || (p[i].roomState == _screenStates[*_screen_p])))
- return _text->getVerb(p[i].verbIndex, 0);
- }
-
- return 0;
-}
-
-/**
- * Add action lists for this screen to event queue
- */
-void HugoEngine::screenActions(const int screenNum) {
- debugC(1, kDebugEngine, "screenActions(%d)", screenNum);
-
- uint16 *screenAct = _screenActs[screenNum];
- if (screenAct) {
- for (int i = 0; screenAct[i]; i++)
- _scheduler->insertActionList(screenAct[i]);
- }
-}
-
-/**
* Set the new screen number into the hero object and any carried objects
*/
void HugoEngine::setNewScreen(const int screenNum) {
@@ -866,10 +670,7 @@ void HugoEngine::setNewScreen(const int screenNum) {
void HugoEngine::calcMaxScore() {
debugC(1, kDebugEngine, "calcMaxScore");
- _maxscore = _object->calcMaxScore();
-
- for (int i = 0; i < _numBonuses; i++)
- _maxscore += _points[i].score;
+ _maxscore = _object->calcMaxScore() + _scheduler->calcMaxPoints();
}
/**
@@ -878,9 +679,9 @@ void HugoEngine::calcMaxScore() {
void HugoEngine::endGame() {
debugC(1, kDebugEngine, "endGame");
- if (!_boot.registered)
- Utils::Box(kBoxAny, "%s", _text->getTextEngine(kEsAdvertise));
- Utils::Box(kBoxAny, "%s\n%s", _episode, getCopyrightString());
+ if (_boot.registered != kRegRegistered)
+ Utils::notifyBox(_text->getTextEngine(kEsAdvertise));
+ Utils::notifyBox(Common::String::format("%s\n%s", _episode, getCopyrightString()));
_status.viewState = kViewExit;
}
diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h
index b73b24eccf..ed021f5cd6 100644
--- a/engines/hugo/hugo.h
+++ b/engines/hugo/hugo.h
@@ -29,14 +29,14 @@
#include "engines/engine.h"
#include "common/file.h"
#include "hugo/console.h"
-#include "hugo/menu.h"
+#include "hugo/dialogs.h"
// This include is here temporarily while the engine is being refactored.
#include "hugo/game.h"
#include "hugo/file.h"
#define HUGO_DAT_VER_MAJ 0 // 1 byte
-#define HUGO_DAT_VER_MIN 41 // 1 byte
+#define HUGO_DAT_VER_MIN 42 // 1 byte
#define DATAALIGNMENT 4
namespace Common {
@@ -58,7 +58,7 @@ class RandomSource;
*/
namespace Hugo {
-static const int kSavegameVersion = 3;
+static const int kSavegameVersion = 6;
static const int kInvDx = 32; // Width of an inventory icon
static const int kInvDy = 32; // Height of inventory icon
static const int kMaxTunes = 16; // Max number of tunes
@@ -125,10 +125,11 @@ enum HugoDebugChannels {
kDebugMusic = 1 << 9
};
-/**
- * Ways to dismiss a text/prompt box
- */
-enum box_t {kBoxAny, kBoxOk, kBoxPrompt, kBoxYesNo};
+enum HugoRegistered {
+ kRegShareware = 0,
+ kRegRegistered,
+ kRegFreeware
+};
/**
* Inventory icon bar states
@@ -233,8 +234,6 @@ public:
byte _numVariant;
byte _gameVariant;
- byte _maxInvent;
- byte _numBonuses;
int8 _soundSilence;
int8 _soundTest;
int8 _tunesNbr;
@@ -244,30 +243,18 @@ public:
object_t *_hero;
byte *_screen_p;
byte _heroImage;
-
- byte *_introX;
- byte *_introY;
byte *_screenStates;
command_t _line; // Line of user text input
config_t _config; // User's config
- uint16 **_arrayReqs;
- int16 *_invent;
- uses_t *_uses;
- uint16 _usesSize;
- background_t *_catchallList;
- background_t **_backgroundObjects;
- uint16 _backgroundObjectsSize;
- point_t *_points;
- cmd **_cmdList;
- uint16 _cmdListSize;
- uint16 **_screenActs;
- uint16 _screenActsSize;
int16 *_defltTunes;
uint16 _look;
uint16 _take;
uint16 _drop;
- GUI::Debugger *getDebugger() { return _console; }
+ maze_t _maze; // Maze control structure
+ hugo_boot_t _boot; // Boot info structure
+
+ GUI::Debugger *getDebugger();
Common::RandomSource *_rnd;
@@ -285,7 +272,7 @@ public:
Common::Platform getPlatform() const;
bool isPacked() const;
- // Temporary, until the engine is fully objectified.
+ // Used by the qsort function
static HugoEngine &get() {
assert(s_Engine != 0);
return *s_Engine;
@@ -295,56 +282,31 @@ public:
virtual bool canSaveGameStateCurrently();
bool loadHugoDat();
- const char *useBG(const char *name);
-
int8 getTPS() const;
void initGame(const HugoGameDescription *gd);
void initGamePart(const HugoGameDescription *gd);
void endGame();
+ void gameOverMsg();
void initStatus();
void readScreenFiles(const int screen);
- void screenActions(const int screen);
void setNewScreen(const int screen);
void shutdown();
void syncSoundSettings();
- status_t &getGameStatus() {
- return _status;
- }
- int getScore() const {
- return _score;
- }
- void setScore(const int newScore) {
- _score = newScore;
- }
- void adjustScore(const int adjustment) {
- _score += adjustment;
- }
- int getMaxScore() const {
- return _maxscore;
- }
- void setMaxScore(const int newScore) {
- _maxscore = newScore;
- }
- byte getIntroSize() {
- return _introXSize;
- }
- Common::Error saveGameState(int slot, const char *desc) {
- return (_file->saveGame(slot, desc) ? Common::kWritingFailed : Common::kNoError);
- }
-
- Common::Error loadGameState(int slot) {
- return (_file->restoreGame(slot) ? Common::kReadingFailed : Common::kNoError);
- }
-
- bool hasFeature(EngineFeature f) const {
- return (f == kSupportsRTL) || (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime);
- }
-
- const char *getCopyrightString() const { return "Copyright 1989-1997 David P Gray, All Rights Reserved."; }
+ status_t &getGameStatus();
+ int getScore() const;
+ void setScore(const int newScore);
+ void adjustScore(const int adjustment);
+ int getMaxScore() const;
+ void setMaxScore(const int newScore);
+ Common::Error saveGameState(int slot, const char *desc);
+ Common::Error loadGameState(int slot);
+ bool hasFeature(EngineFeature f) const;
+ const char *getCopyrightString() const;
Common::String getSavegameFilename(int slot);
+ uint16 **loadLongArray(Common::SeekableReadStream &in);
FileManager *_file;
Scheduler *_scheduler;
@@ -357,7 +319,6 @@ public:
IntroHandler *_intro;
ObjectHandler *_object;
TextHandler *_text;
-
TopMenu *_topMenu;
protected:
@@ -368,7 +329,6 @@ protected:
private:
static const int kTurboTps = 16; // This many in turbo mode
- byte _introXSize;
status_t _status; // Game status structure
uint32 _lastTime;
uint32 _curTime;
@@ -384,8 +344,6 @@ private:
int _score; // Holds current score
int _maxscore; // Holds maximum score
- uint16 **loadLongArray(Common::ReadStream &in);
-
void initPlaylist(bool playlist[kMaxTunes]);
void initConfig();
void initialize();
diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp
index 02fb94c83d..63e81924c4 100644
--- a/engines/hugo/intro.cpp
+++ b/engines/hugo/intro.cpp
@@ -41,12 +41,42 @@
namespace Hugo {
-IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm) {
+IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm), _introX(0), _introY(0) {
+ _introXSize = 0;
}
IntroHandler::~IntroHandler() {
}
+byte IntroHandler::getIntroSize() const {
+ return _introXSize;
+}
+
+/**
+ * Read _introX and _introY from hugo.dat
+ */
+void IntroHandler::loadIntroData(Common::SeekableReadStream &in) {
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ int numRows = in.readUint16BE();
+ if (varnt == _vm->_gameVariant) {
+ _introXSize = numRows;
+ _introX = (byte *)malloc(sizeof(byte) * _introXSize);
+ _introY = (byte *)malloc(sizeof(byte) * _introXSize);
+ for (int i = 0; i < _introXSize; i++) {
+ _introX[i] = in.readByte();
+ _introY[i] = in.readByte();
+ }
+ } else {
+ in.skip(numRows * 2);
+ }
+ }
+}
+
+void IntroHandler::freeIntroData() {
+ free(_introX);
+ free(_introY);
+}
+
intro_v1d::intro_v1d(HugoEngine *vm) : IntroHandler(vm) {
}
@@ -68,7 +98,7 @@ void intro_v1d::introInit() {
}
bool intro_v1d::introPlay() {
- byte introSize = _vm->getIntroSize();
+ byte introSize = getIntroSize();
if (_vm->getGameStatus().skipIntroFl)
return true;
@@ -89,16 +119,20 @@ bool intro_v1d::introPlay() {
error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 8");
char buffer[80];
- if (_boot.registered)
+ if (_vm->_boot.registered == kRegRegistered)
strcpy(buffer, "Registered Version");
- else
+ else if (_vm->_boot.registered == kRegShareware)
strcpy(buffer, "Shareware Version");
+ else if (_vm->_boot.registered == kRegFreeware)
+ strcpy(buffer, "Freeware Version");
+ else
+ error("Unknown registration flag in hugo.bsf: %d", _vm->_boot.registered);
font.drawString(&surf, buffer, 0, 163, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
font.drawString(&surf, _vm->getCopyrightString(), 0, 176, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
- if (scumm_stricmp(_boot.distrib, "David P. Gray")) {
- sprintf(buffer, "Distributed by %s.", _boot.distrib);
+ if ((*_vm->_boot.distrib != '\0') && (scumm_stricmp(_vm->_boot.distrib, "David P. Gray"))) {
+ sprintf(buffer, "Distributed by %s.", _vm->_boot.distrib);
font.drawString(&surf, buffer, 0, 75, 320, _TMAGENTA, Graphics::kTextAlignCenter);
}
@@ -221,16 +255,16 @@ void intro_v2d::introInit() {
if (!font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 8)))
error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 8");
- if (_boot.registered)
+ if (_vm->_boot.registered)
sprintf(buffer, "%s Registered Version", _vm->getCopyrightString());
else
sprintf(buffer, "%s Shareware Version", _vm->getCopyrightString());
font.drawString(&surf, buffer, 0, 186, 320, _TLIGHTRED, Graphics::kTextAlignCenter);
- if (scumm_stricmp(_boot.distrib, "David P. Gray")) {
+ if ((*_vm->_boot.distrib != '\0') && (scumm_stricmp(_vm->_boot.distrib, "David P. Gray"))) {
// TROMAN, size 10-5
- sprintf(buffer, "Distributed by %s.", _boot.distrib);
+ sprintf(buffer, "Distributed by %s.", _vm->_boot.distrib);
font.drawString(&surf, buffer, 0, 1, 320, _TLIGHTRED, Graphics::kTextAlignCenter);
}
@@ -262,7 +296,7 @@ void intro_v3d::introInit() {
surf.bytesPerPixel = 1;
char buffer[128];
- if (_boot.registered)
+ if (_vm->_boot.registered)
sprintf(buffer, "%s Registered Version", _vm->getCopyrightString());
else
sprintf(buffer,"%s Shareware Version", _vm->getCopyrightString());
@@ -273,8 +307,8 @@ void intro_v3d::introInit() {
font.drawString(&surf, buffer, 0, 190, 320, _TBROWN, Graphics::kTextAlignCenter);
- if (scumm_stricmp(_boot.distrib, "David P. Gray")) {
- sprintf(buffer, "Distributed by %s.", _boot.distrib);
+ if ((*_vm->_boot.distrib != '\0') && (scumm_stricmp(_vm->_boot.distrib, "David P. Gray"))) {
+ sprintf(buffer, "Distributed by %s.", _vm->_boot.distrib);
font.drawString(&surf, buffer, 0, 0, 320, _TBROWN, Graphics::kTextAlignCenter);
}
@@ -296,25 +330,25 @@ bool intro_v3d::introPlay() {
if (_vm->getGameStatus().skipIntroFl)
return true;
- if (introTicks < _vm->getIntroSize()) {
- font.drawString(&surf, ".", _vm->_introX[introTicks], _vm->_introY[introTicks] - kDibOffY, 320, _TBRIGHTWHITE);
+ if (introTicks < getIntroSize()) {
+ font.drawString(&surf, ".", _introX[introTicks], _introY[introTicks] - kDibOffY, 320, _TBRIGHTWHITE);
_vm->_screen->displayBackground();
// Text boxes at various times
switch (introTicks) {
case 4:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro1));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro1));
break;
case 9:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro2));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro2));
break;
case 35:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro3));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro3));
break;
}
}
- return (++introTicks >= _vm->getIntroSize());
+ return (++introTicks >= getIntroSize());
}
intro_v1w::intro_v1w(HugoEngine *vm) : IntroHandler(vm) {
@@ -387,25 +421,25 @@ bool intro_v3w::introPlay() {
if (_vm->getGameStatus().skipIntroFl)
return true;
- if (introTicks < _vm->getIntroSize()) {
+ if (introTicks < getIntroSize()) {
// Scale viewport x_intro,y_intro to screen (offsetting y)
- _vm->_screen->writeStr(_vm->_introX[introTicks], _vm->_introY[introTicks] - kDibOffY, "x", _TBRIGHTWHITE);
+ _vm->_screen->writeStr(_introX[introTicks], _introY[introTicks] - kDibOffY, "x", _TBRIGHTWHITE);
_vm->_screen->displayBackground();
// Text boxes at various times
switch (introTicks) {
case 4:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro1));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro1));
break;
case 9:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro2));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro2));
break;
case 35:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro3));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro3));
break;
}
}
- return (++introTicks >= _vm->getIntroSize());
+ return (++introTicks >= getIntroSize());
}
} // End of namespace Hugo
diff --git a/engines/hugo/intro.h b/engines/hugo/intro.h
index 37c846fc10..772d98e244 100644
--- a/engines/hugo/intro.h
+++ b/engines/hugo/intro.h
@@ -54,9 +54,18 @@ public:
virtual void introInit() = 0;
virtual bool introPlay() = 0;
+ void freeIntroData();
+ void loadIntroData(Common::SeekableReadStream &in);
+
+ byte getIntroSize() const;
+
protected:
HugoEngine *_vm;
- int16 introTicks; // Count calls to introPlay()
+
+ byte *_introX;
+ byte *_introY;
+ byte _introXSize;
+ int16 introTicks; // Count calls to introPlay()
};
class intro_v1w : public IntroHandler {
diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp
index 4bf107575e..ab58e386ba 100644
--- a/engines/hugo/inventory.cpp
+++ b/engines/hugo/inventory.cpp
@@ -46,11 +46,49 @@ namespace Hugo {
static const int kMaxDisp = (kXPix / kInvDx); // Max icons displayable
-InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm) {
+InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm), _invent(0) {
_firstIconId = 0;
_inventoryState = kInventoryOff; // Inventory icon bar state
_inventoryHeight = 0; // Inventory icon bar pos
_inventoryObjId = -1; // Inventory object selected (none)
+ _maxInvent = 0;
+}
+
+void InventoryHandler::setInventoryObjId(int16 objId) {
+ _inventoryObjId = objId;
+}
+
+void InventoryHandler::setInventoryState(istate_t state) {
+ _inventoryState = state;
+}
+
+void InventoryHandler::freeInvent() {
+ free(_invent);
+}
+
+int16 InventoryHandler::getInventoryObjId() const {
+ return _inventoryObjId;
+}
+
+istate_t InventoryHandler::getInventoryState() const {
+ return _inventoryState;
+}
+
+/**
+ * Read _invent from Hugo.dat
+ */
+void InventoryHandler::loadInvent(Common::SeekableReadStream &in) {
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ int16 numElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant) {
+ _maxInvent = numElem;
+ _invent = (int16 *)malloc(sizeof(int16) * numElem);
+ for (int i = 0; i < numElem; i++)
+ _invent[i] = in.readSint16BE();
+ } else {
+ in.skip(numElem * sizeof(int16));
+ }
+ }
}
/**
@@ -78,7 +116,7 @@ void InventoryHandler::constructInventory(const int16 imageTotNumb, int displayN
int16 displayed = 0;
int16 carried = 0;
for (int16 i = 0; (i < imageTotNumb) && (displayed < displayNumb); i++) {
- if (_vm->_object->isCarried(_vm->_invent[i])) {
+ if (_vm->_object->isCarried(_invent[i])) {
// Check still room to display and past first scroll index
if (displayed < displayNumb && carried >= firstObjId) {
// Compute source coordinates in dib_u
@@ -107,8 +145,8 @@ int16 InventoryHandler::processInventory(const invact_t action, ...) {
int16 imageNumb; // Total number of inventory items
int displayNumb; // Total number displayed/carried
// Compute total number and number displayed, i.e. number carried
- for (imageNumb = 0, displayNumb = 0; imageNumb < _vm->_maxInvent && _vm->_invent[imageNumb] != -1; imageNumb++) {
- if (_vm->_object->isCarried(_vm->_invent[imageNumb]))
+ for (imageNumb = 0, displayNumb = 0; imageNumb < _maxInvent && _invent[imageNumb] != -1; imageNumb++) {
+ if (_vm->_object->isCarried(_invent[imageNumb]))
displayNumb++;
}
@@ -236,4 +274,18 @@ void InventoryHandler::runInventory() {
}
}
+
+/**
+ * Find index of dragged icon
+ */
+int16 InventoryHandler::findIconId(int16 objId) {
+ int16 iconId = 0;
+ for (; iconId < _maxInvent; iconId++) {
+ if (objId == _invent[iconId])
+ break;
+ }
+
+ return iconId;
+}
+
} // End of namespace Hugo
diff --git a/engines/hugo/inventory.h b/engines/hugo/inventory.h
index deb22cf9aa..ec102f3cce 100644
--- a/engines/hugo/inventory.h
+++ b/engines/hugo/inventory.h
@@ -43,13 +43,17 @@ class InventoryHandler {
public:
InventoryHandler(HugoEngine *vm);
- void setInventoryObjId(int16 objId) { _inventoryObjId = objId; }
- void setInventoryState(istate_t state) { _inventoryState = state; }
- int16 getInventoryObjId() const { return _inventoryObjId; }
- istate_t getInventoryState() const { return _inventoryState; }
+ void setInventoryObjId(int16 objId);
+ void setInventoryState(istate_t state);
+ void freeInvent();
+ int16 getInventoryObjId() const;
+ istate_t getInventoryState() const;
+
+ int16 findIconId(int16 objId);
+ void loadInvent(Common::SeekableReadStream &in);
int16 processInventory(const invact_t action, ...);
- void runInventory();
+ void runInventory();
private:
HugoEngine *_vm;
@@ -57,9 +61,11 @@ private:
static const int kStepDy = 8; // Pixels per step movement
int16 _firstIconId; // Index of first icon to display
+ int16 *_invent;
istate_t _inventoryState; // Inventory icon bar state
int16 _inventoryHeight; // Inventory icon bar height
int16 _inventoryObjId; // Inventory object selected, or -1
+ byte _maxInvent;
void constructInventory(const int16 imageTotNumb, int displayNumb, const bool scrollFl, int16 firstObjId);
};
diff --git a/engines/hugo/module.mk b/engines/hugo/module.mk
index 3a1ceded73..2ded997437 100644
--- a/engines/hugo/module.mk
+++ b/engines/hugo/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/hugo
MODULE_OBJS := \
console.o \
detection.o \
+ dialogs.o \
display.o \
file.o \
file_v1d.o \
@@ -13,7 +14,6 @@ MODULE_OBJS := \
hugo.o \
intro.o \
inventory.o \
- menu.o \
mouse.o \
object.o \
object_v1d.o \
diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp
index 9bbc60f04b..1b2dd588b8 100644
--- a/engines/hugo/mouse.cpp
+++ b/engines/hugo/mouse.cpp
@@ -47,7 +47,7 @@
namespace Hugo {
-MouseHandler::MouseHandler(HugoEngine *vm) : _vm(vm) {
+MouseHandler::MouseHandler(HugoEngine *vm) : _vm(vm), _hotspots(0) {
_leftButtonFl = false;
_rightButtonFl = false;
_jumpExitFl = false; // Can't jump to a screen exit
@@ -55,6 +55,58 @@ MouseHandler::MouseHandler(HugoEngine *vm) : _vm(vm) {
_mouseY = kYPix / 2;
}
+void MouseHandler::resetLeftButton() {
+ _leftButtonFl = false;
+}
+
+void MouseHandler::resetRightButton() {
+ _rightButtonFl = false;
+}
+
+void MouseHandler::setLeftButton() {
+ _leftButtonFl = true;
+}
+
+void MouseHandler::setRightButton() {
+ _rightButtonFl = true;
+}
+
+void MouseHandler::setJumpExitFl(bool fl) {
+ _jumpExitFl = fl;
+}
+
+void MouseHandler::setMouseX(int x) {
+ _mouseX = x;
+}
+
+void MouseHandler::setMouseY(int y) {
+ _mouseY = y;
+}
+
+void MouseHandler::freeHotspots() {
+ free(_hotspots);
+}
+
+bool MouseHandler::getJumpExitFl() const {
+ return _jumpExitFl;
+}
+
+int MouseHandler::getMouseX() const {
+ return _mouseX;
+}
+
+int MouseHandler::getMouseY() const {
+ return _mouseY;
+}
+
+int16 MouseHandler::getDirection(const int16 hotspotId) const {
+ return _hotspots[hotspotId].direction;
+}
+
+int16 MouseHandler::getHotspotActIndex(const int16 hotspotId) const {
+ return _hotspots[hotspotId].actIndex;
+}
+
/**
* Shadow-blit supplied string into dib_a at cx,cy and add to display list
*/
@@ -135,7 +187,7 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in
if (_vm->_hero->cycling == kCycleInvisible) // If invisible do
_vm->_object->useObject(objId); // immediate use
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
+ Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
}
break;
}
@@ -189,7 +241,7 @@ void MouseHandler::processLeftClick(const int16 objId, const int16 cx, const int
else if (_hotspots[i].direction == Common::KEYCODE_LEFT)
x += kHeroMaxWidth;
if (!_vm->_route->startRoute(kRouteExit, i, x, y))
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
+ Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
}
// Get rid of any attached icon
@@ -219,7 +271,7 @@ void MouseHandler::processLeftClick(const int16 objId, const int16 cx, const int
if (_vm->_hero->cycling == kCycleInvisible) // If invisible do
_vm->_object->lookObject(obj); // immediate decription
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
+ Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
}
break;
}
@@ -293,31 +345,31 @@ void MouseHandler::mouseHandler() {
resetRightButton();
}
+void MouseHandler::readHotspot(Common::ReadStream &in, hotspot_t &hotspot) {
+ hotspot.screenIndex = in.readSint16BE();
+ hotspot.x1 = in.readSint16BE();
+ hotspot.y1 = in.readSint16BE();
+ hotspot.x2 = in.readSint16BE();
+ hotspot.y2 = in.readSint16BE();
+ hotspot.actIndex = in.readUint16BE();
+ hotspot.viewx = in.readSint16BE();
+ hotspot.viewy = in.readSint16BE();
+ hotspot.direction = in.readSint16BE();
+}
+
/**
* Load hotspots data from hugo.dat
*/
void MouseHandler::loadHotspots(Common::ReadStream &in) {
- // Read _hotspots
+ hotspot_t *wrkHotspots = 0;
+ hotspot_t tmp;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
int numRows = in.readUint16BE();
- hotspot_t *wrkHotspots = (hotspot_t *)malloc(sizeof(hotspot_t) * numRows);
-
- for (int i = 0; i < numRows; i++) {
- wrkHotspots[i].screenIndex = in.readSint16BE();
- wrkHotspots[i].x1 = in.readSint16BE();
- wrkHotspots[i].y1 = in.readSint16BE();
- wrkHotspots[i].x2 = in.readSint16BE();
- wrkHotspots[i].y2 = in.readSint16BE();
- wrkHotspots[i].actIndex = in.readUint16BE();
- wrkHotspots[i].viewx = in.readSint16BE();
- wrkHotspots[i].viewy = in.readSint16BE();
- wrkHotspots[i].direction = in.readSint16BE();
- }
-
if (varnt == _vm->_gameVariant)
- _hotspots = wrkHotspots;
- else
- free(wrkHotspots);
+ _hotspots = wrkHotspots = (hotspot_t *)malloc(sizeof(hotspot_t) * numRows);
+
+ for (int i = 0; i < numRows; i++)
+ readHotspot(in, (varnt == _vm->_gameVariant) ? wrkHotspots[i] : tmp);
}
}
diff --git a/engines/hugo/mouse.h b/engines/hugo/mouse.h
index eae13b48fb..ae1974b726 100644
--- a/engines/hugo/mouse.h
+++ b/engines/hugo/mouse.h
@@ -39,21 +39,21 @@ public:
MouseHandler(HugoEngine *vm);
void mouseHandler();
- void resetLeftButton() { _leftButtonFl = false; }
- void resetRightButton() { _rightButtonFl = false; }
- void setLeftButton() { _leftButtonFl = true; }
- void setRightButton() { _rightButtonFl = true; }
- void setJumpExitFl(bool fl) { _jumpExitFl = fl; }
- void setMouseX(int x) { _mouseX = x; }
- void setMouseY(int y) { _mouseY = y; }
- void freeHotspots() { free(_hotspots); }
-
- bool getJumpExitFl() const { return _jumpExitFl; }
- int getMouseX() const { return _mouseX; }
- int getMouseY() const { return _mouseY; }
-
- int16 getDirection(const int16 hotspotId) const { return _hotspots[hotspotId].direction; }
- int16 getHotspotActIndex(const int16 hotspotId) const { return _hotspots[hotspotId].actIndex; }
+ void resetLeftButton();
+ void resetRightButton();
+ void setLeftButton();
+ void setRightButton();
+ void setJumpExitFl(bool fl);
+ void setMouseX(int x);
+ void setMouseY(int y);
+ void freeHotspots();
+
+ bool getJumpExitFl() const;
+ int getMouseX() const;
+ int getMouseY() const;
+
+ int16 getDirection(const int16 hotspotId) const;
+ int16 getHotspotActIndex(const int16 hotspotId) const;
void drawHotspots() const;
int16 findExit(const int16 cx, const int16 cy, byte screenId);
@@ -83,6 +83,7 @@ private:
void cursorText(const char *buffer, const int16 cx, const int16 cy, const uif_t fontId, const int16 color);
void processRightClick(const int16 objId, const int16 cx, const int16 cy);
void processLeftClick(const int16 objId, const int16 cx, const int16 cy);
+ void readHotspot(Common::ReadStream &in, hotspot_t &hotspot);
};
} // End of namespace Hugo
diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp
index b909df45bb..0a52a0f62d 100644
--- a/engines/hugo/object.cpp
+++ b/engines/hugo/object.cpp
@@ -48,9 +48,10 @@
namespace Hugo {
-ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0) {
+ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0), _uses(0) {
_numObj = 0;
_objCount = 0;
+ _usesSize = 0;
memset(_objBound, '\0', sizeof(overlay_t));
memset(_boundary, '\0', sizeof(overlay_t));
memset(_overlay, '\0', sizeof(overlay_t));
@@ -60,6 +61,41 @@ ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0) {
ObjectHandler::~ObjectHandler() {
}
+byte ObjectHandler::getBoundaryOverlay(uint16 index) const {
+ return _boundary[index];
+}
+
+byte ObjectHandler::getObjectBoundary(uint16 index) const {
+ return _objBound[index];
+}
+
+byte ObjectHandler::getBaseBoundary(uint16 index) const {
+ return _ovlBase[index];
+}
+
+byte ObjectHandler::getFirstOverlay(uint16 index) const {
+ return _overlay[index];
+}
+
+bool ObjectHandler::isCarried(int objIndex) const {
+ return _objects[objIndex].carriedFl;
+}
+
+void ObjectHandler::setCarry(int objIndex, bool val) {
+ _objects[objIndex].carriedFl = val;
+}
+
+void ObjectHandler::setVelocity(int objIndex, int8 vx, int8 vy) {
+ _objects[objIndex].vx = vx;
+ _objects[objIndex].vy = vy;
+}
+
+void ObjectHandler::setPath(int objIndex, path_t pathType, int16 vxPath, int16 vyPath) {
+ _objects[objIndex].pathType = pathType;
+ _objects[objIndex].vxPath = vxPath;
+ _objects[objIndex].vyPath = vyPath;
+}
+
/**
* Save sequence number and image number in given object
*/
@@ -108,20 +144,20 @@ void ObjectHandler::useObject(int16 objId) {
if ((obj->genericCmd & TAKE) || obj->objValue) // Get collectible item
sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_take, 0), _vm->_text->getNoun(obj->nounIndex, 0));
else if (obj->cmdIndex != 0) // Use non-collectible item if able
- sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_cmdList[obj->cmdIndex][0].verbIndex, 0), _vm->_text->getNoun(obj->nounIndex, 0));
- else if ((verb = _vm->useBG(_vm->_text->getNoun(obj->nounIndex, 0))) != 0)
+ sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_parser->getCmdDefaultVerbIdx(obj->cmdIndex), 0), _vm->_text->getNoun(obj->nounIndex, 0));
+ else if ((verb = _vm->_parser->useBG(_vm->_text->getNoun(obj->nounIndex, 0))) != 0)
sprintf(_vm->_line, "%s %s", verb, _vm->_text->getNoun(obj->nounIndex, 0));
else
return; // Can't use object directly
} else {
// Use status.objid on objid
// Default to first cmd verb
- sprintf(_vm->_line, "%s %s %s", _vm->_text->getVerb(_vm->_cmdList[_objects[inventObjId].cmdIndex][0].verbIndex, 0),
+ sprintf(_vm->_line, "%s %s %s", _vm->_text->getVerb(_vm->_parser->getCmdDefaultVerbIdx(_objects[inventObjId].cmdIndex), 0),
_vm->_text->getNoun(_objects[inventObjId].nounIndex, 0),
_vm->_text->getNoun(obj->nounIndex, 0));
// Check valid use of objects and override verb if necessary
- for (uses_t *use = _vm->_uses; use->objId != _numObj; use++) {
+ for (uses_t *use = _uses; use->objId != _numObj; use++) {
if (inventObjId == use->objId) {
// Look for secondary object, if found use matching verb
bool foundFl = false;
@@ -139,7 +175,7 @@ void ObjectHandler::useObject(int16 objId) {
// Deselect dragged icon if inventory not active
if (_vm->_inventory->getInventoryState() != kInventoryActive)
_vm->_screen->resetInventoryObjId();
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(use->dataIndex));
+ Utils::notifyBox(_vm->_text->getTextData(use->dataIndex));
return;
}
}
@@ -212,40 +248,52 @@ void ObjectHandler::lookObject(object_t *obj) {
}
/**
- * Free all object images
+ * Free all object images, uses and ObjArr (before exiting)
*/
void ObjectHandler::freeObjects() {
debugC(1, kDebugObject, "freeObjects");
- // Nothing to do if not allocated yet
- if (_vm->_hero == 0 || _vm->_hero->seqList[0].seqPtr == 0)
- return;
-
- // Free all sequence lists and image data
- for (int i = 0; i < _numObj; i++) {
- object_t *obj = &_objects[i];
- for (int j = 0; j < obj->seqNumb; j++) {
- seq_t *seq = obj->seqList[j].seqPtr;
- seq_t *next;
- if (seq == 0) // Failure during database load
- break;
- if (seq->imagePtr != 0) {
- free(seq->imagePtr);
- seq->imagePtr = 0;
- }
- seq = seq->nextSeqPtr;
- while (seq != obj->seqList[j].seqPtr) {
+ if (_vm->_hero != 0 && _vm->_hero->seqList[0].seqPtr != 0) {
+ // Free all sequence lists and image data
+ for (int16 i = 0; i < _numObj; i++) {
+ object_t *obj = &_objects[i];
+ for (int16 j = 0; j < obj->seqNumb; j++) {
+ seq_t *seq = obj->seqList[j].seqPtr;
+ seq_t *next;
+ if (seq == 0) // Failure during database load
+ break;
if (seq->imagePtr != 0) {
free(seq->imagePtr);
seq->imagePtr = 0;
}
- next = seq->nextSeqPtr;
+ seq = seq->nextSeqPtr;
+ while (seq != obj->seqList[j].seqPtr) {
+ if (seq->imagePtr != 0) {
+ free(seq->imagePtr);
+ seq->imagePtr = 0;
+ }
+ next = seq->nextSeqPtr;
+ free(seq);
+ seq = next;
+ }
free(seq);
- seq = next;
}
- free(seq);
}
}
+
+ if (_uses) {
+ for (int16 i = 0; i < _usesSize; i++)
+ free(_uses[i].targets);
+ free(_uses);
+ }
+
+ for(int16 i = 0; i < _objCount; i++) {
+ free(_objects[i].stateDataIndex);
+ _objects[i].stateDataIndex = 0;
+ }
+
+ free(_objects);
+ _objects = 0;
}
/**
@@ -305,7 +353,7 @@ void ObjectHandler::showTakeables() {
if ((obj->cycling != kCycleInvisible) &&
(obj->screenIndex == *_vm->_screen_p) &&
(((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) {
- Utils::Box(kBoxAny, "You can also see:\n%s.", _vm->_text->getNoun(obj->nounIndex, LOOK_NAME));
+ Utils::notifyBox(Common::String::format("You can also see:\n%s.", _vm->_text->getNoun(obj->nounIndex, LOOK_NAME)));
}
}
}
@@ -355,120 +403,123 @@ bool ObjectHandler::findObjectSpace(object_t *obj, int16 *destx, int16 *desty) {
return foundFl;
}
+void ObjectHandler::readUse(Common::ReadStream &in, uses_t &curUse) {
+ curUse.objId = in.readSint16BE();
+ curUse.dataIndex = in.readUint16BE();
+ uint16 numSubElem = in.readUint16BE();
+ curUse.targets = (target_t *)malloc(sizeof(target_t) * numSubElem);
+ for (int j = 0; j < numSubElem; j++) {
+ curUse.targets[j].nounIndex = in.readUint16BE();
+ curUse.targets[j].verbIndex = in.readUint16BE();
+ }
+}
/**
- * Free ObjectArr (before exiting)
+ * Load _uses from Hugo.dat
*/
-void ObjectHandler::freeObjectArr() {
- for(int16 i = 0; i < _objCount; i++) {
- free(_objects[i].stateDataIndex);
- _objects[i].stateDataIndex = 0;
+void ObjectHandler::loadObjectUses(Common::ReadStream &in) {
+ uses_t tmpUse;
+ tmpUse.targets = 0;
+
+ //Read _uses
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ uint16 numElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant) {
+ _usesSize = numElem;
+ _uses = (uses_t *)malloc(sizeof(uses_t) * numElem);
+ }
+
+ for (int i = 0; i < numElem; i++) {
+ if (varnt == _vm->_gameVariant)
+ readUse(in, _uses[i]);
+ else {
+ readUse(in, tmpUse);
+ free(tmpUse.targets);
+ tmpUse.targets = 0;
+ }
+ }
}
- free(_objects);
- _objects = 0;
}
+void ObjectHandler::readObject(Common::ReadStream &in, object_t &curObject) {
+ curObject.nounIndex = in.readUint16BE();
+ curObject.dataIndex = in.readUint16BE();
+ uint16 numSubElem = in.readUint16BE();
+
+ if (numSubElem == 0)
+ curObject.stateDataIndex = 0;
+ else
+ curObject.stateDataIndex = (uint16 *)malloc(sizeof(uint16) * numSubElem);
+ for (int j = 0; j < numSubElem; j++)
+ curObject.stateDataIndex[j] = in.readUint16BE();
+
+ curObject.pathType = (path_t) in.readSint16BE();
+ curObject.vxPath = in.readSint16BE();
+ curObject.vyPath = in.readSint16BE();
+ curObject.actIndex = in.readUint16BE();
+ curObject.seqNumb = in.readByte();
+ curObject.currImagePtr = 0;
+
+ if (curObject.seqNumb == 0) {
+ curObject.seqList[0].imageNbr = 0;
+ curObject.seqList[0].seqPtr = 0;
+ }
+
+ for (int j = 0; j < curObject.seqNumb; j++) {
+ curObject.seqList[j].imageNbr = in.readUint16BE();
+ curObject.seqList[j].seqPtr = 0;
+ }
+
+ curObject.cycling = (cycle_t)in.readByte();
+ curObject.cycleNumb = in.readByte();
+ curObject.frameInterval = in.readByte();
+ curObject.frameTimer = in.readByte();
+ curObject.radius = in.readByte();
+ curObject.screenIndex = in.readByte();
+ curObject.x = in.readSint16BE();
+ curObject.y = in.readSint16BE();
+ curObject.oldx = in.readSint16BE();
+ curObject.oldy = in.readSint16BE();
+ curObject.vx = in.readByte();
+ curObject.vy = in.readByte();
+ curObject.objValue = in.readByte();
+ curObject.genericCmd = in.readSint16BE();
+ curObject.cmdIndex = in.readUint16BE();
+ curObject.carriedFl = (in.readByte() != 0);
+ curObject.state = in.readByte();
+ curObject.verbOnlyFl = (in.readByte() != 0);
+ curObject.priority = in.readByte();
+ curObject.viewx = in.readSint16BE();
+ curObject.viewy = in.readSint16BE();
+ curObject.direction = in.readSint16BE();
+ curObject.curSeqNum = in.readByte();
+ curObject.curImageNum = in.readByte();
+ curObject.oldvx = in.readByte();
+ curObject.oldvy = in.readByte();
+}
/**
* Load ObjectArr from Hugo.dat
*/
void ObjectHandler::loadObjectArr(Common::ReadStream &in) {
debugC(6, kDebugObject, "loadObject(&in)");
+ object_t tmpObject;
+ tmpObject.stateDataIndex = 0;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numElem = in.readUint16BE();
+
if (varnt == _vm->_gameVariant) {
_objCount = numElem;
_objects = (object_t *)malloc(sizeof(object_t) * numElem);
- for (int i = 0; i < numElem; i++) {
- _objects[i].nounIndex = in.readUint16BE();
- _objects[i].dataIndex = in.readUint16BE();
- uint16 numSubElem = in.readUint16BE();
- if (numSubElem == 0)
- _objects[i].stateDataIndex = 0;
- else
- _objects[i].stateDataIndex = (uint16 *)malloc(sizeof(uint16) * numSubElem);
- for (int j = 0; j < numSubElem; j++)
- _objects[i].stateDataIndex[j] = in.readUint16BE();
- _objects[i].pathType = (path_t) in.readSint16BE();
- _objects[i].vxPath = in.readSint16BE();
- _objects[i].vyPath = in.readSint16BE();
- _objects[i].actIndex = in.readUint16BE();
- _objects[i].seqNumb = in.readByte();
- _objects[i].currImagePtr = 0;
- if (_objects[i].seqNumb == 0) {
- _objects[i].seqList[0].imageNbr = 0;
- _objects[i].seqList[0].seqPtr = 0;
- }
- for (int j = 0; j < _objects[i].seqNumb; j++) {
- _objects[i].seqList[j].imageNbr = in.readUint16BE();
- _objects[i].seqList[j].seqPtr = 0;
- }
- _objects[i].cycling = (cycle_t)in.readByte();
- _objects[i].cycleNumb = in.readByte();
- _objects[i].frameInterval = in.readByte();
- _objects[i].frameTimer = in.readByte();
- _objects[i].radius = in.readByte();
- _objects[i].screenIndex = in.readByte();
- _objects[i].x = in.readSint16BE();
- _objects[i].y = in.readSint16BE();
- _objects[i].oldx = in.readSint16BE();
- _objects[i].oldy = in.readSint16BE();
- _objects[i].vx = in.readByte();
- _objects[i].vy = in.readByte();
- _objects[i].objValue = in.readByte();
- _objects[i].genericCmd = in.readSint16BE();
- _objects[i].cmdIndex = in.readUint16BE();
- _objects[i].carriedFl = (in.readByte() != 0);
- _objects[i].state = in.readByte();
- _objects[i].verbOnlyFl = (in.readByte() != 0);
- _objects[i].priority = in.readByte();
- _objects[i].viewx = in.readSint16BE();
- _objects[i].viewy = in.readSint16BE();
- _objects[i].direction = in.readSint16BE();
- _objects[i].curSeqNum = in.readByte();
- _objects[i].curImageNum = in.readByte();
- _objects[i].oldvx = in.readByte();
- _objects[i].oldvy = in.readByte();
- }
- } else {
- for (int i = 0; i < numElem; i++) {
- in.readUint16BE();
- in.readUint16BE();
- uint16 numSubElem = in.readUint16BE();
- for (int j = 0; j < numSubElem; j++)
- in.readUint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- numSubElem = in.readByte();
- for (int j = 0; j < numSubElem; j++)
- in.readUint16BE();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readSint16BE();
- in.readUint16BE();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readByte();
- in.readByte();
- in.readByte();
- in.readByte();
+ }
+
+ for (int i = 0; i < numElem; i++) {
+ if (varnt == _vm->_gameVariant)
+ readObject(in, _objects[i]);
+ else {
+ // Skip over uneeded objects.
+ readObject(in, tmpObject);
+ free(tmpObject.stateDataIndex);
+ tmpObject.stateDataIndex = 0;
}
}
}
diff --git a/engines/hugo/object.h b/engines/hugo/object.h
index aa2ed9ba9f..41ea776840 100644
--- a/engines/hugo/object.h
+++ b/engines/hugo/object.h
@@ -37,6 +37,17 @@
namespace Hugo {
+struct target_t { // Secondary target for action
+ uint16 nounIndex; // Secondary object
+ uint16 verbIndex; // Action on secondary object
+};
+
+struct uses_t { // Define uses of certain objects
+ int16 objId; // Primary object
+ uint16 dataIndex; // String if no secondary object matches
+ target_t *targets; // List of secondary targets
+};
+
class ObjectHandler {
public:
ObjectHandler(HugoEngine *vm);
@@ -50,10 +61,10 @@ public:
object_t *_objects;
uint16 _numObj;
- byte getBoundaryOverlay(uint16 index) const { return _boundary[index]; }
- byte getObjectBoundary(uint16 index) const { return _objBound[index]; }
- byte getBaseBoundary(uint16 index) const { return _ovlBase[index]; }
- byte getFirstOverlay(uint16 index) const { return _overlay[index]; }
+ byte getBoundaryOverlay(uint16 index) const;
+ byte getObjectBoundary(uint16 index) const;
+ byte getBaseBoundary(uint16 index) const;
+ byte getFirstOverlay(uint16 index) const;
int deltaX(const int x1, const int x2, const int vx, int y) const;
int deltaY(const int x1, const int x2, const int vy, const int y) const;
@@ -74,10 +85,12 @@ public:
int16 findObject(uint16 x, uint16 y);
void freeObjects();
void loadObjectArr(Common::ReadStream &in);
- void freeObjectArr();
+ void loadObjectUses(Common::ReadStream &in);
void loadNumObj(Common::ReadStream &in);
void lookObject(object_t *obj);
void readObjectImages();
+ void readObject(Common::ReadStream &in, object_t &curObject);
+ void readUse(Common::ReadStream &in, uses_t &curUse);
void restoreAllSeq();
void restoreObjects(Common::SeekableReadStream *in);
void saveObjects(Common::WriteStream *out);
@@ -88,24 +101,11 @@ public:
static int y2comp(const void *a, const void *b);
- bool isCarried(int objIndex) {
- return _objects[objIndex].carriedFl;
- }
-
- void setCarry(int objIndex, bool val) {
- _objects[objIndex].carriedFl = val;
- }
-
- void setVelocity(int objIndex, int8 vx, int8 vy) {
- _objects[objIndex].vx = vx;
- _objects[objIndex].vy = vy;
- }
+ bool isCarried(int objIndex) const;
+ void setCarry(int objIndex, bool val);
+ void setVelocity(int objIndex, int8 vx, int8 vy);
+ void setPath(int objIndex, path_t pathType, int16 vxPath, int16 vyPath);
- void setPath(int objIndex, path_t pathType, int16 vxPath, int16 vyPath) {
- _objects[objIndex].pathType = pathType;
- _objects[objIndex].vxPath = vxPath;
- _objects[objIndex].vyPath = vyPath;
- }
protected:
HugoEngine *_vm;
@@ -114,11 +114,13 @@ protected:
static const int kMaxObjNumb = 128; // Used in Update_images()
uint16 _objCount;
+ uses_t *_uses;
+ uint16 _usesSize;
void restoreSeq(object_t *obj);
inline bool checkBoundary(int16 x, int16 y);
- template <typename T>
+ template <typename T>
inline int sign(T a) { if ( a < 0) return -1; else return 1; }
};
diff --git a/engines/hugo/object_v1d.cpp b/engines/hugo/object_v1d.cpp
index d46ef890bc..a8edb45746 100644
--- a/engines/hugo/object_v1d.cpp
+++ b/engines/hugo/object_v1d.cpp
@@ -334,7 +334,7 @@ void ObjectHandler_v1d::moveObjects() {
}
// If maze mode is enabled, do special maze processing
- if (_maze.enabledFl) {
+ if (_vm->_maze.enabledFl) {
seq_t *currImage = _vm->_hero->currImagePtr;// Get ptr to current image
// hero coordinates
int x1 = _vm->_hero->x + currImage->x1; // Left edge of object
diff --git a/engines/hugo/object_v1w.cpp b/engines/hugo/object_v1w.cpp
index 321bb293f0..f3ba793a3b 100644
--- a/engines/hugo/object_v1w.cpp
+++ b/engines/hugo/object_v1w.cpp
@@ -344,7 +344,7 @@ void ObjectHandler_v1w::moveObjects() {
}
// If maze mode is enabled, do special maze processing
- if (_maze.enabledFl) {
+ if (_vm->_maze.enabledFl) {
seq_t *currImage = _vm->_hero->currImagePtr; // Get ptr to current image
// hero coordinates
int x1 = _vm->_hero->x + currImage->x1; // Left edge of object
diff --git a/engines/hugo/object_v2d.cpp b/engines/hugo/object_v2d.cpp
index 0bb207411e..b3c49262ad 100644
--- a/engines/hugo/object_v2d.cpp
+++ b/engines/hugo/object_v2d.cpp
@@ -347,7 +347,7 @@ void ObjectHandler_v2d::moveObjects() {
}
// If maze mode is enabled, do special maze processing
- if (_maze.enabledFl) {
+ if (_vm->_maze.enabledFl) {
seq_t *currImage = _vm->_hero->currImagePtr; // Get ptr to current image
// hero coordinates
int x1 = _vm->_hero->x + currImage->x1; // Left edge of object
diff --git a/engines/hugo/object_v3d.cpp b/engines/hugo/object_v3d.cpp
index 8c9efba1d0..2c6fc5d99d 100644
--- a/engines/hugo/object_v3d.cpp
+++ b/engines/hugo/object_v3d.cpp
@@ -229,7 +229,7 @@ void ObjectHandler_v3d::moveObjects() {
}
// If maze mode is enabled, do special maze processing
- if (_maze.enabledFl) {
+ if (_vm->_maze.enabledFl) {
seq_t *currImage = _vm->_hero->currImagePtr;// Get ptr to current image
// hero coordinates
int x1 = _vm->_hero->x + currImage->x1; // Left edge of object
diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp
index 001ddac8e4..feee4cbadd 100644
--- a/engines/hugo/parser.cpp
+++ b/engines/hugo/parser.cpp
@@ -51,17 +51,156 @@
namespace Hugo {
-Parser::Parser(HugoEngine *vm) :
- _vm(vm), _putIndex(0), _getIndex(0), _checkDoubleF1Fl(false) {
+Parser::Parser(HugoEngine *vm) : _vm(vm), _putIndex(0), _getIndex(0), _arrayReqs(0), _catchallList(0), _backgroundObjects(0), _cmdList(0) {
_cmdLineIndex = 0;
_cmdLineTick = 0;
_cmdLineCursor = '_';
_cmdLine[0] = '\0';
+ _cmdListSize = 0;
+ _checkDoubleF1Fl = false;
+ _backgroundObjectsSize = 0;
}
Parser::~Parser() {
}
+uint16 Parser::getCmdDefaultVerbIdx(const uint16 index) const {
+ return _cmdList[index][0].verbIndex;
+}
+
+/**
+ * Read a cmd structure from Hugo.dat
+ */
+void Parser::readCmd(Common::ReadStream &in, cmd &curCmd) {
+ curCmd.verbIndex = in.readUint16BE();
+ curCmd.reqIndex = in.readUint16BE();
+ curCmd.textDataNoCarryIndex = in.readUint16BE();
+ curCmd.reqState = in.readByte();
+ curCmd.newState = in.readByte();
+ curCmd.textDataWrongIndex = in.readUint16BE();
+ curCmd.textDataDoneIndex = in.readUint16BE();
+ curCmd.actIndex = in.readUint16BE();
+}
+
+/**
+ * Load _cmdList from Hugo.dat
+ */
+void Parser::loadCmdList(Common::ReadStream &in) {
+ cmd tmpCmd;
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ uint16 numElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant) {
+ _cmdListSize = numElem;
+ _cmdList = (cmd **)malloc(sizeof(cmd *) * _cmdListSize);
+ }
+
+ for (int16 i = 0; i < numElem; i++) {
+ uint16 numSubElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant)
+ _cmdList[i] = (cmd *)malloc(sizeof(cmd) * numSubElem);
+ for (int16 j = 0; j < numSubElem; j++)
+ readCmd(in, (varnt == _vm->_gameVariant) ? _cmdList[i][j] : tmpCmd);
+ }
+ }
+}
+
+
+void Parser::readBG(Common::ReadStream &in, background_t &curBG) {
+ curBG.verbIndex = in.readUint16BE();
+ curBG.nounIndex = in.readUint16BE();
+ curBG.commentIndex = in.readSint16BE();
+ curBG.matchFl = (in.readByte() != 0);
+ curBG.roomState = in.readByte();
+ curBG.bonusIndex = in.readByte();
+}
+
+/**
+ * Read _backgrounObjects from Hugo.dat
+ */
+void Parser::loadBackgroundObjects(Common::ReadStream &in) {
+ background_t tmpBG;
+
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ uint16 numElem = in.readUint16BE();
+
+ if (varnt == _vm->_gameVariant) {
+ _backgroundObjectsSize = numElem;
+ _backgroundObjects = (background_t **)malloc(sizeof(background_t *) * numElem);
+ }
+
+ for (int i = 0; i < numElem; i++) {
+ uint16 numSubElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant)
+ _backgroundObjects[i] = (background_t *)malloc(sizeof(background_t) * numSubElem);
+
+ for (int j = 0; j < numSubElem; j++)
+ readBG(in, (varnt == _vm->_gameVariant) ? _backgroundObjects[i][j] : tmpBG);
+ }
+ }
+}
+
+/**
+ * Read _catchallList from Hugo.dat
+ */
+void Parser::loadCatchallList(Common::ReadStream &in) {
+ background_t *wrkCatchallList = 0;
+ background_t tmpBG;
+
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ uint16 numElem = in.readUint16BE();
+
+ if (varnt == _vm->_gameVariant)
+ _catchallList = wrkCatchallList = (background_t *)malloc(sizeof(background_t) * numElem);
+
+ for (int i = 0; i < numElem; i++)
+ readBG(in, (varnt == _vm->_gameVariant) ? wrkCatchallList[i] : tmpBG);
+ }
+}
+
+void Parser::loadArrayReqs(Common::SeekableReadStream &in) {
+ _arrayReqs = _vm->loadLongArray(in);
+}
+
+/**
+ * Search background command list for this screen for supplied object.
+ * Return first associated verb (not "look") or 0 if none found.
+ */
+const char *Parser::useBG(const char *name) {
+ debugC(1, kDebugEngine, "useBG(%s)", name);
+
+ objectList_t p = _backgroundObjects[*_vm->_screen_p];
+ for (int i = 0; p[i].verbIndex != 0; i++) {
+ if ((name == _vm->_text->getNoun(p[i].nounIndex, 0) &&
+ p[i].verbIndex != _vm->_look) &&
+ ((p[i].roomState == kStateDontCare) || (p[i].roomState == _vm->_screenStates[*_vm->_screen_p])))
+ return _vm->_text->getVerb(p[i].verbIndex, 0);
+ }
+
+ return 0;
+}
+
+void Parser::freeParser() {
+ if (_arrayReqs) {
+ for (int i = 0; _arrayReqs[i] != 0; i++)
+ free(_arrayReqs[i]);
+ free(_arrayReqs);
+ }
+
+ free(_catchallList);
+
+ if (_backgroundObjects) {
+ for (int i = 0; i < _backgroundObjectsSize; i++)
+ free(_backgroundObjects[i]);
+ free(_backgroundObjects);
+ }
+
+ if (_cmdList) {
+ for (int i = 0; i < _cmdListSize; i++)
+ free(_cmdList[i]);
+ free(_cmdList);
+ }
+}
+
void Parser::switchTurbo() {
_vm->_config.turboFl = !_vm->_config.turboFl;
}
@@ -147,16 +286,15 @@ void Parser::keyHandler(Common::Event event) {
break;
case Common::KEYCODE_l:
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
break;
case Common::KEYCODE_n:
- warning("STUB: CTRL-N (WIN) - New Game");
+ if (Utils::yesNoBox("Are you sure you want to start a new game?"))
+ _vm->_file->restoreGame(0);
break;
case Common::KEYCODE_s:
if (gameStatus.viewState == kViewPlay) {
if (gameStatus.gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
_vm->_file->saveGame(-1, Common::String());
}
@@ -214,15 +352,13 @@ void Parser::keyHandler(Common::Event event) {
case Common::KEYCODE_F4: // Save game
if (gameStatus.viewState == kViewPlay) {
if (gameStatus.gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
_vm->_file->saveGame(-1, Common::String());
}
break;
case Common::KEYCODE_F5: // Restore game
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
break;
case Common::KEYCODE_F6: // Inventory
showInventory();
@@ -349,7 +485,7 @@ void Parser::showDosInventory() const {
if (index & 1)
buffer += "\n";
buffer += Common::String(_vm->_text->getTextParser(kTBOutro));
- Utils::Box(kBoxAny, "%s", buffer.c_str());
+ Utils::notifyBox(buffer.c_str());
}
} // End of namespace Hugo
diff --git a/engines/hugo/parser.h b/engines/hugo/parser.h
index 2e807e543f..dd9244ba93 100644
--- a/engines/hugo/parser.h
+++ b/engines/hugo/parser.h
@@ -42,17 +42,56 @@ enum seqTextParser {
kCmtAny5, kTBExit_1d, kTBEh_1d, kTBEh_2d, kTBNoUse_2d
};
+/**
+ * The following determines how a verb is acted on, for an object
+ */
+struct cmd {
+ uint16 verbIndex; // the verb
+ uint16 reqIndex; // ptr to list of required objects
+ uint16 textDataNoCarryIndex; // ptr to string if any of above not carried
+ byte reqState; // required state for verb to be done
+ byte newState; // new states if verb done
+ uint16 textDataWrongIndex; // ptr to string if wrong state
+ uint16 textDataDoneIndex; // ptr to string if verb done
+ uint16 actIndex; // Ptr to action list if verb done
+};
+
+/**
+ * Following is structure of verbs and nouns for 'background' objects
+ * These are objects that appear in the various screens, but nothing
+ * interesting ever happens with them. Rather than just be dumb and say
+ * "don't understand" we produce an interesting msg to keep user sane.
+ */
+struct background_t {
+ uint16 verbIndex;
+ uint16 nounIndex;
+ int commentIndex; // Index of comment produced on match
+ bool matchFl; // TRUE if noun must match when present
+ byte roomState; // "State" of room. Comments might differ.
+ byte bonusIndex; // Index of bonus score (0 = no bonus)
+};
+
+typedef background_t *objectList_t;
+
class Parser {
public:
Parser(HugoEngine *vm);
virtual ~Parser();
bool isWordPresent(char **wordArr) const;
-
+
+ uint16 getCmdDefaultVerbIdx(const uint16 index) const;
+
void charHandler();
void command(const char *format, ...);
+ void freeParser();
void keyHandler(Common::Event event);
+ void loadArrayReqs(Common::SeekableReadStream &in);
+ void loadBackgroundObjects(Common::ReadStream &in);
+ void loadCatchallList(Common::ReadStream &in);
+ void loadCmdList(Common::ReadStream &in);
void switchTurbo();
+ const char *useBG(const char *name);
virtual void lineHandler() = 0;
virtual void showInventory() const = 0;
@@ -64,9 +103,18 @@ protected:
uint32 _cmdLineTick; // For flashing cursor
char _cmdLineCursor;
command_t _cmdLine; // Build command line
+ uint16 _backgroundObjectsSize;
+ uint16 _cmdListSize;
+
+ uint16 **_arrayReqs;
+ background_t **_backgroundObjects;
+ background_t *_catchallList;
+ cmd **_cmdList;
const char *findNoun() const;
const char *findVerb() const;
+ void readBG(Common::ReadStream &in, background_t &curBG);
+ void readCmd(Common::ReadStream &in, cmd &curCmd);
void showDosInventory() const;
bool _checkDoubleF1Fl; // Flag used to display user help or instructions
diff --git a/engines/hugo/parser_v1d.cpp b/engines/hugo/parser_v1d.cpp
index 1565490ce3..de18427d93 100644
--- a/engines/hugo/parser_v1d.cpp
+++ b/engines/hugo/parser_v1d.cpp
@@ -151,25 +151,25 @@ bool Parser_v1d::isGenericVerb_v1(const char *word, object_t *obj) {
// Following is equivalent to switch, but couldn't do one
if (word == _vm->_text->getVerb(_vm->_look, 0)) {
if ((LOOK & obj->genericCmd) == LOOK)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->dataIndex));
+ Utils::notifyBox(_vm->_text->getTextData(obj->dataIndex));
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBUnusual_1d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBUnusual_1d));
} else if (word == _vm->_text->getVerb(_vm->_take, 0)) {
if (obj->carriedFl)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBHave));
else if ((TAKE & obj->genericCmd) == TAKE)
takeObject(obj);
else if (!obj->verbOnlyFl) // Make sure not taking object in context!
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse));
else
return false;
} else if (word == _vm->_text->getVerb(_vm->_drop, 0)) {
if (!obj->carriedFl)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBDontHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBDontHave));
else if ((DROP & obj->genericCmd) == DROP)
dropObject(obj);
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNeed));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNeed));
} else { // It was not a generic cmd
return false;
}
@@ -192,21 +192,21 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) {
return false;
int i;
- for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd
- if (!strcmp(word, _vm->_text->getVerb(_vm->_cmdList[cmdIndex][i].verbIndex, 0))) // Is this verb catered for?
+ for (i = 0; _cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd
+ if (!strcmp(word, _vm->_text->getVerb(_cmdList[cmdIndex][i].verbIndex, 0))) // Is this verb catered for?
break;
}
- if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No
+ if (_cmdList[cmdIndex][i].verbIndex == 0) // No
return false;
// Verb match found, check all required objects are being carried
- cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd
+ cmd *cmnd = &_cmdList[cmdIndex][i]; // ptr to struct cmd
if (cmnd->reqIndex) { // At least 1 thing in list
- uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
+ uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
for (i = 0; reqs[i]; i++) { // for each obj
if (!_vm->_object->isCarrying(reqs[i])) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataNoCarryIndex));
return true;
}
}
@@ -214,14 +214,14 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) {
// Required objects are present, now check state is correct
if ((obj->state != cmnd->reqState) && (cmnd->reqState != kStateDontCare)){
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataWrongIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataWrongIndex));
return true;
}
// Everything checked. Change the state and carry out any actions
if (cmnd->reqState != kStateDontCare) // Don't change new state if required state didn't care
obj->state = cmnd->newState;
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataDoneIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataDoneIndex));
_vm->_scheduler->insertActionList(cmnd->actIndex);
// Special case if verb is Take or Drop. Assume additional generic actions
if ((word == _vm->_text->getVerb(_vm->_take, 0)) || (word == _vm->_text->getVerb(_vm->_drop, 0)))
@@ -241,7 +241,7 @@ bool Parser_v1d::isBackgroundWord_v1(const char *noun, const char *verb, objectL
for (int i = 0; obj[i].verbIndex; i++) {
if ((verb == _vm->_text->getVerb(obj[i].verbIndex, 0)) && (noun == _vm->_text->getNoun(obj[i].nounIndex, 0))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
return true;
}
}
@@ -260,7 +260,7 @@ void Parser_v1d::takeObject(object_t *obj) {
_vm->adjustScore(obj->objValue);
- Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME));
+ Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME)));
}
/**
@@ -276,7 +276,7 @@ void Parser_v1d::dropObject(object_t *obj) {
obj->x = _vm->_hero->x - 1;
obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1;
_vm->adjustScore(-obj->objValue);
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBOk));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBOk));
}
/**
@@ -286,7 +286,7 @@ void Parser_v1d::dropObject(object_t *obj) {
bool Parser_v1d::isCatchallVerb_v1(bool testNounFl, const char *noun, const char *verb, objectList_t obj) const {
debugC(1, kDebugParser, "isCatchallVerb(%d, %s, %s, object_list_t obj)", (testNounFl) ? 1 : 0, noun, verb);
- if (_maze.enabledFl)
+ if (_vm->_maze.enabledFl)
return false;
if (testNounFl && !noun)
@@ -294,7 +294,7 @@ bool Parser_v1d::isCatchallVerb_v1(bool testNounFl, const char *noun, const char
for (int i = 0; obj[i].verbIndex; i++) {
if ((verb == _vm->_text->getVerb(obj[i].verbIndex, 0)) && ((noun == _vm->_text->getNoun(obj[i].nounIndex, 0)) || (obj[i].nounIndex == 0))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
return true;
}
}
@@ -364,7 +364,7 @@ void Parser_v1d::lineHandler() {
}
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
@@ -372,7 +372,7 @@ void Parser_v1d::lineHandler() {
// SAVE/RESTORE
if (!strcmp("save", _vm->_line)) {
if (gameStatus.gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
_vm->_file->saveGame(-1, Common::String());
return;
@@ -380,8 +380,6 @@ void Parser_v1d::lineHandler() {
if (!strcmp("restore", _vm->_line)) {
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -391,8 +389,9 @@ void Parser_v1d::lineHandler() {
if (strspn(_vm->_line, " ") == strlen(_vm->_line)) // Nothing but spaces!
return;
- if (gameStatus.gameOverFl) { // No commands allowed!
- Utils::gameOverMsg();
+ if (gameStatus.gameOverFl) {
+ // No commands allowed!
+ _vm->gameOverMsg();
return;
}
@@ -413,24 +412,24 @@ void Parser_v1d::lineHandler() {
return;
}
}
- if ((*farComment == '\0') && isBackgroundWord_v1(noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]))
+ if ((*farComment == '\0') && isBackgroundWord_v1(noun, verb, _backgroundObjects[*_vm->_screen_p]))
return;
} while (noun);
}
noun = findNextNoun(noun);
if (*farComment != '\0') // An object matched but not near enough
- Utils::Box(kBoxAny, "%s", farComment);
- else if (!isCatchallVerb_v1(true, noun, verb, _vm->_catchallList) &&
- !isCatchallVerb_v1(false, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) &&
- !isCatchallVerb_v1(false, noun, verb, _vm->_catchallList))
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_1d));
+ Utils::notifyBox(farComment);
+ else if (!isCatchallVerb_v1(true, noun, verb, _catchallList) &&
+ !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p]) &&
+ !isCatchallVerb_v1(false, noun, verb, _catchallList))
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh_1d));
}
void Parser_v1d::showInventory() const {
status_t &gameStatus = _vm->getGameStatus();
if (gameStatus.viewState == kViewPlay) {
if (gameStatus.gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
showDosInventory();
}
diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp
index 2b6741d440..305fb995e1 100644
--- a/engines/hugo/parser_v1w.cpp
+++ b/engines/hugo/parser_v1w.cpp
@@ -119,7 +119,7 @@ void Parser_v1w::lineHandler() {
// Special meta commands
// EXIT/QUIT
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
@@ -132,8 +132,6 @@ void Parser_v1w::lineHandler() {
if (!strcmp("restore", _vm->_line) && (gameStatus.viewState == kViewPlay || gameStatus.viewState == kViewIdle)) {
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -145,7 +143,7 @@ void Parser_v1w::lineHandler() {
if (gameStatus.gameOverFl) {
// No commands allowed!
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
return;
}
@@ -172,36 +170,36 @@ void Parser_v1w::lineHandler() {
}
// No objects match command line, try background and catchall commands
- if (isBackgroundWord_v3(_vm->_backgroundObjects[*_vm->_screen_p]))
+ if (isBackgroundWord_v3(_backgroundObjects[*_vm->_screen_p]))
return;
- if (isCatchallVerb_v3(_vm->_backgroundObjects[*_vm->_screen_p]))
+ if (isCatchallVerb_v3(_backgroundObjects[*_vm->_screen_p]))
return;
- if (isBackgroundWord_v3(_vm->_catchallList))
+ if (isBackgroundWord_v3(_catchallList))
return;
- if (isCatchallVerb_v3(_vm->_catchallList))
+ if (isCatchallVerb_v3(_catchallList))
return;
// If a not-near comment was generated, print it
if (*farComment != '\0') {
- Utils::Box(kBoxAny, "%s", farComment);
+ Utils::notifyBox(farComment);
return;
}
// Nothing matches. Report recognition success to user.
const char *verb = findVerb();
const char *noun = findNoun();
- if (verb == _vm->_text->getVerb(_vm->_look, 0) && _maze.enabledFl) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBMaze));
+ if (verb == _vm->_text->getVerb(_vm->_look, 0) && _vm->_maze.enabledFl) {
+ Utils::notifyBox(_vm->_text->getTextParser(kTBMaze));
_vm->_object->showTakeables();
} else if (verb && noun) { // A combination I didn't think of
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoPoint));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoPoint));
} else if (noun) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoun));
} else if (verb) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBVerb));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBVerb));
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh));
}
}
@@ -209,7 +207,7 @@ void Parser_v1w::showInventory() const {
status_t &gameStatus = _vm->getGameStatus();
istate_t inventState = _vm->_inventory->getInventoryState();
if (gameStatus.gameOverFl) {
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
} else if ((inventState == kInventoryOff) && (gameStatus.viewState == kViewPlay)) {
_vm->_inventory->setInventoryState(kInventoryDown);
gameStatus.viewState = kViewInvent;
diff --git a/engines/hugo/parser_v2d.cpp b/engines/hugo/parser_v2d.cpp
index cd7928e069..d6f2adfedc 100644
--- a/engines/hugo/parser_v2d.cpp
+++ b/engines/hugo/parser_v2d.cpp
@@ -114,7 +114,7 @@ void Parser_v2d::lineHandler() {
}
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
@@ -123,7 +123,7 @@ void Parser_v2d::lineHandler() {
if (!strcmp("save", _vm->_line)) {
_vm->_config.soundFl = false;
if (gameStatus.gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
_vm->_file->saveGame(-1, Common::String());
return;
@@ -132,8 +132,6 @@ void Parser_v2d::lineHandler() {
if (!strcmp("restore", _vm->_line)) {
_vm->_config.soundFl = false;
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -143,8 +141,9 @@ void Parser_v2d::lineHandler() {
if (strspn(_vm->_line, " ") == strlen(_vm->_line)) // Nothing but spaces!
return;
- if (gameStatus.gameOverFl) { // No commands allowed!
- Utils::gameOverMsg();
+ if (gameStatus.gameOverFl) {
+ // No commands allowed!
+ _vm->gameOverMsg();
return;
}
@@ -165,27 +164,27 @@ void Parser_v2d::lineHandler() {
return;
}
}
- if ((*farComment != '\0') && isBackgroundWord_v1(noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]))
+ if ((*farComment != '\0') && isBackgroundWord_v1(noun, verb, _backgroundObjects[*_vm->_screen_p]))
return;
} while (noun);
}
noun = findNextNoun(noun);
- if ( !isCatchallVerb_v1(true, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p])
- && !isCatchallVerb_v1(true, noun, verb, _vm->_catchallList)
- && !isCatchallVerb_v1(false, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p])
- && !isCatchallVerb_v1(false, noun, verb, _vm->_catchallList)) {
+ if ( !isCatchallVerb_v1(true, noun, verb, _backgroundObjects[*_vm->_screen_p])
+ && !isCatchallVerb_v1(true, noun, verb, _catchallList)
+ && !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p])
+ && !isCatchallVerb_v1(false, noun, verb, _catchallList)) {
if (*farComment != '\0') { // An object matched but not near enough
- Utils::Box(kBoxAny, "%s", farComment);
- } else if (_maze.enabledFl && (verb == _vm->_text->getVerb(_vm->_look, 0))) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBMaze));
+ Utils::notifyBox(farComment);
+ } else if (_vm->_maze.enabledFl && (verb == _vm->_text->getVerb(_vm->_look, 0))) {
+ Utils::notifyBox(_vm->_text->getTextParser(kTBMaze));
_vm->_object->showTakeables();
} else if (verb && noun) { // A combination I didn't think of
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse_2d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse_2d));
} else if (verb || noun) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoun));
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_2d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh_2d));
}
}
}
diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp
index 532b1f92d1..f08d472240 100644
--- a/engines/hugo/parser_v3d.cpp
+++ b/engines/hugo/parser_v3d.cpp
@@ -116,7 +116,7 @@ void Parser_v3d::lineHandler() {
// Special meta commands
// EXIT/QUIT
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
@@ -125,7 +125,7 @@ void Parser_v3d::lineHandler() {
if (!strcmp("save", _vm->_line)) {
_vm->_config.soundFl = false;
if (gameStatus.gameOverFl)
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
else
_vm->_file->saveGame(-1, Common::String());
return;
@@ -134,8 +134,6 @@ void Parser_v3d::lineHandler() {
if (!strcmp("restore", _vm->_line)) {
_vm->_config.soundFl = false;
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -147,7 +145,7 @@ void Parser_v3d::lineHandler() {
if (gameStatus.gameOverFl) {
// No commands allowed!
- Utils::gameOverMsg();
+ _vm->gameOverMsg();
return;
}
@@ -174,19 +172,19 @@ void Parser_v3d::lineHandler() {
}
// No objects match command line, try background and catchall commands
- if (isBackgroundWord_v3(_vm->_backgroundObjects[*_vm->_screen_p]))
+ if (isBackgroundWord_v3(_backgroundObjects[*_vm->_screen_p]))
return;
- if (isCatchallVerb_v3(_vm->_backgroundObjects[*_vm->_screen_p]))
+ if (isCatchallVerb_v3(_backgroundObjects[*_vm->_screen_p]))
return;
- if (isBackgroundWord_v3(_vm->_catchallList))
+ if (isBackgroundWord_v3(_catchallList))
return;
- if (isCatchallVerb_v3(_vm->_catchallList))
+ if (isCatchallVerb_v3(_catchallList))
return;
// If a not-near comment was generated, print it
if (*farComment != '\0') {
- Utils::Box(kBoxAny, "%s", farComment);
+ Utils::notifyBox(farComment);
return;
}
@@ -195,13 +193,13 @@ void Parser_v3d::lineHandler() {
const char *noun = findNoun();
if (verb && noun) { // A combination I didn't think of
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoPoint));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoPoint));
} else if (noun) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoun));
} else if (verb) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBVerb));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBVerb));
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh));
}
}
@@ -219,26 +217,26 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) {
return false;
int i;
- for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd
- if (isWordPresent(_vm->_text->getVerbArray(_vm->_cmdList[cmdIndex][i].verbIndex))) // Was this verb used?
+ for (i = 0; _cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd
+ if (isWordPresent(_vm->_text->getVerbArray(_cmdList[cmdIndex][i].verbIndex))) // Was this verb used?
break;
}
- if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used.
+ if (_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used.
return false;
// Verb match found. Check if object is Near
- char *verb = *_vm->_text->getVerbArray(_vm->_cmdList[cmdIndex][i].verbIndex);
+ char *verb = *_vm->_text->getVerbArray(_cmdList[cmdIndex][i].verbIndex);
if (!isNear_v3(obj, verb, comment))
return false;
// Check all required objects are being carried
- cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd
+ cmd *cmnd = &_cmdList[cmdIndex][i]; // ptr to struct cmd
if (cmnd->reqIndex) { // At least 1 thing in list
- uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
+ uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
for (i = 0; reqs[i]; i++) { // for each obj
if (!_vm->_object->isCarrying(reqs[i])) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataNoCarryIndex));
return true;
}
}
@@ -246,14 +244,14 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) {
// Required objects are present, now check state is correct
if ((obj->state != cmnd->reqState) && (cmnd->reqState != kStateDontCare)) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataWrongIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataWrongIndex));
return true;
}
// Everything checked. Change the state and carry out any actions
if (cmnd->reqState != kStateDontCare) // Don't change new state if required state didn't care
obj->state = cmnd->newState;
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataDoneIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataDoneIndex));
_vm->_scheduler->insertActionList(cmnd->actIndex);
// See if any additional generic actions
@@ -275,35 +273,35 @@ bool Parser_v3d::isGenericVerb_v3(object_t *obj, char *comment) {
if (isWordPresent(_vm->_text->getVerbArray(_vm->_look)) && isNear_v3(obj, _vm->_text->getVerb(_vm->_look, 0), comment)) {
// Test state-dependent look before general look
if ((obj->genericCmd & LOOK_S) == LOOK_S) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->stateDataIndex[obj->state]));
+ Utils::notifyBox(_vm->_text->getTextData(obj->stateDataIndex[obj->state]));
} else {
if ((LOOK & obj->genericCmd) == LOOK) {
if (obj->dataIndex != 0)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->dataIndex));
+ Utils::notifyBox(_vm->_text->getTextData(obj->dataIndex));
else
return false;
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBUnusual));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBUnusual));
}
}
} else if (isWordPresent(_vm->_text->getVerbArray(_vm->_take)) && isNear_v3(obj, _vm->_text->getVerb(_vm->_take, 0), comment)) {
if (obj->carriedFl)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBHave));
else if ((TAKE & obj->genericCmd) == TAKE)
takeObject(obj);
else if (obj->cmdIndex) // No comment if possible commands
return false;
else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context!
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse));
else
return false;
} else if (isWordPresent(_vm->_text->getVerbArray(_vm->_drop))) {
if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP))
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBDontHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBDontHave));
else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP))
dropObject(obj);
else if (obj->cmdIndex == 0)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNeed));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNeed));
else
return false;
} else { // It was not a generic cmd
@@ -385,7 +383,7 @@ void Parser_v3d::takeObject(object_t *obj) {
if (obj->seqNumb > 0) // If object has an image, force walk to dropped
obj->viewx = -1; // (possibly moved) object next time taken!
- Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME));
+ Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME)));
}
/**
@@ -404,7 +402,7 @@ void Parser_v3d::dropObject(object_t *obj) {
obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1;
obj->y = (obj->y + obj->currImagePtr->y2 < kYPix) ? obj->y : kYPix - obj->currImagePtr->y2 - 10;
_vm->adjustScore(-obj->objValue);
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBOk));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBOk));
}
/**
@@ -416,7 +414,7 @@ void Parser_v3d::dropObject(object_t *obj) {
bool Parser_v3d::isCatchallVerb_v3(objectList_t obj) const {
debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)");
- if (_maze.enabledFl)
+ if (_vm->_maze.enabledFl)
return false;
for (int i = 0; obj[i].verbIndex != 0; i++) {
@@ -424,7 +422,7 @@ bool Parser_v3d::isCatchallVerb_v3(objectList_t obj) const {
(!obj[i].matchFl || !findNoun()) &&
((obj[i].roomState == kStateDontCare) ||
(obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
_vm->_scheduler->processBonus(obj[i].bonusIndex);
// If this is LOOK (without a noun), show any takeable objects
@@ -444,7 +442,7 @@ bool Parser_v3d::isCatchallVerb_v3(objectList_t obj) const {
bool Parser_v3d::isBackgroundWord_v3(objectList_t obj) const {
debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)");
- if (_maze.enabledFl)
+ if (_vm->_maze.enabledFl)
return false;
for (int i = 0; obj[i].verbIndex != 0; i++) {
@@ -452,7 +450,7 @@ bool Parser_v3d::isBackgroundWord_v3(objectList_t obj) const {
isWordPresent(_vm->_text->getNounArray(obj[i].nounIndex)) &&
((obj[i].roomState == kStateDontCare) ||
(obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
_vm->_scheduler->processBonus(obj[i].bonusIndex);
return true;
}
diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp
index c122439c70..76ec583857 100644
--- a/engines/hugo/route.cpp
+++ b/engines/hugo/route.cpp
@@ -49,6 +49,14 @@ Route::Route(HugoEngine *vm) : _vm(vm) {
_routeObjId = -1; // Hero not walking to anything
}
+void Route::resetRoute() {
+ _routeIndex = -1;
+}
+
+int16 Route::getRouteIndex() const {
+ return _routeIndex;
+}
+
/**
* Face hero in new direction, based on cursor key input by user.
*/
diff --git a/engines/hugo/route.h b/engines/hugo/route.h
index 727c7d77eb..83a36f27ef 100644
--- a/engines/hugo/route.h
+++ b/engines/hugo/route.h
@@ -54,8 +54,8 @@ class Route {
public:
Route(HugoEngine *vm);
- void resetRoute() {_routeIndex = -1; }
- int16 getRouteIndex() const {return _routeIndex; }
+ void resetRoute();
+ int16 getRouteIndex() const;
void processRoute();
bool startRoute(const go_t routeType, const int16 objId, int16 cx, int16 cy);
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index b36ce70847..45a2b77826 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -48,13 +48,19 @@
namespace Hugo {
-Scheduler::Scheduler(HugoEngine *vm) : _vm(vm), _actListArr(0), _curTick(0), _oldTime(0), _refreshTimeout(0) {
+Scheduler::Scheduler(HugoEngine *vm) : _vm(vm), _actListArr(0), _curTick(0), _oldTime(0), _refreshTimeout(0), _points(0), _screenActs(0) {
memset(_events, 0, sizeof(_events));
+ _numBonuses = 0;
+ _screenActsSize = 0;
}
Scheduler::~Scheduler() {
}
+void Scheduler::initCypher() {
+ _cypher = getCypher();
+}
+
/**
* Initialise the timer event queue
*/
@@ -127,7 +133,7 @@ uint32 Scheduler::getDosTicks(const bool updateFl) {
if (_oldTime == 0)
_oldTime = (uint32) floor((double) (g_system->getMillis() * _vm->getTPS() / 1000));
// Calculate current wall time in ticks
- t_now = g_system->getMillis() * _vm->getTPS() / 1000 ;
+ t_now = g_system->getMillis() * _vm->getTPS() / 1000;
if ((t_now - _oldTime) > 0) {
_oldTime = t_now;
@@ -142,9 +148,9 @@ uint32 Scheduler::getDosTicks(const bool updateFl) {
void Scheduler::processBonus(const int bonusIndex) {
debugC(1, kDebugSchedule, "processBonus(%d)", bonusIndex);
- if (!_vm->_points[bonusIndex].scoredFl) {
- _vm->adjustScore(_vm->_points[bonusIndex].score);
- _vm->_points[bonusIndex].scoredFl = true;
+ if (!_points[bonusIndex].scoredFl) {
+ _vm->adjustScore(_points[bonusIndex].score);
+ _points[bonusIndex].scoredFl = true;
}
}
@@ -186,7 +192,7 @@ void Scheduler::newScreen(const int screenIndex) {
_vm->readScreenFiles(screenIndex);
// 4. Schedule action list for this screen
- _vm->screenActions(screenIndex);
+ _vm->_scheduler->screenActions(screenIndex);
// 5. Initialise prompt line and status line
_vm->_screen->initNewScreenDisplay();
@@ -245,580 +251,380 @@ void Scheduler::loadAlNewscrIndex(Common::ReadStream &in) {
}
/**
+ * Load Points from Hugo.dat
+ */
+void Scheduler::loadPoints(Common::SeekableReadStream &in) {
+ debugC(6, kDebugSchedule, "loadPoints(&in)");
+
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ uint16 numElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant) {
+ _numBonuses = numElem;
+ _points = (point_t *)malloc(sizeof(point_t) * _numBonuses);
+ for (int i = 0; i < _numBonuses; i++) {
+ _points[i].score = in.readByte();
+ _points[i].scoredFl = false;
+ }
+ } else {
+ in.skip(numElem);
+ }
+ }
+}
+
+void Scheduler::readAct(Common::ReadStream &in, act &curAct) {
+ uint16 numSubAct;
+
+ curAct.a0.actType = (action_t) in.readByte();
+ switch (curAct.a0.actType) {
+ case ANULL: // -1
+ break;
+ case ASCHEDULE: // 0
+ curAct.a0.timer = in.readSint16BE();
+ curAct.a0.actIndex = in.readUint16BE();
+ break;
+ case START_OBJ: // 1
+ curAct.a1.timer = in.readSint16BE();
+ curAct.a1.objIndex = in.readSint16BE();
+ curAct.a1.cycleNumb = in.readSint16BE();
+ curAct.a1.cycle = (cycle_t) in.readByte();
+ break;
+ case INIT_OBJXY: // 2
+ curAct.a2.timer = in.readSint16BE();
+ curAct.a2.objIndex = in.readSint16BE();
+ curAct.a2.x = in.readSint16BE();
+ curAct.a2.y = in.readSint16BE();
+ break;
+ case PROMPT: // 3
+ curAct.a3.timer = in.readSint16BE();
+ curAct.a3.promptIndex = in.readSint16BE();
+ numSubAct = in.readUint16BE();
+ curAct.a3.responsePtr = (int *) malloc(sizeof(int) * numSubAct);
+ for (int k = 0; k < numSubAct; k++)
+ curAct.a3.responsePtr[k] = in.readSint16BE();
+ curAct.a3.actPassIndex = in.readUint16BE();
+ curAct.a3.actFailIndex = in.readUint16BE();
+ curAct.a3.encodedFl = (in.readByte() == 1) ? true : false;
+ break;
+ case BKGD_COLOR: // 4
+ curAct.a4.timer = in.readSint16BE();
+ curAct.a4.newBackgroundColor = in.readUint32BE();
+ break;
+ case INIT_OBJVXY: // 5
+ curAct.a5.timer = in.readSint16BE();
+ curAct.a5.objIndex = in.readSint16BE();
+ curAct.a5.vx = in.readSint16BE();
+ curAct.a5.vy = in.readSint16BE();
+ break;
+ case INIT_CARRY: // 6
+ curAct.a6.timer = in.readSint16BE();
+ curAct.a6.objIndex = in.readSint16BE();
+ curAct.a6.carriedFl = (in.readByte() == 1) ? true : false;
+ break;
+ case INIT_HF_COORD: // 7
+ curAct.a7.timer = in.readSint16BE();
+ curAct.a7.objIndex = in.readSint16BE();
+ break;
+ case NEW_SCREEN: // 8
+ curAct.a8.timer = in.readSint16BE();
+ curAct.a8.screenIndex = in.readSint16BE();
+ break;
+ case INIT_OBJSTATE: // 9
+ curAct.a9.timer = in.readSint16BE();
+ curAct.a9.objIndex = in.readSint16BE();
+ curAct.a9.newState = in.readByte();
+ break;
+ case INIT_PATH: // 10
+ curAct.a10.timer = in.readSint16BE();
+ curAct.a10.objIndex = in.readSint16BE();
+ curAct.a10.newPathType = in.readSint16BE();
+ curAct.a10.vxPath = in.readByte();
+ curAct.a10.vyPath = in.readByte();
+ break;
+ case COND_R: // 11
+ curAct.a11.timer = in.readSint16BE();
+ curAct.a11.objIndex = in.readSint16BE();
+ curAct.a11.stateReq = in.readByte();
+ curAct.a11.actPassIndex = in.readUint16BE();
+ curAct.a11.actFailIndex = in.readUint16BE();
+ break;
+ case TEXT: // 12
+ curAct.a12.timer = in.readSint16BE();
+ curAct.a12.stringIndex = in.readSint16BE();
+ break;
+ case SWAP_IMAGES: // 13
+ curAct.a13.timer = in.readSint16BE();
+ curAct.a13.objIndex1 = in.readSint16BE();
+ curAct.a13.objIndex2 = in.readSint16BE();
+ break;
+ case COND_SCR: // 14
+ curAct.a14.timer = in.readSint16BE();
+ curAct.a14.objIndex = in.readSint16BE();
+ curAct.a14.screenReq = in.readSint16BE();
+ curAct.a14.actPassIndex = in.readUint16BE();
+ curAct.a14.actFailIndex = in.readUint16BE();
+ break;
+ case AUTOPILOT: // 15
+ curAct.a15.timer = in.readSint16BE();
+ curAct.a15.objIndex1 = in.readSint16BE();
+ curAct.a15.objIndex2 = in.readSint16BE();
+ curAct.a15.dx = in.readByte();
+ curAct.a15.dy = in.readByte();
+ break;
+ case INIT_OBJ_SEQ: // 16
+ curAct.a16.timer = in.readSint16BE();
+ curAct.a16.objIndex = in.readSint16BE();
+ curAct.a16.seqIndex = in.readSint16BE();
+ break;
+ case SET_STATE_BITS: // 17
+ curAct.a17.timer = in.readSint16BE();
+ curAct.a17.objIndex = in.readSint16BE();
+ curAct.a17.stateMask = in.readSint16BE();
+ break;
+ case CLEAR_STATE_BITS: // 18
+ curAct.a18.timer = in.readSint16BE();
+ curAct.a18.objIndex = in.readSint16BE();
+ curAct.a18.stateMask = in.readSint16BE();
+ break;
+ case TEST_STATE_BITS: // 19
+ curAct.a19.timer = in.readSint16BE();
+ curAct.a19.objIndex = in.readSint16BE();
+ curAct.a19.stateMask = in.readSint16BE();
+ curAct.a19.actPassIndex = in.readUint16BE();
+ curAct.a19.actFailIndex = in.readUint16BE();
+ break;
+ case DEL_EVENTS: // 20
+ curAct.a20.timer = in.readSint16BE();
+ curAct.a20.actTypeDel = (action_t) in.readByte();
+ break;
+ case GAMEOVER: // 21
+ curAct.a21.timer = in.readSint16BE();
+ break;
+ case INIT_HH_COORD: // 22
+ curAct.a22.timer = in.readSint16BE();
+ curAct.a22.objIndex = in.readSint16BE();
+ break;
+ case EXIT: // 23
+ curAct.a23.timer = in.readSint16BE();
+ break;
+ case BONUS: // 24
+ curAct.a24.timer = in.readSint16BE();
+ curAct.a24.pointIndex = in.readSint16BE();
+ break;
+ case COND_BOX: // 25
+ curAct.a25.timer = in.readSint16BE();
+ curAct.a25.objIndex = in.readSint16BE();
+ curAct.a25.x1 = in.readSint16BE();
+ curAct.a25.y1 = in.readSint16BE();
+ curAct.a25.x2 = in.readSint16BE();
+ curAct.a25.y2 = in.readSint16BE();
+ curAct.a25.actPassIndex = in.readUint16BE();
+ curAct.a25.actFailIndex = in.readUint16BE();
+ break;
+ case SOUND: // 26
+ curAct.a26.timer = in.readSint16BE();
+ curAct.a26.soundIndex = in.readSint16BE();
+ break;
+ case ADD_SCORE: // 27
+ curAct.a27.timer = in.readSint16BE();
+ curAct.a27.objIndex = in.readSint16BE();
+ break;
+ case SUB_SCORE: // 28
+ curAct.a28.timer = in.readSint16BE();
+ curAct.a28.objIndex = in.readSint16BE();
+ break;
+ case COND_CARRY: // 29
+ curAct.a29.timer = in.readSint16BE();
+ curAct.a29.objIndex = in.readSint16BE();
+ curAct.a29.actPassIndex = in.readUint16BE();
+ curAct.a29.actFailIndex = in.readUint16BE();
+ break;
+ case INIT_MAZE: // 30
+ curAct.a30.timer = in.readSint16BE();
+ curAct.a30.mazeSize = in.readByte();
+ curAct.a30.x1 = in.readSint16BE();
+ curAct.a30.y1 = in.readSint16BE();
+ curAct.a30.x2 = in.readSint16BE();
+ curAct.a30.y2 = in.readSint16BE();
+ curAct.a30.x3 = in.readSint16BE();
+ curAct.a30.x4 = in.readSint16BE();
+ curAct.a30.firstScreenIndex = in.readByte();
+ break;
+ case EXIT_MAZE: // 31
+ curAct.a31.timer = in.readSint16BE();
+ break;
+ case INIT_PRIORITY: // 32
+ curAct.a32.timer = in.readSint16BE();
+ curAct.a32.objIndex = in.readSint16BE();
+ curAct.a32.priority = in.readByte();
+ break;
+ case INIT_SCREEN: // 33
+ curAct.a33.timer = in.readSint16BE();
+ curAct.a33.objIndex = in.readSint16BE();
+ curAct.a33.screenIndex = in.readSint16BE();
+ break;
+ case AGSCHEDULE: // 34
+ curAct.a34.timer = in.readSint16BE();
+ curAct.a34.actIndex = in.readUint16BE();
+ break;
+ case REMAPPAL: // 35
+ curAct.a35.timer = in.readSint16BE();
+ curAct.a35.oldColorIndex = in.readSint16BE();
+ curAct.a35.newColorIndex = in.readSint16BE();
+ break;
+ case COND_NOUN: // 36
+ curAct.a36.timer = in.readSint16BE();
+ curAct.a36.nounIndex = in.readUint16BE();
+ curAct.a36.actPassIndex = in.readUint16BE();
+ curAct.a36.actFailIndex = in.readUint16BE();
+ break;
+ case SCREEN_STATE: // 37
+ curAct.a37.timer = in.readSint16BE();
+ curAct.a37.screenIndex = in.readSint16BE();
+ curAct.a37.newState = in.readByte();
+ break;
+ case INIT_LIPS: // 38
+ curAct.a38.timer = in.readSint16BE();
+ curAct.a38.lipsObjIndex = in.readSint16BE();
+ curAct.a38.objIndex = in.readSint16BE();
+ curAct.a38.dxLips = in.readByte();
+ curAct.a38.dyLips = in.readByte();
+ break;
+ case INIT_STORY_MODE: // 39
+ curAct.a39.timer = in.readSint16BE();
+ curAct.a39.storyModeFl = (in.readByte() == 1);
+ break;
+ case WARN: // 40
+ curAct.a40.timer = in.readSint16BE();
+ curAct.a40.stringIndex = in.readSint16BE();
+ break;
+ case COND_BONUS: // 41
+ curAct.a41.timer = in.readSint16BE();
+ curAct.a41.BonusIndex = in.readSint16BE();
+ curAct.a41.actPassIndex = in.readUint16BE();
+ curAct.a41.actFailIndex = in.readUint16BE();
+ break;
+ case TEXT_TAKE: // 42
+ curAct.a42.timer = in.readSint16BE();
+ curAct.a42.objIndex = in.readSint16BE();
+ break;
+ case YESNO: // 43
+ curAct.a43.timer = in.readSint16BE();
+ curAct.a43.promptIndex = in.readSint16BE();
+ curAct.a43.actYesIndex = in.readUint16BE();
+ curAct.a43.actNoIndex = in.readUint16BE();
+ break;
+ case STOP_ROUTE: // 44
+ curAct.a44.timer = in.readSint16BE();
+ break;
+ case COND_ROUTE: // 45
+ curAct.a45.timer = in.readSint16BE();
+ curAct.a45.routeIndex = in.readSint16BE();
+ curAct.a45.actPassIndex = in.readUint16BE();
+ curAct.a45.actFailIndex = in.readUint16BE();
+ break;
+ case INIT_JUMPEXIT: // 46
+ curAct.a46.timer = in.readSint16BE();
+ curAct.a46.jumpExitFl = (in.readByte() == 1);
+ break;
+ case INIT_VIEW: // 47
+ curAct.a47.timer = in.readSint16BE();
+ curAct.a47.objIndex = in.readSint16BE();
+ curAct.a47.viewx = in.readSint16BE();
+ curAct.a47.viewy = in.readSint16BE();
+ curAct.a47.direction = in.readSint16BE();
+ break;
+ case INIT_OBJ_FRAME: // 48
+ curAct.a48.timer = in.readSint16BE();
+ curAct.a48.objIndex = in.readSint16BE();
+ curAct.a48.seqIndex = in.readSint16BE();
+ curAct.a48.frameIndex = in.readSint16BE();
+ break;
+ case OLD_SONG: //49
+ curAct.a49.timer = in.readSint16BE();
+ curAct.a49.songIndex = in.readUint16BE();
+ break;
+ default:
+ error("Engine - Unknown action type encountered: %d", curAct.a0.actType);
+ }
+}
+
+/**
* Load actListArr from Hugo.dat
*/
void Scheduler::loadActListArr(Common::ReadStream &in) {
debugC(6, kDebugSchedule, "loadActListArr(&in)");
- int numElem, numSubElem, numSubAct;
+ act tmpAct;
+
+ int numElem, numSubElem;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
numElem = in.readUint16BE();
if (varnt == _vm->_gameVariant) {
_actListArrSize = numElem;
_actListArr = (act **)malloc(sizeof(act *) * _actListArrSize);
- for (int i = 0; i < _actListArrSize; i++) {
- numSubElem = in.readUint16BE();
+ }
+
+ for (int i = 0; i < numElem; i++) {
+ numSubElem = in.readUint16BE();
+ if (varnt == _vm->_gameVariant)
_actListArr[i] = (act *) malloc(sizeof(act) * (numSubElem + 1));
- for (int j = 0; j < numSubElem; j++) {
- _actListArr[i][j].a0.actType = (action_t) in.readByte();
- switch (_actListArr[i][j].a0.actType) {
- case ANULL: // -1
- break;
- case ASCHEDULE: // 0
- _actListArr[i][j].a0.timer = in.readSint16BE();
- _actListArr[i][j].a0.actIndex = in.readUint16BE();
- break;
- case START_OBJ: // 1
- _actListArr[i][j].a1.timer = in.readSint16BE();
- _actListArr[i][j].a1.objIndex = in.readSint16BE();
- _actListArr[i][j].a1.cycleNumb = in.readSint16BE();
- _actListArr[i][j].a1.cycle = (cycle_t) in.readByte();
- break;
- case INIT_OBJXY: // 2
- _actListArr[i][j].a2.timer = in.readSint16BE();
- _actListArr[i][j].a2.objIndex = in.readSint16BE();
- _actListArr[i][j].a2.x = in.readSint16BE();
- _actListArr[i][j].a2.y = in.readSint16BE();
- break;
- case PROMPT: // 3
- _actListArr[i][j].a3.timer = in.readSint16BE();
- _actListArr[i][j].a3.promptIndex = in.readSint16BE();
- numSubAct = in.readUint16BE();
- _actListArr[i][j].a3.responsePtr = (int *) malloc(sizeof(int) * numSubAct);
- for (int k = 0; k < numSubAct; k++)
- _actListArr[i][j].a3.responsePtr[k] = in.readSint16BE();
- _actListArr[i][j].a3.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a3.actFailIndex = in.readUint16BE();
- _actListArr[i][j].a3.encodedFl = (in.readByte() == 1) ? true : false;
- break;
- case BKGD_COLOR: // 4
- _actListArr[i][j].a4.timer = in.readSint16BE();
- _actListArr[i][j].a4.newBackgroundColor = in.readUint32BE();
- break;
- case INIT_OBJVXY: // 5
- _actListArr[i][j].a5.timer = in.readSint16BE();
- _actListArr[i][j].a5.objIndex = in.readSint16BE();
- _actListArr[i][j].a5.vx = in.readSint16BE();
- _actListArr[i][j].a5.vy = in.readSint16BE();
- break;
- case INIT_CARRY: // 6
- _actListArr[i][j].a6.timer = in.readSint16BE();
- _actListArr[i][j].a6.objIndex = in.readSint16BE();
- _actListArr[i][j].a6.carriedFl = (in.readByte() == 1) ? true : false;
- break;
- case INIT_HF_COORD: // 7
- _actListArr[i][j].a7.timer = in.readSint16BE();
- _actListArr[i][j].a7.objIndex = in.readSint16BE();
- break;
- case NEW_SCREEN: // 8
- _actListArr[i][j].a8.timer = in.readSint16BE();
- _actListArr[i][j].a8.screenIndex = in.readSint16BE();
- break;
- case INIT_OBJSTATE: // 9
- _actListArr[i][j].a9.timer = in.readSint16BE();
- _actListArr[i][j].a9.objIndex = in.readSint16BE();
- _actListArr[i][j].a9.newState = in.readByte();
- break;
- case INIT_PATH: // 10
- _actListArr[i][j].a10.timer = in.readSint16BE();
- _actListArr[i][j].a10.objIndex = in.readSint16BE();
- _actListArr[i][j].a10.newPathType = in.readSint16BE();
- _actListArr[i][j].a10.vxPath = in.readByte();
- _actListArr[i][j].a10.vyPath = in.readByte();
- break;
- case COND_R: // 11
- _actListArr[i][j].a11.timer = in.readSint16BE();
- _actListArr[i][j].a11.objIndex = in.readSint16BE();
- _actListArr[i][j].a11.stateReq = in.readByte();
- _actListArr[i][j].a11.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a11.actFailIndex = in.readUint16BE();
- break;
- case TEXT: // 12
- _actListArr[i][j].a12.timer = in.readSint16BE();
- _actListArr[i][j].a12.stringIndex = in.readSint16BE();
- break;
- case SWAP_IMAGES: // 13
- _actListArr[i][j].a13.timer = in.readSint16BE();
- _actListArr[i][j].a13.objIndex1 = in.readSint16BE();
- _actListArr[i][j].a13.objIndex2 = in.readSint16BE();
- break;
- case COND_SCR: // 14
- _actListArr[i][j].a14.timer = in.readSint16BE();
- _actListArr[i][j].a14.objIndex = in.readSint16BE();
- _actListArr[i][j].a14.screenReq = in.readSint16BE();
- _actListArr[i][j].a14.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a14.actFailIndex = in.readUint16BE();
- break;
- case AUTOPILOT: // 15
- _actListArr[i][j].a15.timer = in.readSint16BE();
- _actListArr[i][j].a15.objIndex1 = in.readSint16BE();
- _actListArr[i][j].a15.objIndex2 = in.readSint16BE();
- _actListArr[i][j].a15.dx = in.readByte();
- _actListArr[i][j].a15.dy = in.readByte();
- break;
- case INIT_OBJ_SEQ: // 16
- _actListArr[i][j].a16.timer = in.readSint16BE();
- _actListArr[i][j].a16.objIndex = in.readSint16BE();
- _actListArr[i][j].a16.seqIndex = in.readSint16BE();
- break;
- case SET_STATE_BITS: // 17
- _actListArr[i][j].a17.timer = in.readSint16BE();
- _actListArr[i][j].a17.objIndex = in.readSint16BE();
- _actListArr[i][j].a17.stateMask = in.readSint16BE();
- break;
- case CLEAR_STATE_BITS: // 18
- _actListArr[i][j].a18.timer = in.readSint16BE();
- _actListArr[i][j].a18.objIndex = in.readSint16BE();
- _actListArr[i][j].a18.stateMask = in.readSint16BE();
- break;
- case TEST_STATE_BITS: // 19
- _actListArr[i][j].a19.timer = in.readSint16BE();
- _actListArr[i][j].a19.objIndex = in.readSint16BE();
- _actListArr[i][j].a19.stateMask = in.readSint16BE();
- _actListArr[i][j].a19.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a19.actFailIndex = in.readUint16BE();
- break;
- case DEL_EVENTS: // 20
- _actListArr[i][j].a20.timer = in.readSint16BE();
- _actListArr[i][j].a20.actTypeDel = (action_t) in.readByte();
- break;
- case GAMEOVER: // 21
- _actListArr[i][j].a21.timer = in.readSint16BE();
- break;
- case INIT_HH_COORD: // 22
- _actListArr[i][j].a22.timer = in.readSint16BE();
- _actListArr[i][j].a22.objIndex = in.readSint16BE();
- break;
- case EXIT: // 23
- _actListArr[i][j].a23.timer = in.readSint16BE();
- break;
- case BONUS: // 24
- _actListArr[i][j].a24.timer = in.readSint16BE();
- _actListArr[i][j].a24.pointIndex = in.readSint16BE();
- break;
- case COND_BOX: // 25
- _actListArr[i][j].a25.timer = in.readSint16BE();
- _actListArr[i][j].a25.objIndex = in.readSint16BE();
- _actListArr[i][j].a25.x1 = in.readSint16BE();
- _actListArr[i][j].a25.y1 = in.readSint16BE();
- _actListArr[i][j].a25.x2 = in.readSint16BE();
- _actListArr[i][j].a25.y2 = in.readSint16BE();
- _actListArr[i][j].a25.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a25.actFailIndex = in.readUint16BE();
- break;
- case SOUND: // 26
- _actListArr[i][j].a26.timer = in.readSint16BE();
- _actListArr[i][j].a26.soundIndex = in.readSint16BE();
- break;
- case ADD_SCORE: // 27
- _actListArr[i][j].a27.timer = in.readSint16BE();
- _actListArr[i][j].a27.objIndex = in.readSint16BE();
- break;
- case SUB_SCORE: // 28
- _actListArr[i][j].a28.timer = in.readSint16BE();
- _actListArr[i][j].a28.objIndex = in.readSint16BE();
- break;
- case COND_CARRY: // 29
- _actListArr[i][j].a29.timer = in.readSint16BE();
- _actListArr[i][j].a29.objIndex = in.readSint16BE();
- _actListArr[i][j].a29.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a29.actFailIndex = in.readUint16BE();
- break;
- case INIT_MAZE: // 30
- _actListArr[i][j].a30.timer = in.readSint16BE();
- _actListArr[i][j].a30.mazeSize = in.readByte();
- _actListArr[i][j].a30.x1 = in.readSint16BE();
- _actListArr[i][j].a30.y1 = in.readSint16BE();
- _actListArr[i][j].a30.x2 = in.readSint16BE();
- _actListArr[i][j].a30.y2 = in.readSint16BE();
- _actListArr[i][j].a30.x3 = in.readSint16BE();
- _actListArr[i][j].a30.x4 = in.readSint16BE();
- _actListArr[i][j].a30.firstScreenIndex = in.readByte();
- break;
- case EXIT_MAZE: // 31
- _actListArr[i][j].a31.timer = in.readSint16BE();
- break;
- case INIT_PRIORITY: // 32
- _actListArr[i][j].a32.timer = in.readSint16BE();
- _actListArr[i][j].a32.objIndex = in.readSint16BE();
- _actListArr[i][j].a32.priority = in.readByte();
- break;
- case INIT_SCREEN: // 33
- _actListArr[i][j].a33.timer = in.readSint16BE();
- _actListArr[i][j].a33.objIndex = in.readSint16BE();
- _actListArr[i][j].a33.screenIndex = in.readSint16BE();
- break;
- case AGSCHEDULE: // 34
- _actListArr[i][j].a34.timer = in.readSint16BE();
- _actListArr[i][j].a34.actIndex = in.readUint16BE();
- break;
- case REMAPPAL: // 35
- _actListArr[i][j].a35.timer = in.readSint16BE();
- _actListArr[i][j].a35.oldColorIndex = in.readSint16BE();
- _actListArr[i][j].a35.newColorIndex = in.readSint16BE();
- break;
- case COND_NOUN: // 36
- _actListArr[i][j].a36.timer = in.readSint16BE();
- _actListArr[i][j].a36.nounIndex = in.readUint16BE();
- _actListArr[i][j].a36.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a36.actFailIndex = in.readUint16BE();
- break;
- case SCREEN_STATE: // 37
- _actListArr[i][j].a37.timer = in.readSint16BE();
- _actListArr[i][j].a37.screenIndex = in.readSint16BE();
- _actListArr[i][j].a37.newState = in.readByte();
- break;
- case INIT_LIPS: // 38
- _actListArr[i][j].a38.timer = in.readSint16BE();
- _actListArr[i][j].a38.lipsObjIndex = in.readSint16BE();
- _actListArr[i][j].a38.objIndex = in.readSint16BE();
- _actListArr[i][j].a38.dxLips = in.readByte();
- _actListArr[i][j].a38.dyLips = in.readByte();
- break;
- case INIT_STORY_MODE: // 39
- _actListArr[i][j].a39.timer = in.readSint16BE();
- _actListArr[i][j].a39.storyModeFl = (in.readByte() == 1);
- break;
- case WARN: // 40
- _actListArr[i][j].a40.timer = in.readSint16BE();
- _actListArr[i][j].a40.stringIndex = in.readSint16BE();
- break;
- case COND_BONUS: // 41
- _actListArr[i][j].a41.timer = in.readSint16BE();
- _actListArr[i][j].a41.BonusIndex = in.readSint16BE();
- _actListArr[i][j].a41.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a41.actFailIndex = in.readUint16BE();
- break;
- case TEXT_TAKE: // 42
- _actListArr[i][j].a42.timer = in.readSint16BE();
- _actListArr[i][j].a42.objIndex = in.readSint16BE();
- break;
- case YESNO: // 43
- _actListArr[i][j].a43.timer = in.readSint16BE();
- _actListArr[i][j].a43.promptIndex = in.readSint16BE();
- _actListArr[i][j].a43.actYesIndex = in.readUint16BE();
- _actListArr[i][j].a43.actNoIndex = in.readUint16BE();
- break;
- case STOP_ROUTE: // 44
- _actListArr[i][j].a44.timer = in.readSint16BE();
- break;
- case COND_ROUTE: // 45
- _actListArr[i][j].a45.timer = in.readSint16BE();
- _actListArr[i][j].a45.routeIndex = in.readSint16BE();
- _actListArr[i][j].a45.actPassIndex = in.readUint16BE();
- _actListArr[i][j].a45.actFailIndex = in.readUint16BE();
- break;
- case INIT_JUMPEXIT: // 46
- _actListArr[i][j].a46.timer = in.readSint16BE();
- _actListArr[i][j].a46.jumpExitFl = (in.readByte() == 1);
- break;
- case INIT_VIEW: // 47
- _actListArr[i][j].a47.timer = in.readSint16BE();
- _actListArr[i][j].a47.objIndex = in.readSint16BE();
- _actListArr[i][j].a47.viewx = in.readSint16BE();
- _actListArr[i][j].a47.viewy = in.readSint16BE();
- _actListArr[i][j].a47.direction = in.readSint16BE();
- break;
- case INIT_OBJ_FRAME: // 48
- _actListArr[i][j].a48.timer = in.readSint16BE();
- _actListArr[i][j].a48.objIndex = in.readSint16BE();
- _actListArr[i][j].a48.seqIndex = in.readSint16BE();
- _actListArr[i][j].a48.frameIndex = in.readSint16BE();
- break;
- case OLD_SONG: //49
- _actListArr[i][j].a49.timer = in.readSint16BE();
- _actListArr[i][j].a49.songIndex = in.readUint16BE();
- break;
- default:
- error("Engine - Unknown action type encountered: %d", _actListArr[i][j].a0.actType);
- }
+ for (int j = 0; j < numSubElem; j++) {
+ if (varnt == _vm->_gameVariant) {
+ readAct(in, _actListArr[i][j]);
+ } else {
+ readAct(in, tmpAct);
+ if (tmpAct.a0.actType == PROMPT)
+ free(tmpAct.a3.responsePtr);
}
+ }
+
+ if (varnt == _vm->_gameVariant)
_actListArr[i][numSubElem].a0.actType = ANULL;
+ }
+ }
+}
+
+
+/**
+ * Read _screenActs
+ */
+void Scheduler::loadScreenAct(Common::SeekableReadStream &in) {
+ for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
+ uint16 numElem = in.readUint16BE();
+
+ if (varnt == _vm->_gameVariant) {
+ _screenActsSize = numElem;
+ _screenActs = (uint16 **)malloc(sizeof(uint16 *) * numElem);
+ for (int i = 0; i < numElem; i++) {
+ uint16 numSubElem = in.readUint16BE();
+ if (numSubElem == 0) {
+ _screenActs[i] = 0;
+ } else {
+ _screenActs[i] = (uint16 *)malloc(sizeof(uint16) * numSubElem);
+ for (int j = 0; j < numSubElem; j++)
+ _screenActs[i][j] = in.readUint16BE();
+ }
}
} else {
for (int i = 0; i < numElem; i++) {
- numSubElem = in.readUint16BE();
- for (int j = 0; j < numSubElem; j++) {
- numSubAct = in.readByte();
- switch (numSubAct) {
- case ANULL: // -1
- break;
- case ASCHEDULE: // 0
- in.readSint16BE();
- in.readUint16BE();
- break;
- case START_OBJ: // 1
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- break;
- case INIT_OBJXY: // 2
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case PROMPT: // 3
- in.readSint16BE();
- in.readSint16BE();
- numSubAct = in.readUint16BE();
- for (int k = 0; k < numSubAct; k++)
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- in.readByte();
- break;
- case BKGD_COLOR: // 4
- in.readSint16BE();
- in.readUint32BE();
- break;
- case INIT_OBJVXY: // 5
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case INIT_CARRY: // 6
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- break;
- case INIT_HF_COORD: // 7
- in.readSint16BE();
- in.readSint16BE();
- break;
- case NEW_SCREEN: // 8
- in.readSint16BE();
- in.readSint16BE();
- break;
- case INIT_OBJSTATE: // 9
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- break;
- case INIT_PATH: // 10
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- in.readByte();
- break;
- case COND_R: // 11
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case TEXT: // 12
- in.readSint16BE();
- in.readSint16BE();
- break;
- case SWAP_IMAGES: // 13
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case COND_SCR: // 14
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case AUTOPILOT: // 15
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- in.readByte();
- break;
- case INIT_OBJ_SEQ: // 16
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case SET_STATE_BITS: // 17
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case CLEAR_STATE_BITS: // 18
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case TEST_STATE_BITS: // 19
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case DEL_EVENTS: // 20
- in.readSint16BE();
- in.readByte();
- break;
- case GAMEOVER: // 21
- in.readSint16BE();
- break;
- case INIT_HH_COORD: // 22
- in.readSint16BE();
- in.readSint16BE();
- break;
- case EXIT: // 23
- in.readSint16BE();
- break;
- case BONUS: // 24
- in.readSint16BE();
- in.readSint16BE();
- break;
- case COND_BOX: // 25
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case SOUND: // 26
- in.readSint16BE();
- in.readSint16BE();
- break;
- case ADD_SCORE: // 27
- in.readSint16BE();
- in.readSint16BE();
- break;
- case SUB_SCORE: // 28
- in.readSint16BE();
- in.readSint16BE();
- break;
- case COND_CARRY: // 29
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case INIT_MAZE: // 30
- in.readSint16BE();
- in.readByte();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- break;
- case EXIT_MAZE: // 31
- in.readSint16BE();
- break;
- case INIT_PRIORITY: // 32
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- break;
- case INIT_SCREEN: // 33
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case AGSCHEDULE: // 34
- in.readSint16BE();
- in.readUint16BE();
- break;
- case REMAPPAL: // 35
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case COND_NOUN: // 36
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case SCREEN_STATE: // 37
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- break;
- case INIT_LIPS: // 38
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readByte();
- in.readByte();
- break;
- case INIT_STORY_MODE: // 39
- in.readSint16BE();
- in.readByte();
- break;
- case WARN: // 40
- in.readSint16BE();
- in.readSint16BE();
- break;
- case COND_BONUS: // 41
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case TEXT_TAKE: // 42
- in.readSint16BE();
- in.readSint16BE();
- break;
- case YESNO: // 43
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case STOP_ROUTE: // 44
- in.readSint16BE();
- break;
- case COND_ROUTE: // 45
- in.readSint16BE();
- in.readSint16BE();
- in.readUint16BE();
- in.readUint16BE();
- break;
- case INIT_JUMPEXIT: // 46
- in.readSint16BE();
- in.readByte();
- break;
- case INIT_VIEW: // 47
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case INIT_OBJ_FRAME: // 48
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- in.readSint16BE();
- break;
- case OLD_SONG: //49
- in.readSint16BE();
- in.readUint16BE();
- break;
- default:
- error("Engine - Unknown action type encountered %d - variante %d pos %d.%d", numSubAct, varnt, i, j);
- }
- }
+ uint16 numSubElem = in.readUint16BE();
+ in.skip(numSubElem * sizeof(uint16));
}
}
}
}
-void Scheduler::freeActListArr() {
+void Scheduler::freeScheduler() {
debugC(6, kDebugSchedule, "freeActListArr()");
+ free(_points);
+
+ if (_screenActs) {
+ for (int i = 0; i < _screenActsSize; i++)
+ free(_screenActs[i]);
+ free(_screenActs);
+ }
+
if (_actListArr) {
for (int i = 0; i < _actListArrSize; i++) {
for (int j = 0; _actListArr[i][j].a0.actType != ANULL; j++) {
@@ -832,38 +638,51 @@ void Scheduler::freeActListArr() {
}
/**
+ * Add action lists for this screen to event queue
+ */
+void Scheduler::screenActions(const int screenNum) {
+ debugC(1, kDebugEngine, "screenActions(%d)", screenNum);
+
+ uint16 *screenAct = _screenActs[screenNum];
+ if (screenAct) {
+ for (int i = 0; screenAct[i]; i++)
+ insertActionList(screenAct[i]);
+ }
+}
+
+/**
* Maze mode is enabled. Check to see whether hero has crossed the maze
* bounding box, if so, go to the next room
*/
void Scheduler::processMaze(const int x1, const int x2, const int y1, const int y2) {
debugC(1, kDebugSchedule, "processMaze");
- if (x1 < _maze.x1) {
+ if (x1 < _vm->_maze.x1) {
// Exit west
_actListArr[_alNewscrIndex][3].a8.screenIndex = *_vm->_screen_p - 1;
- _actListArr[_alNewscrIndex][0].a2.x = _maze.x2 - kShiftSize - (x2 - x1);
+ _actListArr[_alNewscrIndex][0].a2.x = _vm->_maze.x2 - kShiftSize - (x2 - x1);
_actListArr[_alNewscrIndex][0].a2.y = _vm->_hero->y;
_vm->_route->resetRoute();
insertActionList(_alNewscrIndex);
- } else if (x2 > _maze.x2) {
+ } else if (x2 > _vm->_maze.x2) {
// Exit east
_actListArr[_alNewscrIndex][3].a8.screenIndex = *_vm->_screen_p + 1;
- _actListArr[_alNewscrIndex][0].a2.x = _maze.x1 + kShiftSize;
+ _actListArr[_alNewscrIndex][0].a2.x = _vm->_maze.x1 + kShiftSize;
_actListArr[_alNewscrIndex][0].a2.y = _vm->_hero->y;
_vm->_route->resetRoute();
insertActionList(_alNewscrIndex);
- } else if (y1 < _maze.y1 - kShiftSize) {
+ } else if (y1 < _vm->_maze.y1 - kShiftSize) {
// Exit north
- _actListArr[_alNewscrIndex][3].a8.screenIndex = *_vm->_screen_p - _maze.size;
- _actListArr[_alNewscrIndex][0].a2.x = _maze.x3;
- _actListArr[_alNewscrIndex][0].a2.y = _maze.y2 - kShiftSize - (y2 - y1);
+ _actListArr[_alNewscrIndex][3].a8.screenIndex = *_vm->_screen_p - _vm->_maze.size;
+ _actListArr[_alNewscrIndex][0].a2.x = _vm->_maze.x3;
+ _actListArr[_alNewscrIndex][0].a2.y = _vm->_maze.y2 - kShiftSize - (y2 - y1);
_vm->_route->resetRoute();
insertActionList(_alNewscrIndex);
- } else if (y2 > _maze.y2 - kShiftSize / 2) {
+ } else if (y2 > _vm->_maze.y2 - kShiftSize / 2) {
// Exit south
- _actListArr[_alNewscrIndex][3].a8.screenIndex = *_vm->_screen_p + _maze.size;
- _actListArr[_alNewscrIndex][0].a2.x = _maze.x4;
- _actListArr[_alNewscrIndex][0].a2.y = _maze.y1 + kShiftSize;
+ _actListArr[_alNewscrIndex][3].a8.screenIndex = *_vm->_screen_p + _vm->_maze.size;
+ _actListArr[_alNewscrIndex][0].a2.x = _vm->_maze.x4;
+ _actListArr[_alNewscrIndex][0].a2.y = _vm->_maze.y1 + kShiftSize;
_vm->_route->resetRoute();
insertActionList(_alNewscrIndex);
}
@@ -889,73 +708,339 @@ void Scheduler::saveEvents(Common::WriteStream *f) {
f->writeSint16BE(tailIndex);
// Convert event ptrs to indexes
- event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes
for (int16 i = 0; i < kMaxEvents; i++) {
event_t *wrkEvent = &_events[i];
- saveEventArr[i] = *wrkEvent;
- // fix up action pointer (to do better)
+ // fix up action pointer (to do better)
int16 index, subElem;
- findAction(saveEventArr[i].action, &index, &subElem);
- saveEventArr[i].action = (act*)((index << 16)| subElem);
-
- saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events);
- saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events);
+ findAction(wrkEvent->action, &index, &subElem);
+ f->writeSint16BE(index);
+ f->writeSint16BE(subElem);
+ f->writeByte((wrkEvent->localActionFl) ? 1 : 0);
+ f->writeUint32BE(wrkEvent->time);
+ f->writeSint16BE((wrkEvent->prevEvent == 0) ? -1 : (wrkEvent->prevEvent - _events));
+ f->writeSint16BE((wrkEvent->nextEvent == 0) ? -1 : (wrkEvent->nextEvent - _events));
}
-
- f->write(saveEventArr, sizeof(saveEventArr));
}
-/**
+/**
* Restore the action data from file with handle f
*/
void Scheduler::restoreActions(Common::ReadStream *f) {
-
for (int i = 0; i < _actListArrSize; i++) {
-
- // read all the sub elems
- int j = 0;
- do {
-
- // handle special case for a3, keep list pointer
- int* responsePtr = 0;
- if (_actListArr[i][j].a3.actType == PROMPT) {
- responsePtr = _actListArr[i][j].a3.responsePtr;
- }
-
- f->read(&_actListArr[i][j], sizeof(act));
-
- // handle special case for a3, reset list pointer
- if (_actListArr[i][j].a3.actType == PROMPT) {
- _actListArr[i][j].a3.responsePtr = responsePtr;
- }
- j++;
- } while (_actListArr[i][j-1].a0.actType != ANULL);
+ uint16 numSubElem = f->readUint16BE();
+ for (int j = 0; j < numSubElem; j++) {
+ readAct(*f, _actListArr[i][j]);
+ }
}
}
+int16 Scheduler::calcMaxPoints() const {
+ int16 tmpScore = 0;
+ for (int i = 0; i < _numBonuses; i++)
+ tmpScore += _points[i].score;
+ return tmpScore;
+}
+
/*
* Save the action data in the file with handle f
*/
+void Scheduler::saveActions(Common::WriteStream *f) const {
+ byte subElemType;
+ int16 nbrCpt;
+ uint16 nbrSubElem;
-void Scheduler::saveActions(Common::WriteStream* f) const {
for (int i = 0; i < _actListArrSize; i++) {
// write all the sub elems data
-
- int j = 0;
- do {
- f->write(&_actListArr[i][j], sizeof(act));
- j++;
- } while (_actListArr[i][j-1].a0.actType != ANULL);
+ for (nbrSubElem = 1; _actListArr[i][nbrSubElem - 1].a0.actType != ANULL; nbrSubElem++)
+ ;
+
+ f->writeUint16BE(nbrSubElem);
+ for (int j = 0; j < nbrSubElem; j++) {
+ subElemType = _actListArr[i][j].a0.actType;
+ f->writeByte(subElemType);
+ switch (subElemType) {
+ case ANULL: // -1
+ break;
+ case ASCHEDULE: // 0
+ f->writeSint16BE(_actListArr[i][j].a0.timer);
+ f->writeUint16BE(_actListArr[i][j].a0.actIndex);
+ break;
+ case START_OBJ: // 1
+ f->writeSint16BE(_actListArr[i][j].a1.timer);
+ f->writeSint16BE(_actListArr[i][j].a1.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a1.cycleNumb);
+ f->writeByte(_actListArr[i][j].a1.cycle);
+ break;
+ case INIT_OBJXY: // 2
+ f->writeSint16BE(_actListArr[i][j].a2.timer);
+ f->writeSint16BE(_actListArr[i][j].a2.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a2.x);
+ f->writeSint16BE(_actListArr[i][j].a2.y);
+ break;
+ case PROMPT: // 3
+ f->writeSint16BE(_actListArr[i][j].a3.timer);
+ f->writeSint16BE(_actListArr[i][j].a3.promptIndex);
+ for (nbrCpt = 0; _actListArr[i][j].a3.responsePtr[nbrCpt] != -1; nbrCpt++)
+ ;
+ nbrCpt++;
+ f->writeUint16BE(nbrCpt);
+ for (int k = 0; k < nbrCpt; k++)
+ f->writeSint16BE(_actListArr[i][j].a3.responsePtr[k]);
+ f->writeUint16BE(_actListArr[i][j].a3.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a3.actFailIndex);
+ f->writeByte((_actListArr[i][j].a3.encodedFl) ? 1 : 0);
+ break;
+ case BKGD_COLOR: // 4
+ f->writeSint16BE(_actListArr[i][j].a4.timer);
+ f->writeUint32BE(_actListArr[i][j].a4.newBackgroundColor);
+ break;
+ case INIT_OBJVXY: // 5
+ f->writeSint16BE(_actListArr[i][j].a5.timer);
+ f->writeSint16BE(_actListArr[i][j].a5.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a5.vx);
+ f->writeSint16BE(_actListArr[i][j].a5.vy);
+ break;
+ case INIT_CARRY: // 6
+ f->writeSint16BE(_actListArr[i][j].a6.timer);
+ f->writeSint16BE(_actListArr[i][j].a6.objIndex);
+ f->writeByte((_actListArr[i][j].a6.carriedFl) ? 1 : 0);
+ break;
+ case INIT_HF_COORD: // 7
+ f->writeSint16BE(_actListArr[i][j].a7.timer);
+ f->writeSint16BE(_actListArr[i][j].a7.objIndex);
+ break;
+ case NEW_SCREEN: // 8
+ f->writeSint16BE(_actListArr[i][j].a8.timer);
+ f->writeSint16BE(_actListArr[i][j].a8.screenIndex);
+ break;
+ case INIT_OBJSTATE: // 9
+ f->writeSint16BE(_actListArr[i][j].a9.timer);
+ f->writeSint16BE(_actListArr[i][j].a9.objIndex);
+ f->writeByte(_actListArr[i][j].a9.newState);
+ break;
+ case INIT_PATH: // 10
+ f->writeSint16BE(_actListArr[i][j].a10.timer);
+ f->writeSint16BE(_actListArr[i][j].a10.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a10.newPathType);
+ f->writeByte(_actListArr[i][j].a10.vxPath);
+ f->writeByte(_actListArr[i][j].a10.vyPath);
+ break;
+ case COND_R: // 11
+ f->writeSint16BE(_actListArr[i][j].a11.timer);
+ f->writeSint16BE(_actListArr[i][j].a11.objIndex);
+ f->writeByte(_actListArr[i][j].a11.stateReq);
+ f->writeUint16BE(_actListArr[i][j].a11.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a11.actFailIndex);
+ break;
+ case TEXT: // 12
+ f->writeSint16BE(_actListArr[i][j].a12.timer);
+ f->writeSint16BE(_actListArr[i][j].a12.stringIndex);
+ break;
+ case SWAP_IMAGES: // 13
+ f->writeSint16BE(_actListArr[i][j].a13.timer);
+ f->writeSint16BE(_actListArr[i][j].a13.objIndex1);
+ f->writeSint16BE(_actListArr[i][j].a13.objIndex2);
+ break;
+ case COND_SCR: // 14
+ f->writeSint16BE(_actListArr[i][j].a14.timer);
+ f->writeSint16BE(_actListArr[i][j].a14.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a14.screenReq);
+ f->writeUint16BE(_actListArr[i][j].a14.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a14.actFailIndex);
+ break;
+ case AUTOPILOT: // 15
+ f->writeSint16BE(_actListArr[i][j].a15.timer);
+ f->writeSint16BE(_actListArr[i][j].a15.objIndex1);
+ f->writeSint16BE(_actListArr[i][j].a15.objIndex2);
+ f->writeByte(_actListArr[i][j].a15.dx);
+ f->writeByte(_actListArr[i][j].a15.dy);
+ break;
+ case INIT_OBJ_SEQ: // 16
+ f->writeSint16BE(_actListArr[i][j].a16.timer);
+ f->writeSint16BE(_actListArr[i][j].a16.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a16.seqIndex);
+ break;
+ case SET_STATE_BITS: // 17
+ f->writeSint16BE(_actListArr[i][j].a17.timer);
+ f->writeSint16BE(_actListArr[i][j].a17.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a17.stateMask);
+ break;
+ case CLEAR_STATE_BITS: // 18
+ f->writeSint16BE(_actListArr[i][j].a18.timer);
+ f->writeSint16BE(_actListArr[i][j].a18.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a18.stateMask);
+ break;
+ case TEST_STATE_BITS: // 19
+ f->writeSint16BE(_actListArr[i][j].a19.timer);
+ f->writeSint16BE(_actListArr[i][j].a19.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a19.stateMask);
+ f->writeUint16BE(_actListArr[i][j].a19.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a19.actFailIndex);
+ break;
+ case DEL_EVENTS: // 20
+ f->writeSint16BE(_actListArr[i][j].a20.timer);
+ f->writeByte(_actListArr[i][j].a20.actTypeDel);
+ break;
+ case GAMEOVER: // 21
+ f->writeSint16BE(_actListArr[i][j].a21.timer);
+ break;
+ case INIT_HH_COORD: // 22
+ f->writeSint16BE(_actListArr[i][j].a22.timer);
+ f->writeSint16BE(_actListArr[i][j].a22.objIndex);
+ break;
+ case EXIT: // 23
+ f->writeSint16BE(_actListArr[i][j].a23.timer);
+ break;
+ case BONUS: // 24
+ f->writeSint16BE(_actListArr[i][j].a24.timer);
+ f->writeSint16BE(_actListArr[i][j].a24.pointIndex);
+ break;
+ case COND_BOX: // 25
+ f->writeSint16BE(_actListArr[i][j].a25.timer);
+ f->writeSint16BE(_actListArr[i][j].a25.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a25.x1);
+ f->writeSint16BE(_actListArr[i][j].a25.y1);
+ f->writeSint16BE(_actListArr[i][j].a25.x2);
+ f->writeSint16BE(_actListArr[i][j].a25.y2);
+ f->writeUint16BE(_actListArr[i][j].a25.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a25.actFailIndex);
+ break;
+ case SOUND: // 26
+ f->writeSint16BE(_actListArr[i][j].a26.timer);
+ f->writeSint16BE(_actListArr[i][j].a26.soundIndex);
+ break;
+ case ADD_SCORE: // 27
+ f->writeSint16BE(_actListArr[i][j].a27.timer);
+ f->writeSint16BE(_actListArr[i][j].a27.objIndex);
+ break;
+ case SUB_SCORE: // 28
+ f->writeSint16BE(_actListArr[i][j].a28.timer);
+ f->writeSint16BE(_actListArr[i][j].a28.objIndex);
+ break;
+ case COND_CARRY: // 29
+ f->writeSint16BE(_actListArr[i][j].a29.timer);
+ f->writeSint16BE(_actListArr[i][j].a29.objIndex);
+ f->writeUint16BE(_actListArr[i][j].a29.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a29.actFailIndex);
+ break;
+ case INIT_MAZE: // 30
+ f->writeSint16BE(_actListArr[i][j].a30.timer);
+ f->writeByte(_actListArr[i][j].a30.mazeSize);
+ f->writeSint16BE(_actListArr[i][j].a30.x1);
+ f->writeSint16BE(_actListArr[i][j].a30.y1);
+ f->writeSint16BE(_actListArr[i][j].a30.x2);
+ f->writeSint16BE(_actListArr[i][j].a30.y2);
+ f->writeSint16BE(_actListArr[i][j].a30.x3);
+ f->writeSint16BE(_actListArr[i][j].a30.x4);
+ f->writeByte(_actListArr[i][j].a30.firstScreenIndex);
+ break;
+ case EXIT_MAZE: // 31
+ f->writeSint16BE(_actListArr[i][j].a31.timer);
+ break;
+ case INIT_PRIORITY: // 32
+ f->writeSint16BE(_actListArr[i][j].a32.timer);
+ f->writeSint16BE(_actListArr[i][j].a32.objIndex);
+ f->writeByte(_actListArr[i][j].a32.priority);
+ break;
+ case INIT_SCREEN: // 33
+ f->writeSint16BE(_actListArr[i][j].a33.timer);
+ f->writeSint16BE(_actListArr[i][j].a33.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a33.screenIndex);
+ break;
+ case AGSCHEDULE: // 34
+ f->writeSint16BE(_actListArr[i][j].a34.timer);
+ f->writeUint16BE(_actListArr[i][j].a34.actIndex);
+ break;
+ case REMAPPAL: // 35
+ f->writeSint16BE(_actListArr[i][j].a35.timer);
+ f->writeSint16BE(_actListArr[i][j].a35.oldColorIndex);
+ f->writeSint16BE(_actListArr[i][j].a35.newColorIndex);
+ break;
+ case COND_NOUN: // 36
+ f->writeSint16BE(_actListArr[i][j].a36.timer);
+ f->writeUint16BE(_actListArr[i][j].a36.nounIndex);
+ f->writeUint16BE(_actListArr[i][j].a36.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a36.actFailIndex);
+ break;
+ case SCREEN_STATE: // 37
+ f->writeSint16BE(_actListArr[i][j].a37.timer);
+ f->writeSint16BE(_actListArr[i][j].a37.screenIndex);
+ f->writeByte(_actListArr[i][j].a37.newState);
+ break;
+ case INIT_LIPS: // 38
+ f->writeSint16BE(_actListArr[i][j].a38.timer);
+ f->writeSint16BE(_actListArr[i][j].a38.lipsObjIndex);
+ f->writeSint16BE(_actListArr[i][j].a38.objIndex);
+ f->writeByte(_actListArr[i][j].a38.dxLips);
+ f->writeByte(_actListArr[i][j].a38.dyLips);
+ break;
+ case INIT_STORY_MODE: // 39
+ f->writeSint16BE(_actListArr[i][j].a39.timer);
+ f->writeByte((_actListArr[i][j].a39.storyModeFl) ? 1 : 0);
+ break;
+ case WARN: // 40
+ f->writeSint16BE(_actListArr[i][j].a40.timer);
+ f->writeSint16BE(_actListArr[i][j].a40.stringIndex);
+ break;
+ case COND_BONUS: // 41
+ f->writeSint16BE(_actListArr[i][j].a41.timer);
+ f->writeSint16BE(_actListArr[i][j].a41.BonusIndex);
+ f->writeUint16BE(_actListArr[i][j].a41.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a41.actFailIndex);
+ break;
+ case TEXT_TAKE: // 42
+ f->writeSint16BE(_actListArr[i][j].a42.timer);
+ f->writeSint16BE(_actListArr[i][j].a42.objIndex);
+ break;
+ case YESNO: // 43
+ f->writeSint16BE(_actListArr[i][j].a43.timer);
+ f->writeSint16BE(_actListArr[i][j].a43.promptIndex);
+ f->writeUint16BE(_actListArr[i][j].a43.actYesIndex);
+ f->writeUint16BE(_actListArr[i][j].a43.actNoIndex);
+ break;
+ case STOP_ROUTE: // 44
+ f->writeSint16BE(_actListArr[i][j].a44.timer);
+ break;
+ case COND_ROUTE: // 45
+ f->writeSint16BE(_actListArr[i][j].a45.timer);
+ f->writeSint16BE(_actListArr[i][j].a45.routeIndex);
+ f->writeUint16BE(_actListArr[i][j].a45.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a45.actFailIndex);
+ break;
+ case INIT_JUMPEXIT: // 46
+ f->writeSint16BE(_actListArr[i][j].a46.timer);
+ f->writeByte((_actListArr[i][j].a46.jumpExitFl) ? 1 : 0);
+ break;
+ case INIT_VIEW: // 47
+ f->writeSint16BE(_actListArr[i][j].a47.timer);
+ f->writeSint16BE(_actListArr[i][j].a47.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a47.viewx);
+ f->writeSint16BE(_actListArr[i][j].a47.viewy);
+ f->writeSint16BE(_actListArr[i][j].a47.direction);
+ break;
+ case INIT_OBJ_FRAME: // 48
+ f->writeSint16BE(_actListArr[i][j].a48.timer);
+ f->writeSint16BE(_actListArr[i][j].a48.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a48.seqIndex);
+ f->writeSint16BE(_actListArr[i][j].a48.frameIndex);
+ break;
+ case OLD_SONG: // 49, Added by Strangerke for DOS versions
+ f->writeSint16BE(_actListArr[i][j].a49.timer);
+ f->writeUint16BE(_actListArr[i][j].a49.songIndex);
+ break;
+ default:
+ error("Unknown action %d", subElemType);
+ }
+ }
}
}
/*
* Find the index in the action list to be able to serialize the action to save game
*/
-
-void Scheduler::findAction(act* action, int16* index, int16* subElem) {
+void Scheduler::findAction(const act* action, int16* index, int16* subElem) {
assert(index && subElem);
if (!action) {
@@ -979,34 +1064,57 @@ void Scheduler::findAction(act* action, int16* index, int16* subElem) {
assert(0);
}
+void Scheduler::saveSchedulerData(Common::WriteStream *out) {
+ savePoints(out);
+
+ // Now save current time and all current events in event queue
+ saveEvents(out);
+
+ // Now save current actions
+ saveActions(out);
+}
+
+void Scheduler::restoreSchedulerData(Common::ReadStream *in) {
+ restorePoints(in);
+ _vm->_object->restoreAllSeq();
+
+ // Now restore time of the save and the event queue
+ restoreEvents(in);
+
+ // Now restore actions
+ restoreActions(in);
+}
+
/**
* Restore the event list from file with handle f
*/
void Scheduler::restoreEvents(Common::ReadStream *f) {
debugC(1, kDebugSchedule, "restoreEvents");
- event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes
-
uint32 saveTime = f->readUint32BE(); // time of save
int16 freeIndex = f->readSint16BE(); // Free list index
int16 headIndex = f->readSint16BE(); // Head of list index
int16 tailIndex = f->readSint16BE(); // Tail of list index
- f->read(savedEvents, sizeof(savedEvents));
- event_t *wrkEvent;
// Restore events indexes to pointers
for (int i = 0; i < kMaxEvents; i++) {
- wrkEvent = &savedEvents[i];
- _events[i] = *wrkEvent;
+ int16 index = f->readSint16BE();
+ int16 subElem = f->readSint16BE();
+
// fix up action pointer (to do better)
- int32 val = (size_t)_events[i].action;
- if ((val & 0xffff) == 0xffff) {
+ if ((index == -1) && (subElem == -1))
_events[i].action = 0;
- } else {
- _events[i].action = (act*)&_actListArr[val >> 16][val & 0xffff];
- }
- _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ];
- _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ];
+ else
+ _events[i].action = (act*)&_actListArr[index][subElem];
+
+ _events[i].localActionFl = (f->readByte() == 1) ? true : false;
+ _events[i].time = f->readUint32BE();
+
+ int16 prevIndex = f->readSint16BE();
+ int16 nextIndex = f->readSint16BE();
+
+ _events[i].prevEvent = (prevIndex == -1) ? (event_t *)0 : &_events[prevIndex];
+ _events[i].nextEvent = (nextIndex == -1) ? (event_t *)0 : &_events[nextIndex];
}
_freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex];
_headEvent = (headIndex == -1) ? 0 : &_events[headIndex];
@@ -1014,7 +1122,7 @@ void Scheduler::restoreEvents(Common::ReadStream *f) {
// Adjust times to fit our time
uint32 curTime = getTicks();
- wrkEvent = _headEvent; // The earliest event
+ event_t *wrkEvent = _headEvent; // The earliest event
while (wrkEvent) { // While mature events found
wrkEvent->time = wrkEvent->time - saveTime + curTime;
wrkEvent = wrkEvent->nextEvent;
@@ -1134,7 +1242,7 @@ event_t *Scheduler::doAction(event_t *curEvent) {
insertActionList(action->a11.actFailIndex);
break;
case TEXT: // act12: Text box (CF WARN)
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file
+ Utils::notifyBox(_vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file
break;
case SWAP_IMAGES: // act13: Swap 2 object images
_vm->_object->swapImages(action->a13.objIndex1, action->a13.objIndex2);
@@ -1213,18 +1321,18 @@ event_t *Scheduler::doAction(event_t *curEvent) {
insertActionList(action->a29.actFailIndex);
break;
case INIT_MAZE: // act30: Enable and init maze structure
- _maze.enabledFl = true;
- _maze.size = action->a30.mazeSize;
- _maze.x1 = action->a30.x1;
- _maze.y1 = action->a30.y1;
- _maze.x2 = action->a30.x2;
- _maze.y2 = action->a30.y2;
- _maze.x3 = action->a30.x3;
- _maze.x4 = action->a30.x4;
- _maze.firstScreenIndex = action->a30.firstScreenIndex;
+ _vm->_maze.enabledFl = true;
+ _vm->_maze.size = action->a30.mazeSize;
+ _vm->_maze.x1 = action->a30.x1;
+ _vm->_maze.y1 = action->a30.y1;
+ _vm->_maze.x2 = action->a30.x2;
+ _vm->_maze.y2 = action->a30.y2;
+ _vm->_maze.x3 = action->a30.x3;
+ _vm->_maze.x4 = action->a30.x4;
+ _vm->_maze.firstScreenIndex = action->a30.firstScreenIndex;
break;
case EXIT_MAZE: // act31: Disable maze mode
- _maze.enabledFl = false;
+ _vm->_maze.enabledFl = false;
break;
case INIT_PRIORITY:
_vm->_object->_objects[action->a32.objIndex].priority = action->a32.priority;
@@ -1259,19 +1367,19 @@ event_t *Scheduler::doAction(event_t *curEvent) {
gameStatus.storyModeFl = action->a39.storyModeFl;
break;
case WARN: // act40: Text box (CF TEXT)
- Utils::Box(kBoxOk, "%s", _vm->_file->fetchString(action->a40.stringIndex));
+ Utils::notifyBox(_vm->_file->fetchString(action->a40.stringIndex));
break;
case COND_BONUS: // act41: Perform action if got bonus
- if (_vm->_points[action->a41.BonusIndex].scoredFl)
+ if (_points[action->a41.BonusIndex].scoredFl)
insertActionList(action->a41.actPassIndex);
else
insertActionList(action->a41.actFailIndex);
break;
case TEXT_TAKE: // act42: Text box with "take" message
- Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(_vm->_object->_objects[action->a42.objIndex].nounIndex, TAKE_NAME));
+ Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(_vm->_object->_objects[action->a42.objIndex].nounIndex, TAKE_NAME)));
break;
case YESNO: // act43: Prompt user for Yes or No
- if (Utils::Box(kBoxYesNo, "%s", _vm->_file->fetchString(action->a43.promptIndex)) != 0)
+ if (Utils::yesNoBox(_vm->_file->fetchString(action->a43.promptIndex)))
insertActionList(action->a43.actYesIndex);
else
insertActionList(action->a43.actNoIndex);
@@ -1354,6 +1462,9 @@ void Scheduler::delQueue(event_t *curEvent) {
_freeEvent = curEvent;
}
+/**
+ * Delete all the active events of a given type
+ */
void Scheduler::delEventType(const action_t actTypeDel) {
// Note: actions are not deleted here, simply turned into NOPs!
event_t *wrkEvent = _headEvent; // The earliest event
@@ -1367,6 +1478,27 @@ void Scheduler::delEventType(const action_t actTypeDel) {
}
}
+/**
+ * Save the points table
+ */
+void Scheduler::savePoints(Common::WriteStream *out) const {
+ for (int i = 0; i < _numBonuses; i++) {
+ out->writeByte(_points[i].score);
+ out->writeByte((_points[i].scoredFl) ? 1 : 0);
+ }
+}
+
+/**
+ * Restore the points table
+ */
+void Scheduler::restorePoints(Common::ReadStream *in) {
+ // Restore points table
+ for (int i = 0; i < _numBonuses; i++) {
+ _points[i].score = in->readByte();
+ _points[i].scoredFl = (in->readByte() == 1);
+ }
+}
+
Scheduler_v1d::Scheduler_v1d(HugoEngine *vm) : Scheduler(vm) {
}
@@ -1397,7 +1529,7 @@ void Scheduler_v1d::runScheduler() {
}
void Scheduler_v1d::promptAction(act *action) {
- Utils::Box(kBoxPrompt, "%s", _vm->_file->fetchString(action->a3.promptIndex));
+ Utils::promptBox(_vm->_file->fetchString(action->a3.promptIndex));
warning("STUB: doAction(act3)");
// TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block
@@ -1427,11 +1559,9 @@ void Scheduler_v1d::promptAction(act *action) {
void Scheduler_v1d::decodeString(char *line) {
debugC(1, kDebugSchedule, "decodeString(%s)", line);
- static const Common::String cypher = getCypher();
-
uint16 linelength = strlen(line);
for(uint16 i = 0; i < linelength; i++) {
- line[i] = (line[i] + cypher.c_str()[i % cypher.size()]) % '~';
+ line[i] = (line[i] + _cypher.c_str()[i % _cypher.size()]) % '~';
if (line[i] < ' ')
line[i] += ' ';
}
@@ -1448,7 +1578,7 @@ const char *Scheduler_v2d::getCypher() const {
}
void Scheduler_v2d::promptAction(act *action) {
- Utils::Box(kBoxPrompt, "%s", _vm->_file->fetchString(action->a3.promptIndex));
+ Utils::promptBox(_vm->_file->fetchString(action->a3.promptIndex));
warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0]));
// TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block
@@ -1480,11 +1610,10 @@ void Scheduler_v2d::promptAction(act *action) {
void Scheduler_v2d::decodeString(char *line) {
debugC(1, kDebugSchedule, "decodeString(%s)", line);
- static const Common::String cypher = getCypher();
-
int16 lineLength = strlen(line);
for (uint16 i = 0; i < lineLength; i++)
- line[i] -= cypher.c_str()[i % cypher.size()];
+ line[i] -= _cypher.c_str()[i % _cypher.size()];
+
debugC(1, kDebugSchedule, "result : %s", line);
}
diff --git a/engines/hugo/schedule.h b/engines/hugo/schedule.h
index b4889aa728..a066fc63c4 100644
--- a/engines/hugo/schedule.h
+++ b/engines/hugo/schedule.h
@@ -37,6 +37,64 @@
namespace Hugo {
+/**
+ * Following defines the action types and action list
+ */
+enum action_t { // Parameters:
+ ANULL = 0xff, // Special NOP used to 'delete' events in DEL_EVENTS
+ ASCHEDULE = 0, // 0 - Ptr to action list to be rescheduled
+ START_OBJ, // 1 - Object number
+ INIT_OBJXY, // 2 - Object number, x,y
+ PROMPT, // 3 - index of prompt & response string, ptrs to action
+ // lists. First if response matches, 2nd if not.
+ BKGD_COLOR, // 4 - new background color
+ INIT_OBJVXY, // 5 - Object number, vx, vy
+ INIT_CARRY, // 6 - Object number, carried status
+ INIT_HF_COORD, // 7 - Object number (gets hero's 'feet' coordinates)
+ NEW_SCREEN, // 8 - New screen number
+ INIT_OBJSTATE, // 9 - Object number, new object state
+ INIT_PATH, // 10 - Object number, new path type
+ COND_R, // 11 - Conditional on object state - req state, 2 act_lists
+ TEXT, // 12 - Simple text box
+ SWAP_IMAGES, // 13 - Swap 2 object images
+ COND_SCR, // 14 - Conditional on current screen
+ AUTOPILOT, // 15 - Set object to home in on another (stationary) object
+ INIT_OBJ_SEQ, // 16 - Object number, sequence index to set curr_seq_p to
+ SET_STATE_BITS, // 17 - Objnum, mask to OR with obj states word
+ CLEAR_STATE_BITS, // 18 - Objnum, mask to ~AND with obj states word
+ TEST_STATE_BITS, // 19 - Objnum, mask to test obj states word
+ DEL_EVENTS, // 20 - Action type to delete all occurrences of
+ GAMEOVER, // 21 - Disable hero & commands. Game is over
+ INIT_HH_COORD, // 22 - Object number (gets hero's actual coordinates)
+ EXIT, // 23 - Exit game back to DOS
+ BONUS, // 24 - Get score bonus for an action
+ COND_BOX, // 25 - Conditional on object within bounding box
+ SOUND, // 26 - Set currently playing sound
+ ADD_SCORE, // 27 - Add object's value to current score
+ SUB_SCORE, // 28 - Subtract object's value from current score
+ COND_CARRY, // 29 - Conditional on carrying object
+ INIT_MAZE, // 30 - Start special maze hotspot processing
+ EXIT_MAZE, // 31 - Exit special maze processing
+ INIT_PRIORITY, // 32 - Initialize fbg field
+ INIT_SCREEN, // 33 - Initialise screen field of object
+ AGSCHEDULE, // 34 - Global schedule - lasts over new screen
+ REMAPPAL, // 35 - Remappe palette - palette index, color
+ COND_NOUN, // 36 - Conditional on noun appearing in line
+ SCREEN_STATE, // 37 - Set new screen state - used for comments
+ INIT_LIPS, // 38 - Position lips object for supplied object
+ INIT_STORY_MODE, // 39 - Set story mode TRUE/FALSE (user can't type)
+ WARN, // 40 - Same as TEXT but can't dismiss box by typing
+ COND_BONUS, // 41 - Conditional on bonus having been scored
+ TEXT_TAKE, // 42 - Issue text box with "take" info string
+ YESNO, // 43 - Prompt user for Yes or No
+ STOP_ROUTE, // 44 - Skip any route in progress (hero still walks)
+ COND_ROUTE, // 45 - Conditional on route in progress
+ INIT_JUMPEXIT, // 46 - Initialize status.jumpexit
+ INIT_VIEW, // 47 - Initialize viewx, viewy, dir
+ INIT_OBJ_FRAME, // 48 - Object number, seq,frame to set curr_seq_p to
+ OLD_SONG = 49 // Added by Strangerke - Set currently playing sound, old way: that is, using a string index instead of a reference in a file
+};
+
struct act0 { // Type 0 - Schedule
action_t actType; // The type of action
int timer; // Time to set off the action
@@ -450,6 +508,14 @@ struct event_t {
struct event_t *nextEvent; // Chain to next event
};
+/**
+ * Following are points for achieving certain actions.
+ */
+struct point_t {
+ byte score; // The value of the point
+ bool scoredFl; // Whether scored yet
+};
+
class Scheduler {
public:
Scheduler(HugoEngine *vm);
@@ -458,31 +524,39 @@ public:
virtual void decodeString(char *line) = 0;
virtual void runScheduler() = 0;
- void freeActListArr();
+ int16 calcMaxPoints() const;
+
+ void freeScheduler();
+ void initCypher();
void initEventQueue();
void insertActionList(const uint16 actIndex);
void loadActListArr(Common::ReadStream &in);
void loadAlNewscrIndex(Common::ReadStream &in);
+ void loadPoints(Common::SeekableReadStream &in);
+ void loadScreenAct(Common::SeekableReadStream &in);
void newScreen(const int screenIndex);
void processBonus(const int bonusIndex);
void processMaze(const int x1, const int x2, const int y1, const int y2);
+ void restoreSchedulerData(Common::ReadStream *in);
void restoreScreen(const int screenIndex);
- void restoreEvents(Common::ReadStream *f);
- void saveEvents(Common::WriteStream *f);
+ void saveSchedulerData(Common::WriteStream *out);
void waitForRefresh();
- void findAction(act* action, int16* index, int16* subElem);
- void saveActions(Common::WriteStream* f) const;
- void restoreActions(Common::ReadStream *f);
-
protected:
HugoEngine *_vm;
static const int kFilenameLength = 12; // Max length of a DOS file name
static const int kMaxEvents = 50; // Max events in event queue
static const int kShiftSize = 8; // Place hero this far inside bounding box
+ Common::String _cypher;
+
uint16 _actListArrSize;
uint16 _alNewscrIndex;
+ uint16 _screenActsSize;
+ uint16 **_screenActs;
+
+ byte _numBonuses;
+ point_t *_points;
uint32 _curTick; // Current system time in ticks
uint32 _oldTime; // The previous wall time in ticks
@@ -509,7 +583,17 @@ protected:
void delEventType(const action_t actTypeDel);
void delQueue(event_t *curEvent);
+ void findAction(const act* action, int16* index, int16* subElem);
void insertAction(act *action);
+ void readAct(Common::ReadStream &in, act &curAct);
+ void restoreActions(Common::ReadStream *f);
+ void restoreEvents(Common::ReadStream *f);
+ void restorePoints(Common::ReadStream *in);
+ void saveActions(Common::WriteStream* f) const;
+ void saveEvents(Common::WriteStream *f);
+ void savePoints(Common::WriteStream *out) const;
+ void screenActions(const int screenNum);
+
};
class Scheduler_v1d : public Scheduler {
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index 3fa7e9fd4e..24359a2c54 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -37,6 +37,7 @@
#include "audio/decoders/raw.h"
#include "audio/audiostream.h"
+#include "audio/midiparser.h"
#include "hugo/hugo.h"
#include "hugo/game.h"
@@ -46,196 +47,80 @@
namespace Hugo {
-MidiPlayer::MidiPlayer(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0) {
+MidiPlayer::MidiPlayer() {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
assert(_driver);
- memset(_channelsTable, 0, sizeof(_channelsTable));
- for (int i = 0; i < kNumbChannels; i++) {
- _channelsVolume[i] = 127;
- }
- _isLooping = false;
- _isPlaying = false;
_paused = false;
- _masterVolume = 0;
-}
-MidiPlayer::~MidiPlayer() {
- close();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer::play(uint8 *stream, uint16 size) {
debugC(3, kDebugMusic, "MidiPlayer::play");
- if (!stream) {
- stop();
- return;
- }
+
+ Common::StackLock lock(_mutex);
stop();
+ if (!stream)
+ return;
+
_midiData = (uint8 *)malloc(size);
if (_midiData) {
memcpy(_midiData, stream, size);
- _mutex.lock();
- syncVolume();
+
+ syncVolume(); // FIXME: syncVolume calls setVolume which in turn also locks the mutex! ugh
+
+ _parser = MidiParser::createParser_SMF();
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
_isLooping = false;
_isPlaying = true;
- _mutex.unlock();
}
}
-void MidiPlayer::stop() {
- debugC(3, kDebugMusic, "MidiPlayer::stop");
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
- }
- _mutex.unlock();
-}
-
void MidiPlayer::pause(bool p) {
_paused = p;
- for (int i = 0; i < kNumbChannels; ++i) {
+ for (int i = 0; i < kNumChannels; ++i) {
if (_channelsTable[i]) {
_channelsTable[i]->volume(_paused ? 0 : _channelsVolume[i] * _masterVolume / 255);
}
}
}
-void MidiPlayer::updateTimer() {
- if (_paused) {
- return;
- }
+void MidiPlayer::onTimer() {
+ Common::StackLock lock(_mutex);
- _mutex.lock();
- if (_isPlaying) {
+ if (!_paused && _isPlaying && _parser) {
_parser->onTimer();
}
- _mutex.unlock();
-}
-
-void MidiPlayer::adjustVolume(int diff) {
- debugC(3, kDebugMusic, "MidiPlayer::adjustVolume");
- setVolume(_masterVolume + diff);
-}
-
-void MidiPlayer::syncVolume() {
- int volume = ConfMan.getInt("music_volume");
- if (ConfMan.getBool("mute")) {
- volume = -1;
- }
- debugC(2, kDebugMusic, "Syncing music volume to %d", volume);
- setVolume(volume);
-}
-
-void MidiPlayer::setVolume(int volume) {
- debugC(3, kDebugMusic, "MidiPlayer::setVolume");
- _masterVolume = CLIP(volume, 0, 255);
- _mutex.lock();
- for (int i = 0; i < kNumbChannels; ++i) {
- if (_channelsTable[i]) {
- _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
- }
- }
- _mutex.unlock();
-}
-
-void MidiPlayer::setChannelVolume(int channel) {
- int newVolume = _channelsVolume[channel] * _masterVolume / 255;
- debugC(3, kDebugMusic, "Music channel %d: volume %d->%d",
- channel, _channelsVolume[channel], newVolume);
- _channelsTable[channel]->volume(newVolume);
-}
-
-int MidiPlayer::open() {
- if (!_driver)
- return 255;
- int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->sendGMReset();
-
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
-
- return 0;
}
-void MidiPlayer::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(0, 0);
- _driver->close();
- delete _driver;
- _driver = 0;
- if (_parser)
- _parser->setMidiDriver(0);
- delete _parser;
- _mutex.unlock();
-}
-
-void MidiPlayer::send(uint32 b) {
- byte volume, ch = (byte)(b & 0xF);
- debugC(9, kDebugMusic, "MidiPlayer::send, channel %d (volume is %d)", ch, _channelsVolume[ch]);
- switch (b & 0xFFF0) {
- case 0x07B0: // volume change
- volume = (byte)((b >> 16) & 0x7F);
- _channelsVolume[ch] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- debugC(8, kDebugMusic, "Volume change, channel %d volume %d", ch, volume);
- break;
- case 0x7BB0: // all notes off
- debugC(8, kDebugMusic, "All notes off, channel %d", ch);
- if (!_channelsTable[ch]) { // channel not yet allocated, no need to send the event
- return;
- }
- break;
- }
-
- if (!_channelsTable[ch]) {
- _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- if (_channelsTable[ch])
- setChannelVolume(ch);
- }
- if (_channelsTable[ch]) {
- _channelsTable[ch]->send(b);
+void MidiPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
}
-}
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
-// warning("Unhandled meta event: %02x", type);
- break;
- }
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
-void MidiPlayer::timerCallback(void *p) {
- MidiPlayer *player = (MidiPlayer *)p;
-
- player->updateTimer();
-}
SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- MidiDriver *driver = MidiDriver::createMidi(dev);
-
- _midiPlayer = new MidiPlayer(driver);
+ _midiPlayer = new MidiPlayer();
_speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
@@ -337,7 +222,7 @@ void SoundHandler::playSound(int16 sound, const byte priority) {
* Initialize for MCI sound and midi
*/
void SoundHandler::initSound() {
- _midiPlayer->open();
+ //_midiPlayer->open();
}
void SoundHandler::syncVolume() {
@@ -452,11 +337,11 @@ void SoundHandler::pcspkr_player() {
case 'G':
count = pcspkrNotes[*DOSSongPtr - 'A'];
switch (DOSSongPtr[1]) { // Check for sharp or flat (#, -)
- case '#':
+ case '#':
count = pcspkrSharps[*DOSSongPtr++ - 'A'];
break;
- case 'b':
- count = pcspkrFlats[*DOSSongPtr++ - 'A'];
+ case 'b':
+ count = pcspkrFlats[*DOSSongPtr++ - 'A'];
break;
default:
break;
diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h
index 1b29ffcef9..d5f51704aa 100644
--- a/engines/hugo/sound.h
+++ b/engines/hugo/sound.h
@@ -34,59 +34,26 @@
#define HUGO_SOUND_H
#include "audio/mixer.h"
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/softsynth/pcspk.h"
namespace Hugo {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
- MidiPlayer(MidiDriver *driver);
- ~MidiPlayer();
+ MidiPlayer();
- bool isPlaying() { return _isPlaying; }
-
- int getVolume() { return _masterVolume; }
-
- void adjustVolume(int diff);
void pause(bool p);
void play(uint8 *stream, uint16 size);
- void setChannelVolume(int channel);
- void setLooping(bool loop) { _isLooping = loop; }
- void setVolume(int volume);
- void stop();
- void syncVolume();
- void updateTimer();
-
- // MidiDriver interface
- int open();
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ uint32 getBaseTempo();
- void close();
- void metaEvent(byte type, byte *data, uint16 length);
- void send(uint32 b);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
+ // Overload Audio::MidiPlayer method
+ virtual void sendToChannel(byte channel, uint32 b);
+ virtual void onTimer();
private:
- static void timerCallback(void *p);
-
- static const int kNumbChannels = 16;
-
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
bool _paused;
- int _masterVolume;
- MidiChannel *_channelsTable[kNumbChannels];
- uint8 _channelsVolume[kNumbChannels];
- Common::Mutex _mutex;
};
class SoundHandler {
diff --git a/engines/hugo/text.cpp b/engines/hugo/text.cpp
index 00a485a730..d2dcbe1405 100644
--- a/engines/hugo/text.cpp
+++ b/engines/hugo/text.cpp
@@ -29,14 +29,62 @@
namespace Hugo {
-TextHandler::TextHandler(HugoEngine *vm) : _vm(vm), _textData(0), _stringtData(0),
- _textEngine(0), _textIntro(0), _textMouse(0), _textParser(0), _textUtil(0),
+TextHandler::TextHandler(HugoEngine *vm) : _vm(vm), _textData(0), _stringtData(0),
+ _textEngine(0), _textIntro(0), _textMouse(0), _textParser(0), _textUtil(0),
_screenNames(0), _arrayNouns(0), _arrayVerbs(0) {
}
TextHandler::~TextHandler() {
}
+const char *TextHandler::getNoun(int idx1, int idx2) const {
+ return _arrayNouns[idx1][idx2];
+}
+
+const char *TextHandler::getScreenNames(int screenIndex) const {
+ return _screenNames[screenIndex];
+}
+
+const char *TextHandler::getStringtData(int stringIndex) const {
+ return _stringtData[stringIndex];
+}
+
+const char *TextHandler::getTextData(int textIndex) const {
+ return _textData[textIndex];
+}
+
+const char *TextHandler::getTextEngine(int engineIndex) const {
+ return _textEngine[engineIndex];
+}
+
+const char *TextHandler::getTextIntro(int introIndex) const {
+ return _textIntro[introIndex];
+}
+
+const char *TextHandler::getTextMouse(int mouseIndex) const {
+ return _textMouse[mouseIndex];
+}
+
+const char *TextHandler::getTextParser(int parserIndex) const {
+ return _textParser[parserIndex];
+}
+
+const char *TextHandler::getTextUtil(int utilIndex) const {
+ return _textUtil[utilIndex];
+}
+
+const char *TextHandler::getVerb(int idx1, int idx2) const {
+ return _arrayVerbs[idx1][idx2];
+}
+
+char **TextHandler::getNounArray(int idx1) const {
+ return _arrayNouns[idx1];
+}
+
+char **TextHandler::getVerbArray(int idx1) const {
+ return _arrayVerbs[idx1];
+}
+
char **TextHandler::loadTextsVariante(Common::ReadStream &in, uint16 *arraySize) {
int numTexts;
int entryLen;
diff --git a/engines/hugo/text.h b/engines/hugo/text.h
index cf728f6ad4..0854bf3f6e 100644
--- a/engines/hugo/text.h
+++ b/engines/hugo/text.h
@@ -32,18 +32,18 @@ public:
TextHandler(HugoEngine *vm);
~TextHandler();
- const char *getNoun(int idx1, int idx2) const { return _arrayNouns[idx1][idx2]; }
- const char *getScreenNames(int screenIndex) const { return _screenNames[screenIndex]; }
- const char *getStringtData(int stringIndex) const { return _stringtData[stringIndex]; }
- const char *getTextData(int textIndex) const { return _textData[textIndex]; }
- const char *getTextEngine(int engineIndex) const { return _textEngine[engineIndex]; }
- const char *getTextIntro(int introIndex) const { return _textIntro[introIndex]; }
- const char *getTextMouse(int mouseIndex) const { return _textMouse[mouseIndex]; }
- const char *getTextParser(int parserIndex) const { return _textParser[parserIndex]; }
- const char *getTextUtil(int utilIndex) const { return _textUtil[utilIndex]; }
- const char *getVerb(int idx1, int idx2) const { return _arrayVerbs[idx1][idx2]; }
- char **getNounArray(int idx1) { return _arrayNouns[idx1]; }
- char **getVerbArray(int idx1) { return _arrayVerbs[idx1]; }
+ const char *getNoun(int idx1, int idx2) const;
+ const char *getScreenNames(int screenIndex) const;
+ const char *getStringtData(int stringIndex) const;
+ const char *getTextData(int textIndex) const;
+ const char *getTextEngine(int engineIndex) const;
+ const char *getTextIntro(int introIndex) const;
+ const char *getTextMouse(int mouseIndex) const;
+ const char *getTextParser(int parserIndex) const;
+ const char *getTextUtil(int utilIndex) const;
+ const char *getVerb(int idx1, int idx2) const;
+ char **getNounArray(int idx1) const;
+ char **getVerbArray(int idx1) const;
void loadAllTexts(Common::ReadStream &in);
void freeAllTexts();
diff --git a/engines/hugo/util.cpp b/engines/hugo/util.cpp
index f8f9f5a0a5..044b58e986 100644
--- a/engines/hugo/util.cpp
+++ b/engines/hugo/util.cpp
@@ -41,10 +41,12 @@
namespace Hugo {
+namespace Utils {
+
/**
* Returns index (0 to 7) of first 1 in supplied byte, or 8 if not found
*/
-int Utils::firstBit(byte data) {
+int firstBit(byte data) {
if (!data)
return 8;
@@ -60,7 +62,7 @@ int Utils::firstBit(byte data) {
/**
* Returns index (0 to 7) of last 1 in supplied byte, or 8 if not found
*/
-int Utils::lastBit(byte data) {
+int lastBit(byte data) {
if (!data)
return 8;
@@ -76,7 +78,7 @@ int Utils::lastBit(byte data) {
/**
* Reverse the bit order in supplied byte
*/
-void Utils::reverseByte(byte *data) {
+void reverseByte(byte *data) {
byte maskIn = 0x80;
byte maskOut = 0x01;
byte result = 0;
@@ -89,65 +91,31 @@ void Utils::reverseByte(byte *data) {
*data = result;
}
-char *Utils::Box(box_t dismiss, const char *s, ...) {
- static char buffer[kMaxStrLength + 1]; // Format text into this
-
- if (!s)
- return 0; // NULL strings catered for
-
- if (s[0] == '\0')
- return 0;
+void notifyBox(const Common::String &msg) {
+ if (msg.empty())
+ return;
- if (strlen(s) > kMaxStrLength - 100) { // Test length
- warning("String too long: '%s'", s);
- return 0;
- }
+ GUI::MessageDialog dialog(msg, "OK");
+ dialog.runModal();
+}
- va_list marker;
- va_start(marker, s);
- vsprintf(buffer, s, marker); // Format string into buffer
- va_end(marker);
+Common::String promptBox(const Common::String &msg) {
+ if (msg.empty())
+ return Common::String();
- if (buffer[0] == '\0')
- return 0;
+ EntryDialog dialog(msg, "OK", "");
+ return dialog.getEditString();
+}
- switch(dismiss) {
- case kBoxAny:
- case kBoxOk: {
- GUI::MessageDialog dialog(buffer, "OK");
- dialog.runModal();
- break;
- }
- case kBoxYesNo: {
- GUI::MessageDialog dialog(buffer, "YES", "NO");
- if (dialog.runModal() == GUI::kMessageOK)
- return buffer;
+bool yesNoBox(const Common::String &msg) {
+ if (msg.empty())
return 0;
- break;
- }
- case kBoxPrompt: {
- // TODO: Some boxes (i.e. the combination code for the shed), needs to return an input.
- warning("Box: unhandled BOX_PROMPT");
- int boxTime = strlen(buffer) * 30;
- GUI::TimedMessageDialog dialog(buffer, MAX(1500, boxTime));
- dialog.runModal();
- break;
- }
- default:
- error("Unknown BOX Type %d", dismiss);
- }
- return buffer;
+ GUI::MessageDialog dialog(msg, "YES", "NO");
+ return (dialog.runModal() == GUI::kMessageOK);
}
-/**
- * Print options for user when dead
- */
-void Utils::gameOverMsg(void) {
- Utils::Box(kBoxOk, "%s", HugoEngine::get()._text->getTextUtil(kGameOver));
-}
-
-char *Utils::strlwr(char *buffer) {
+char *strlwr(char *buffer) {
char *result = buffer;
while (*buffer != '\0') {
@@ -159,4 +127,6 @@ char *Utils::strlwr(char *buffer) {
return result;
}
+} // End of namespace Utils
+
} // End of namespace Hugo
diff --git a/engines/hugo/util.h b/engines/hugo/util.h
index 84f69858fd..85fef01a6e 100644
--- a/engines/hugo/util.h
+++ b/engines/hugo/util.h
@@ -40,17 +40,36 @@ enum seqTextUtil {
};
namespace Utils {
-static const int kMaxStrLength = 1024;
int firstBit(byte data);
int lastBit(byte data);
-void gameOverMsg();
void reverseByte(byte *data);
-char *Box(box_t, const char *, ...) GCC_PRINTF(2, 3);
+/**
+ * Show a dialog notifying the user about something, with
+ * only a simple "OK" button to dismiss it.
+ */
+void notifyBox(const Common::String &msg);
+
+/**
+ * Show a dialog prompting the player to input some text.
+ */
+Common::String promptBox(const Common::String &msg);
+
+/**
+ * Show a dialog prompting the player for a "yes"/"no" choice.
+ */
+bool yesNoBox(const Common::String &msg);
+
+/**
+ * Convert a string to lower case, in place.
+ * @param buffer string to convert to lower case
+ * @return the string which was passed in
+ */
char *strlwr(char *buffer);
-}
+
+} // End of namespace Utils
} // End of namespace Hugo
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp
index 12f1061432..e6daba7aeb 100644
--- a/engines/kyra/animator_mr.cpp
+++ b/engines/kyra/animator_mr.cpp
@@ -336,7 +336,6 @@ void KyraEngine_MR::setupSceneAnimObject(int animId, uint16 flags, int x, int y,
if (flags & 8) {
_sceneAnimMovie[animId]->open(filename, 1, 0);
- musicUpdate(0);
if (_sceneAnimMovie[animId]->opened()) {
anim.wsaFlag = 1;
if (x2 == -1)
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index b7952eb81e..3560478a1b 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -564,7 +564,6 @@ int GUI_LoK::resumeGame(Button *button) {
void GUI_LoK::setupSavegames(Menu &menu, int num) {
Common::InSaveFile *in;
- static char savenames[5][35];
uint8 startSlot;
assert(num <= 5);
@@ -583,11 +582,11 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) {
KyraEngine_LoK::SaveHeader header;
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); i++) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) {
- Common::strlcpy(savenames[i], header.description.c_str(), ARRAYSIZE(savenames[0]));
+ Common::strlcpy(_savegameNames[i], header.description.c_str(), ARRAYSIZE(_savegameNames[0]));
- Util::convertISOToDOS(savenames[i]);
+ Util::convertISOToDOS(_savegameNames[i]);
- menu.item[i].itemString = savenames[i];
+ menu.item[i].itemString = _savegameNames[i];
menu.item[i].enabled = 1;
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
delete in;
diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h
index 05dd1533b1..e846933741 100644
--- a/engines/kyra/gui_lok.h
+++ b/engines/kyra/gui_lok.h
@@ -166,6 +166,7 @@ private:
uint8 _toplevelMenu;
int _savegameOffset;
char _savegameName[35];
+ char _savegameNames[5][35];
const char *_specialSavegameString;
Button::Callback _scrollUpFunctor;
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index a04ec49324..6bdecfc3b8 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -830,8 +830,6 @@ void KyraEngine_MR::processAlbum() {
checkInput(buttonList);
removeInputTop();
- musicUpdate(0);
-
if (_album.curPage != _album.nextPage) {
int oldPage = _album.curPage;
_album.curPage = _album.nextPage;
@@ -1085,11 +1083,6 @@ void GUI_MR::flagButtonDisable(Button *button) {
}
}
-void GUI_MR::getInput() {
- _vm->musicUpdate(0);
- GUI_v2::getInput();
-}
-
const char *GUI_MR::getMenuTitle(const Menu &menu) {
if (!menu.menuNameId)
return 0;
@@ -1173,8 +1166,6 @@ int GUI_MR::quitGame(Button *caller) {
int GUI_MR::optionsButton(Button *button) {
PauseTimer pause(*_vm->_timer);
- _vm->musicUpdate(0);
-
_screen->hideMouse();
updateButton(&_vm->_mainButtonData[0]);
_screen->showMouse();
@@ -1200,7 +1191,6 @@ int GUI_MR::optionsButton(Button *button) {
int oldHandItem = _vm->_itemInHand;
_screen->setMouseCursor(0, 0, _vm->getShapePtr(0));
- _vm->musicUpdate(0);
_displayMenu = true;
for (int i = 0; i < 4; ++i) {
@@ -1226,8 +1216,6 @@ int GUI_MR::optionsButton(Button *button) {
_currentMenu = &_mainMenu;
- _vm->musicUpdate(0);
-
if (_vm->_menuDirectlyToLoad) {
backUpPage1(_vm->_screenBuffer);
@@ -1256,7 +1244,6 @@ int GUI_MR::optionsButton(Button *button) {
_isDeathMenu = false;
}
- _vm->musicUpdate(0);
backUpPage1(_vm->_screenBuffer);
initMenu(*_currentMenu);
_madeSave = false;
@@ -1407,7 +1394,6 @@ int GUI_MR::gameOptions(Button *caller) {
}
void GUI_MR::setupOptionsButtons() {
- _vm->musicUpdate(0);
if (_vm->_configWalkspeed == 3)
_gameOptions.item[0].itemId = 28;
else
diff --git a/engines/kyra/gui_mr.h b/engines/kyra/gui_mr.h
index 89aaa447d1..b104626db7 100644
--- a/engines/kyra/gui_mr.h
+++ b/engines/kyra/gui_mr.h
@@ -50,8 +50,6 @@ public:
void createScreenThumbnail(Graphics::Surface &dst);
private:
- void getInput();
-
const char *getMenuTitle(const Menu &menu);
const char *getMenuItemTitle(const MenuItem &menuItem);
const char *getMenuItemLabel(const MenuItem &menuItem);
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index 5c471a8c8b..c73792ef8e 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -87,7 +87,9 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn
_pathfinderFlag = 0;
_mouseX = _mouseY = 0;
+ _nextIdleAnim = 0;
_lastIdleScript = -1;
+ _useSceneIdleAnim = false;
_currentTalkSections.STATim = 0;
_currentTalkSections.TLKTim = 0;
@@ -145,6 +147,11 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn
_menu = 0;
_chatIsNote = false;
memset(&_npcScriptData, 0, sizeof(_npcScriptData));
+
+ _setCharPalFinal = false;
+ _useCharPal = false;
+
+ memset(_characterFacingCountTable, 0, sizeof(_characterFacingCountTable));
}
KyraEngine_HoF::~KyraEngine_HoF() {
@@ -504,6 +511,14 @@ void KyraEngine_HoF::runLoop() {
int inputFlag = checkInput(_buttonList, true);
removeInputTop();
+ if (_updateHandItemCursor) {
+ // This works around an issue which would occur when setHandItem(_itemInHand)
+ // was called from inside loadGameState(). When loading via GMM the
+ // mouse cursor would not be set correctly.
+ _updateHandItemCursor = false;
+ setHandItem(_itemInHand);
+ }
+
update();
if (inputFlag == 198 || inputFlag == 199) {
@@ -1127,8 +1142,6 @@ void KyraEngine_HoF::restorePage0() {
}
void KyraEngine_HoF::updateCharPal(int unk1) {
- static bool unkVar1 = false;
-
if (!_useCharPal)
return;
@@ -1144,12 +1157,12 @@ void KyraEngine_HoF::updateCharPal(int unk1) {
++src;
}
_screen->setScreenPalette(_screen->getPalette(0));
- unkVar1 = true;
+ _setCharPalFinal = true;
_charPalEntry = palEntry;
- } else if (unkVar1 || !unk1) {
+ } else if (_setCharPalFinal || !unk1) {
_screen->getPalette(0).copy(_scenePal, palEntry << 4, 16, 112);
_screen->setScreenPalette(_screen->getPalette(0));
- unkVar1 = false;
+ _setCharPalFinal = false;
}
}
@@ -1266,15 +1279,14 @@ int KyraEngine_HoF::getCharacterWalkspeed() const {
return _timer->getDelay(0);
}
-void KyraEngine_HoF::updateCharAnimFrame(int charId, int *table) {
- static int unkTable1[] = { 0, 0 };
- static const int unkTable2[] = { 17, 0 };
- static const int unkTable3[] = { 10, 0 };
- static const int unkTable4[] = { 24, 0 };
- static const int unkTable5[] = { 19, 0 };
- static const int unkTable6[] = { 21, 0 };
- static const int unkTable7[] = { 31, 0 };
- static const int unkTable8[] = { 26, 0 };
+void KyraEngine_HoF::updateCharAnimFrame(int *table) {
+ static const int unkFrame1 = 17;
+ static const int unkFrame2 = 10;
+ static const int unkFrame3 = 24;
+ static const int unkFrame4 = 19;
+ static const int unkFrame5 = 21;
+ static const int unkFrame6 = 31;
+ static const int unkFrame7 = 26;
Character *character = &_mainCharacter;
++character->animFrame;
@@ -1289,46 +1301,46 @@ void KyraEngine_HoF::updateCharAnimFrame(int charId, int *table) {
}
if (!facing) {
- ++unkTable1[charId];
+ ++_characterFacingCountTable[0];
} else if (facing == 4) {
- ++unkTable1[charId+1];
+ ++_characterFacingCountTable[1];
} else if (facing == 7 || facing == 1 || facing == 5 || facing == 3) {
if (facing == 7 || facing == 1) {
- if (unkTable1[charId] > 2)
+ if (_characterFacingCountTable[0] > 2)
facing = 0;
} else {
- if (unkTable1[charId+1] > 2)
+ if (_characterFacingCountTable[1] > 2)
facing = 4;
}
- unkTable1[charId] = 0;
- unkTable1[charId+1] = 0;
+ _characterFacingCountTable[0] = 0;
+ _characterFacingCountTable[1] = 0;
}
if (facing == 0) {
- if (character->animFrame < unkTable8[charId])
- character->animFrame = unkTable8[charId];
+ if (character->animFrame < unkFrame7)
+ character->animFrame = unkFrame7;
- if (character->animFrame > unkTable7[charId])
- character->animFrame = unkTable8[charId];
+ if (character->animFrame > unkFrame6)
+ character->animFrame = unkFrame7;
} else if (facing == 4) {
- if (character->animFrame < unkTable5[charId])
- character->animFrame = unkTable5[charId];
+ if (character->animFrame < unkFrame4)
+ character->animFrame = unkFrame4;
- if (character->animFrame > unkTable4[charId])
- character->animFrame = unkTable5[charId];
+ if (character->animFrame > unkFrame3)
+ character->animFrame = unkFrame4;
} else {
- if (character->animFrame > unkTable5[charId])
- character->animFrame = unkTable6[charId];
+ if (character->animFrame > unkFrame4)
+ character->animFrame = unkFrame5;
- if (character->animFrame == unkTable2[charId])
- character->animFrame = unkTable3[charId];
+ if (character->animFrame == unkFrame1)
+ character->animFrame = unkFrame2;
- if (character->animFrame > unkTable2[charId])
- character->animFrame = unkTable3[charId] + 2;
+ if (character->animFrame > unkFrame1)
+ character->animFrame = unkFrame2 + 2;
}
- updateCharacterAnim(charId);
+ updateCharacterAnim(0);
}
bool KyraEngine_HoF::checkCharCollision(int x, int y) {
@@ -1385,12 +1397,11 @@ void KyraEngine_HoF::showIdleAnim() {
if (queryGameFlag(0x159) && _flags.isTalkie)
return;
- static bool scriptAnimation = false;
- if (!scriptAnimation && _flags.isTalkie) {
- scriptAnimation = true;
+ if (!_useSceneIdleAnim && _flags.isTalkie) {
+ _useSceneIdleAnim = true;
randomSceneChat();
} else {
- scriptAnimation = false;
+ _useSceneIdleAnim = false;
if (_characterShapeFile > 8)
return;
diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h
index b862a89dd0..308698484d 100644
--- a/engines/kyra/kyra_hof.h
+++ b/engines/kyra/kyra_hof.h
@@ -574,13 +574,16 @@ protected:
// character
bool _useCharPal;
+ bool _setCharPalFinal;
int _charPalEntry;
uint8 _charPalTable[16];
void updateCharPal(int unk1);
void setCharPalEntry(int entry, int value);
+ int _characterFacingCountTable[2];
+
int getCharacterWalkspeed() const;
- void updateCharAnimFrame(int num, int *table);
+ void updateCharAnimFrame(int *table);
bool checkCharCollision(int x, int y);
@@ -681,6 +684,7 @@ protected:
uint32 _nextIdleAnim;
int _lastIdleScript;
+ bool _useSceneIdleAnim;
void setNextIdleAnimTimer();
void showIdleAnim();
diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp
index d46fc2d502..d7ec6ada71 100644
--- a/engines/kyra/kyra_lok.cpp
+++ b/engines/kyra/kyra_lok.cpp
@@ -92,10 +92,22 @@ KyraEngine_LoK::KyraEngine_LoK(OSystem *system, const GameFlags &flags)
memset(_panPagesTable, 0, sizeof(_panPagesTable));
memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
_currHeadShape = 0;
+ _currentHeadFrameTableIndex = 0;
_speechPlayTime = 0;
_seqPlayerFlag = false;
+ memset(&_characterFacingZeroCount, 0, sizeof(_characterFacingZeroCount));
+ memset(&_characterFacingFourCount, 0, sizeof(_characterFacingFourCount));
+
memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp));
+
+ _beadStateTimer1 = _beadStateTimer2 = 0;
+ memset(&_beadState1, 0, sizeof(_beadState1));
+ _beadState1.x = -1;
+ memset(&_beadState2, 0, sizeof(_beadState2));
+
+ _malcolmFrame = 0;
+ _malcolmTimer1 = _malcolmTimer2 = 0;
}
KyraEngine_LoK::~KyraEngine_LoK() {
@@ -819,6 +831,14 @@ void KyraEngine_LoK::updateMousePointer(bool forceUpdate) {
newY = 4;
}
+ if (_updateHandItemCursor) {
+ // This works around an issue which would occur when setHandItem(_itemInHand)
+ // was called from inside loadGameState(). When loading via GMM the
+ // mouse cursor would not be set correctly.
+ _updateHandItemCursor = false;
+ setHandItem(_itemInHand);
+ }
+
if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) {
_mouseState = newMouseState;
_screen->hideMouse();
diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h
index dfbf5bddd8..d1ff24ad85 100644
--- a/engines/kyra/kyra_lok.h
+++ b/engines/kyra/kyra_lok.h
@@ -447,6 +447,9 @@ protected:
uint16 _currentChatPartnerBackupFrame;
uint16 _currentCharAnimFrame;
+ int _characterFacingZeroCount[8];
+ int _characterFacingFourCount[8];
+
int8 *_sceneAnimTable[50];
uint8 _itemHtDat[145];
@@ -471,6 +474,7 @@ protected:
int8 _charSayUnk2;
int8 _charSayUnk3;
int8 _currHeadShape;
+ int _currentHeadFrameTableIndex;
int8 _disabledTalkAnimObject;
int8 _enabledTalkAnimObject;
uint8 _currSentenceColor[3];
@@ -498,6 +502,15 @@ protected:
Button *_buttonList;
GUI_LoK *_gui;
+ uint16 _malcolmFrame;
+ uint32 _malcolmTimer1;
+ uint32 _malcolmTimer2;
+
+ uint32 _beadStateTimer1;
+ uint32 _beadStateTimer2;
+ BeadState _beadState1;
+ BeadState _beadState2;
+
struct KyragemState {
uint16 nextOperation;
uint16 rOffset;
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index a6b99fffbf..65e78448a5 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -426,9 +426,7 @@ void KyraEngine_MR::snd_playWanderScoreViaMap(int track, int force) {
if (_musicSoundChannel == -1) {
assert(track < _soundListSize && track >= 0);
- char file[13];
- sprintf(file, "%s", _soundList[track]);
- _musicSoundChannel = _soundDigital->playSound(file, 0xFF, Audio::Mixer::kMusicSoundType);
+ _musicSoundChannel = _soundDigital->playSound(_soundList[track], 0xFF, Audio::Mixer::kMusicSoundType, 255, true);
}
_lastMusicCommand = track;
@@ -442,31 +440,6 @@ void KyraEngine_MR::stopMusicTrack() {
_musicSoundChannel = -1;
}
-int KyraEngine_MR::musicUpdate(int forceRestart) {
- static uint32 mTimer = 0;
- static uint16 lock = 0;
-
- if (ABS<int>(_system->getMillis() - mTimer) > (int)(0x0F * _tickLength))
- mTimer = _system->getMillis();
-
- if (_system->getMillis() < mTimer && !forceRestart)
- return 1;
-
- if (!lock) {
- lock = 1;
- if (_musicSoundChannel >= 0) {
- if (!_soundDigital->isPlaying(_musicSoundChannel)) {
- if (_lastMusicCommand != -1)
- snd_playWanderScoreViaMap(_lastMusicCommand, 1);
- }
- }
- lock = 0;
- mTimer = _system->getMillis() + 0x0F * _tickLength;
- }
-
- return 1;
-}
-
void KyraEngine_MR::fadeOutMusic(int ticks) {
if (_musicSoundChannel >= 0) {
_fadeOutMusicChannel = _musicSoundChannel;
@@ -550,11 +523,8 @@ void KyraEngine_MR::startup() {
assert(_album.leftPage.wsa);
_album.rightPage.wsa = new WSAMovie_v2(this);
assert(_album.rightPage.wsa);
- musicUpdate(0);
_gamePlayBuffer = new uint8[64000];
- musicUpdate(0);
- musicUpdate(0);
_interface = new uint8[17920];
_interfaceCommandLine = new uint8[3840];
@@ -562,17 +532,11 @@ void KyraEngine_MR::startup() {
_screen->setFont(Screen::FID_8_FNT);
_stringBuffer = new char[500];
- musicUpdate(0);
allocAnimObjects(1, 16, 50);
- musicUpdate(0);
-
memset(_sceneShapes, 0, sizeof(_sceneShapes));
_screenBuffer = new uint8[64000];
- musicUpdate(0);
- musicUpdate(0);
-
if (!loadLanguageFile("ITEMS.", _itemFile))
error("Couldn't load ITEMS");
if (!loadLanguageFile("SCORE.", _scoreFile))
@@ -586,13 +550,10 @@ void KyraEngine_MR::startup() {
if (!loadLanguageFile("_ACTOR.", _actorFile))
error("couldn't load _ACTOR");
- musicUpdate(0);
openTalkFile(0);
- musicUpdate(0);
_currentTalkFile = 0;
openTalkFile(1);
loadCostPal();
- musicUpdate(0);
for (int i = 0; i < 16; ++i) {
_sceneAnims[i].flags = 0;
@@ -607,30 +568,24 @@ void KyraEngine_MR::startup() {
for (int i = 0; i < 88; ++i)
_talkObjectList[i].sceneId = 0xFF;
- musicUpdate(0);
_gfxBackUpRect = new uint8[_screen->getRectSize(32, 32)];
initItemList(50);
resetItemList();
loadShadowShape();
- musicUpdate(0);
loadExtrasShapes();
- musicUpdate(0);
_characterShapeFile = 0;
loadCharacterShapes(_characterShapeFile);
updateMalcolmShapes();
- musicUpdate(0);
initMainButtonList(true);
loadButtonShapes();
loadInterfaceShapes();
- musicUpdate(0);
_screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
_paletteOverlay = new uint8[256];
_screen->generateOverlay(_screen->getPalette(0), _paletteOverlay, 0xF0, 0x19);
loadInterface();
- musicUpdate(0);
clearAnimObjects();
@@ -640,8 +595,6 @@ void KyraEngine_MR::startup() {
_scoreMax += _scoreTable[i];
}
- musicUpdate(0);
-
memset(_newSceneDlgState, 0, sizeof(_newSceneDlgState));
memset(_conversationState, -1, sizeof(_conversationState));
@@ -650,7 +603,6 @@ void KyraEngine_MR::startup() {
memset(_sceneList, 0, sizeof(SceneDesc)*98);
_sceneListSize = 98;
- musicUpdate(0);
runStartupScript(1, 0);
_res->exists("MOODOMTR.WSA", true);
_invWsa = new WSAMovie_v2(this);
@@ -667,7 +619,6 @@ void KyraEngine_MR::startup() {
(*_mainButtonData[0].buttonCallback)(&_mainButtonData[0]);
_screen->updateScreen();
- musicUpdate(0);
_screen->showMouse();
setNextIdleAnimTimer();
@@ -837,7 +788,7 @@ int KyraEngine_MR::getCharacterWalkspeed() const {
return _mainCharacter.walkspeed;
}
-void KyraEngine_MR::updateCharAnimFrame(int character, int *table) {
+void KyraEngine_MR::updateCharAnimFrame(int *table) {
++_mainCharacter.animFrame;
int facing = _mainCharacter.facing;
@@ -966,6 +917,14 @@ void KyraEngine_MR::runLoop() {
int inputFlag = checkInput(_mainButtonList, true);
removeInputTop();
+ if (_updateHandItemCursor) {
+ // This works around an issue which would occur when setHandItem(_itemInHand)
+ // was called from inside loadGameState(). When loading via GMM the
+ // mouse cursor would not be set correctly.
+ _updateHandItemCursor = false;
+ setHandItem(_itemInHand);
+ }
+
update();
_timer->update();
@@ -1105,14 +1064,11 @@ int KyraEngine_MR::inputSceneChange(int x, int y, int unk1, int unk2) {
void KyraEngine_MR::update() {
updateInput();
- musicUpdate(0);
refreshAnimObjectsIfNeed();
- musicUpdate(0);
updateMouse();
updateSpecialSceneScripts();
updateCommandLine();
updateItemAnimations();
- musicUpdate(0);
_screen->updateScreen();
}
@@ -1120,12 +1076,10 @@ void KyraEngine_MR::update() {
void KyraEngine_MR::updateWithText() {
updateInput();
- musicUpdate(0);
updateMouse();
updateItemAnimations();
updateSpecialSceneScripts();
updateCommandLine();
- musicUpdate(0);
restorePage3();
drawAnimObjects();
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index fd31089953..912c615757 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -122,7 +122,6 @@ private:
void snd_playWanderScoreViaMap(int track, int force);
void stopMusicTrack();
- int musicUpdate(int forceRestart);
void fadeOutMusic(int ticks);
void snd_playSoundEffect(int item, int volume);
@@ -387,7 +386,7 @@ private:
// character
int getCharacterWalkspeed() const;
- void updateCharAnimFrame(int character, int *table);
+ void updateCharAnimFrame(int *table);
int8 _characterAnimTable[2];
static const uint8 _characterFrameTable[];
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index f5b96410e8..3a5d21196b 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -65,6 +65,7 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
_gameToLoad = -1;
_mouseState = -1;
+ _updateHandItemCursor = false;
_deathHandler = -1;
memset(_flagsTable, 0, sizeof(_flagsTable));
@@ -128,10 +129,11 @@ Common::Error KyraEngine_v1::init() {
_sound = new SoundAdLibPC(this, _mixer);
} else {
Sound::kType type;
+ const MusicType midiType = MidiDriver::getMusicType(dev);
- if (MidiDriver::getMusicType(dev) == MT_PCSPK)
+ if (midiType == MT_PCSPK || midiType == MT_NULL)
type = Sound::kPCSpkr;
- else if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32"))
+ else if (midiType == MT_MT32 || ConfMan.getBool("native_mt32"))
type = Sound::kMidiMT32;
else
type = Sound::kMidiGM;
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 12b9fb5942..cf51774b0f 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -343,6 +343,9 @@ protected:
virtual void setHandItem(Item item) = 0;
virtual void removeHandItem() = 0;
+ void setDelayedCursorUpdate() { _updateHandItemCursor = true; }
+ bool _updateHandItemCursor;
+
// game flags
uint8 _flagsTable[100]; // TODO: check this value
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 53c57c21cd..804097c81d 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -74,6 +74,9 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi
_pauseStart = 0;
+ _pathfinderFlag = 0;
+ _smoothingPath = false;
+
_lang = 0;
Common::Language lang = Common::parseLanguage(ConfMan.get("language"));
if (lang == _flags.fanLang && _flags.replacedLang != Common::UNK_LANG)
@@ -236,7 +239,7 @@ int KyraEngine_v2::updateCharPos(int *table, int force) {
return 0;
_mainCharacter.x1 += _charAddXPosTable[_mainCharacter.facing];
_mainCharacter.y1 += _charAddYPosTable[_mainCharacter.facing];
- updateCharAnimFrame(0, table);
+ updateCharAnimFrame(table);
_updateCharPosNextUpdate = _system->getMillis() + getCharacterWalkspeed() * _tickLength;
return 1;
}
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index 084b159ee2..9f0aecd78c 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -269,6 +269,7 @@ protected:
// pathfinder
int _movFacingTable[600];
int _pathfinderFlag;
+ bool _smoothingPath;
int findWay(int curX, int curY, int dstX, int dstY, int *moveTable, int moveTableSize);
@@ -340,7 +341,7 @@ protected:
uint32 _updateCharPosNextUpdate;
virtual int getCharacterWalkspeed() const = 0;
- virtual void updateCharAnimFrame(int num, int *table) = 0;
+ virtual void updateCharAnimFrame(int *table) = 0;
// chat
int _vocHigh;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 36bc0c99d7..5928c40f92 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -898,7 +898,9 @@ void LoLEngine::startupNew() {
memset(_globalScriptVars2, 0x100, 8);
- static int selectIds[] = { -9, -1, -8, -5 };
+ static const int selectIds[] = { -9, -1, -8, -5 };
+ assert(_charSelection >= 0);
+ assert(_charSelection < ARRAYSIZE(selectIds));
addCharacter(selectIds[_charSelection]);
gui_enableDefaultPlayfieldButtons();
@@ -931,6 +933,14 @@ void LoLEngine::runLoop() {
checkFloatingPointerRegions();
gui_updateInput();
+ if (_updateHandItemCursor) {
+ // This works around an issue which would occur when setHandItem(_itemInHand)
+ // was called from inside loadGameState(). When loading via GMM the
+ // mouse cursor would not be set correctly.
+ _updateHandItemCursor = false;
+ setHandItem(_itemInHand);
+ }
+
update();
if (_sceneUpdateRequired)
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 8372bf9ad1..9948c52001 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -102,7 +102,7 @@ protected:
enum KyraResources {
kLoadAll = -1,
- // This list has to match orderwise (and thus value wise) the static data list of "tools/create_kyradat/create_kyradat.h"!
+ // This list has to match orderwise (and thus value wise) the static data list of "devtools/create_kyradat/create_kyradat.h"!
k1ForestSeq = 1,
k1KallakWritingSeq,
k1KyrandiaLogoSeq,
diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp
index f26cb8fb26..1dc084f14d 100644
--- a/engines/kyra/resource_intern.cpp
+++ b/engines/kyra/resource_intern.cpp
@@ -356,7 +356,7 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
const uint32 magic = stream.readUint32BE();
- if (magic != MKID_BE('SCVM'))
+ if (magic != MKTAG('S','C','V','M'))
error("LINKLIST file does not contain 'SCVM' header");
const uint32 links = stream.readUint32BE();
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index cd5ef52b92..44579c3377 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -47,13 +47,13 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
header.flags = 0;
header.thumbnail = 0;
- if (type == MKID_BE('KYRA') || type == MKID_BE('ARYK')) { // old Kyra1 header ID
+ if (type == MKTAG('K','Y','R','A') || type == MKTAG('A','R','Y','K')) { // old Kyra1 header ID
header.gameID = GI_KYRA1;
header.oldHeader = true;
- } else if (type == MKID_BE('HOFS')) { // old Kyra2 header ID
+ } else if (type == MKTAG('H','O','F','S')) { // old Kyra2 header ID
header.gameID = GI_KYRA2;
header.oldHeader = true;
- } else if (type == MKID_BE('WWSV')) {
+ } else if (type == MKTAG('W','W','S','V')) {
header.gameID = in->readByte();
} else {
// try checking for original save header
@@ -71,12 +71,12 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
type = in->readUint32BE();
header.version = in->readUint16LE();
- if (type == MKID_BE('MBL3') && header.version == 100) {
+ if (type == MKTAG('M','B','L','3') && header.version == 100) {
saveOk = true;
header.description = descriptionBuffer;
header.gameID = GI_KYRA2;
break;
- } else if (type == MKID_BE('MBL4') && header.version == 102) {
+ } else if (type == MKTAG('M','B','L','4') && header.version == 102) {
saveOk = true;
header.description = descriptionBuffer;
header.gameID = GI_KYRA3;
@@ -94,7 +94,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
}
header.version = in->readUint32BE();
- if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKID_BE('ARYK') && header.version > 3))
+ if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKTAG('A','R','Y','K') && header.version > 3))
return kRSHEInvalidVersion;
// Versions prior to 9 are using a fixed length description field
@@ -190,7 +190,7 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con
}
// Savegame version
- out->writeUint32BE(MKID_BE('WWSV'));
+ out->writeUint32BE(MKTAG('W','W','S','V'));
out->writeByte(_flags.gameID);
out->writeUint32BE(CURRENT_SAVE_VERSION);
out->write(saveName, strlen(saveName)+1);
diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp
index ced103b7e3..7a487dcf7b 100644
--- a/engines/kyra/saveload_hof.cpp
+++ b/engines/kyra/saveload_hof.cpp
@@ -311,7 +311,7 @@ Common::Error KyraEngine_HoF::loadGameState(int slot) {
_mainCharacter.facing = 4;
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
- setHandItem(_itemInHand);
+ setDelayedCursorUpdate();
if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1)
snd_playWanderScoreViaMap(_lastMusicCommand, 1);
diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp
index 3e11d3dad3..012ff138b5 100644
--- a/engines/kyra/saveload_lok.cpp
+++ b/engines/kyra/saveload_lok.cpp
@@ -176,7 +176,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) {
_screen->copyRegion(8, 8, 8, 8, 304, 212, 10, 0);
}
- setHandItem(_itemInHand);
+ setDelayedCursorUpdate();
// Will-O-Wisp uses a different shape size than Brandon's usual
// shape, thus we need to setup the correct size depending on
diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp
index ee4fbf4dc1..b6c0693a16 100644
--- a/engines/kyra/saveload_lol.cpp
+++ b/engines/kyra/saveload_lol.cpp
@@ -263,7 +263,7 @@ Common::Error LoLEngine::loadGameState(int slot) {
int t = _credits;
_credits = 0;
giveCredits(t, 0);
- setHandItem(_itemInHand);
+ setDelayedCursorUpdate();
loadLevel(_currentLevel);
gui_drawPlayField();
timerSpecialCharacterUpdate(0);
diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp
index 7c583f95ee..a5e9b9e0f5 100644
--- a/engines/kyra/saveload_mr.cpp
+++ b/engines/kyra/saveload_mr.cpp
@@ -308,7 +308,7 @@ Common::Error KyraEngine_MR::loadGameState(int slot) {
_goodConsciencePosition = false;
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
- setHandItem(_itemInHand);
+ setDelayedCursorUpdate();
if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1)
snd_playWanderScoreViaMap(_lastMusicCommand, 1);
diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp
index f7ada5d623..3abfe03fff 100644
--- a/engines/kyra/scene_lok.cpp
+++ b/engines/kyra/scene_lok.cpp
@@ -314,38 +314,35 @@ void KyraEngine_LoK::setCharacterPositionHelper(int character, int *facingTable)
}
}
- static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
if (facing == 0) {
- ++facingIsZero[character];
+ ++_characterFacingZeroCount[character];
} else {
bool resetTables = false;
if (facing != 7) {
if (facing - 1 != 0) {
if (facing != 4) {
if (facing == 3 || facing == 5) {
- if (facingIsFour[character] > 2)
+ if (_characterFacingFourCount[character] > 2)
facing = 4;
resetTables = true;
}
} else {
- ++facingIsFour[character];
+ ++_characterFacingFourCount[character];
}
} else {
- if (facingIsZero[character] > 2)
+ if (_characterFacingZeroCount[character] > 2)
facing = 0;
resetTables = true;
}
} else {
- if (facingIsZero[character] > 2)
+ if (_characterFacingZeroCount[character] > 2)
facing = 0;
resetTables = true;
}
if (resetTables) {
- facingIsZero[character] = 0;
- facingIsFour[character] = 0;
+ _characterFacingZeroCount[character] = 0;
+ _characterFacingFourCount[character] = 0;
}
}
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index f1ea79f49b..acb0710616 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -36,20 +36,13 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
_screen->hideMouse();
showMessage(0, 0xF0, 0xF0);
- if (_inventoryState) {
+ if (_inventoryState)
hideInventory();
- musicUpdate(0);
- }
- musicUpdate(0);
if (_currentChapter != _currentTalkFile) {
_currentTalkFile = _currentChapter;
openTalkFile(_currentTalkFile);
}
- musicUpdate(0);
-
- if (!unk3)
- musicUpdate(0);
if (unk1) {
int x = _mainCharacter.x1;
@@ -73,11 +66,9 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
break;
}
- musicUpdate(0);
moveCharacter(facing, x, y);
}
- musicUpdate(0);
uint32 waitUntilTimer = 0;
if (_lastMusicCommand != _sceneList[sceneId].sound) {
fadeOutMusic(60);
@@ -89,33 +80,23 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
if (!unk3) {
_emc->init(&_sceneScriptState, &_sceneScriptData);
_emc->start(&_sceneScriptState, 5);
- while (_emc->isValid(&_sceneScriptState)) {
+ while (_emc->isValid(&_sceneScriptState))
_emc->run(&_sceneScriptState);
- musicUpdate(0);
- }
}
- musicUpdate(0);
-
_specialExitCount = 0;
Common::set_to(_specialExitTable, _specialExitTable+ARRAYSIZE(_specialExitTable), 0xFFFF);
- musicUpdate(0);
-
_mainCharacter.sceneId = sceneId;
_sceneList[sceneId].flags &= ~1;
- musicUpdate(0);
unloadScene();
- musicUpdate(0);
for (int i = 0; i < 4; ++i) {
if (i != _musicSoundChannel && i != _fadeOutMusicChannel)
_soundDigital->stopSound(i);
}
_fadeOutMusicChannel = -1;
- musicUpdate(0);
loadScenePal();
- musicUpdate(0);
if (queryGameFlag(0x1D9)) {
char filename[20];
@@ -141,9 +122,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
resetGameFlag(0x1D9);
}
- musicUpdate(0);
loadSceneMsc();
- musicUpdate(0);
_sceneExit1 = _sceneList[sceneId].exit1;
_sceneExit2 = _sceneList[sceneId].exit2;
_sceneExit3 = _sceneList[sceneId].exit3;
@@ -152,9 +131,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
while (_system->getMillis() < waitUntilTimer)
_system->delayMillis(10);
- musicUpdate(0);
initSceneScript(unk3);
- musicUpdate(0);
if (_overwriteSceneFacing) {
facing = _mainCharacter.facing;
@@ -162,7 +139,6 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
}
enterNewSceneUnk1(facing, unk2, unk3);
- musicUpdate(0);
setCommandLineRestoreTimer(-1);
_sceneScriptState.regs[3] = 1;
enterNewSceneUnk2(unk3);
@@ -306,13 +282,9 @@ void KyraEngine_MR::enterNewSceneUnk2(int unk1) {
void KyraEngine_MR::unloadScene() {
delete[] _sceneStrings;
_sceneStrings = 0;
- musicUpdate(0);
_emc->unload(&_sceneScriptData);
- musicUpdate(0);
freeSceneShapes();
- musicUpdate(0);
freeSceneAnims();
- musicUpdate(0);
}
void KyraEngine_MR::freeSceneShapes() {
@@ -356,13 +328,11 @@ void KyraEngine_MR::loadSceneMsc() {
height = stream->readSint16LE();
delete stream;
stream = 0;
- musicUpdate(0);
_maskPageMinY = minY;
_maskPageMaxY = minY + height - 1;
_screen->setShapePages(5, 3, _maskPageMinY, _maskPageMaxY);
- musicUpdate(0);
_screen->loadBitmap(filename, 5, 5, 0, true);
// HACK
@@ -372,12 +342,10 @@ void KyraEngine_MR::loadSceneMsc() {
_screen->copyBlockToPage(5, 0, _maskPageMinY, 320, height, data);
delete[] data;
- musicUpdate(0);
}
void KyraEngine_MR::initSceneScript(int unk1) {
const SceneDesc &scene = _sceneList[_mainCharacter.sceneId];
- musicUpdate(0);
char filename[16];
strcpy(filename, scene.filename1);
@@ -400,7 +368,6 @@ void KyraEngine_MR::initSceneScript(int unk1) {
if (shapesCount > 0) {
strcpy(filename, scene.filename1);
strcat(filename, "9.CPS");
- musicUpdate(0);
_screen->loadBitmap(filename, 3, 3, 0);
int pageBackUp = _screen->_curPage;
_screen->_curPage = 2;
@@ -413,19 +380,15 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_sceneShapeDescs[i].drawY = stream->readSint16LE();
_sceneShapes[i] = _screen->encodeShape(x, y, w, h, 0);
assert(_sceneShapes[i]);
- musicUpdate(0);
}
_screen->_curPage = pageBackUp;
- musicUpdate(0);
}
delete stream;
stream = 0;
- musicUpdate(0);
strcpy(filename, scene.filename1);
strcat(filename, ".CPS");
_screen->loadBitmap(filename, 3, 3, 0);
- musicUpdate(0);
Common::set_to(_specialSceneScriptState, _specialSceneScriptState+ARRAYSIZE(_specialSceneScriptState), false);
_sceneEnterX1 = 160;
@@ -442,14 +405,12 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_emc->init(&_sceneScriptState, &_sceneScriptData);
strcpy(filename, scene.filename2);
strcat(filename, ".EMC");
- musicUpdate(0);
_res->exists(filename, true);
_emc->load(filename, &_sceneScriptData, &_opcodes);
strcpy(filename, scene.filename2);
strcat(filename, ".");
loadLanguageFile(filename, _sceneStrings);
- musicUpdate(0);
runSceneScript8();
_emc->start(&_sceneScriptState, 0);
@@ -459,12 +420,10 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_emc->run(&_sceneScriptState);
_screen->copyRegionToBuffer(3, 0, 0, 320, 200, _gamePlayBuffer);
- musicUpdate(0);
for (int i = 0; i < 10; ++i) {
_emc->init(&_sceneSpecialScripts[i], &_sceneScriptData);
_emc->start(&_sceneSpecialScripts[i], i+9);
- musicUpdate(0);
_sceneSpecialScriptsTimer[i] = 0;
}
@@ -476,7 +435,6 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_sceneEnterY3 &= ~1;
_sceneEnterX4 &= ~3;
_sceneEnterY4 &= ~1;
- musicUpdate(0);
}
void KyraEngine_MR::initSceneAnims(int unk1) {
@@ -789,10 +747,8 @@ void KyraEngine_MR::runSceneScript4(int unk1) {
void KyraEngine_MR::runSceneScript8() {
_emc->start(&_sceneScriptState, 8);
- while (_emc->isValid(&_sceneScriptState)) {
- musicUpdate(0);
+ while (_emc->isValid(&_sceneScriptState))
_emc->run(&_sceneScriptState);
- }
}
bool KyraEngine_MR::lineIsPassable(int x, int y) {
diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp
index f0c26acd54..fdfbceb521 100644
--- a/engines/kyra/scene_v2.cpp
+++ b/engines/kyra/scene_v2.cpp
@@ -86,15 +86,16 @@ int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int m
x &= ~3; toX &= ~3;
y &= ~1; toY &= ~1;
int size = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize);
- static bool usePostProcess = false;
- if (size && !usePostProcess) {
- usePostProcess = true;
+
+ if (size && !_smoothingPath) {
+ _smoothingPath = true;
int temp = pathfinderInitPositionTable(moveTable);
temp = pathfinderInitPositionIndexTable(temp, x, y);
pathfinderFinializePath(moveTable, temp, x, y, moveTableSize);
- usePostProcess = false;
+ _smoothingPath = false;
}
- return usePostProcess ? size : getMoveTableSize(moveTable);
+
+ return _smoothingPath ? size : getMoveTableSize(moveTable);
}
bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) {
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index b8eac058fd..58d8e7f3d4 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -137,16 +137,15 @@ bool Screen::init() {
// We setup the PC98 text mode palette at [16, 24], since that will be used
// for KANJI characters in Lands of Lore.
if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) {
- uint8 palette[8 * 4];
+ uint8 palette[8 * 3];
for (int i = 0; i < 8; ++i) {
- palette[i * 4 + 0] = ((i >> 1) & 1) * 0xFF;
- palette[i * 4 + 1] = ((i >> 2) & 1) * 0xFF;
- palette[i * 4 + 2] = ((i >> 0) & 1) * 0xFF;
- palette[i * 4 + 3] = 0;
-
- _system->getPaletteManager()->setPalette(palette, 16, 8);
+ palette[i * 3 + 0] = ((i >> 1) & 1) * 0xFF;
+ palette[i * 3 + 1] = ((i >> 2) & 1) * 0xFF;
+ palette[i * 3 + 2] = ((i >> 0) & 1) * 0xFF;
}
+
+ _system->getPaletteManager()->setPalette(palette, 16, 8);
}
_curDim = 0;
@@ -180,7 +179,7 @@ bool Screen::enableScreenDebug(bool enable) {
}
void Screen::setResolution() {
- byte palette[4*256];
+ byte palette[3*256];
_system->getPaletteManager()->grabPalette(palette, 0, 256);
int width = 320, height = 200;
@@ -700,14 +699,13 @@ void Screen::getRealPalette(int num, uint8 *dst) {
}
void Screen::setScreenPalette(const Palette &pal) {
- uint8 screenPal[256 * 4];
+ uint8 screenPal[256 * 3];
_screenPalette->copy(pal);
for (int i = 0; i < pal.getNumColors(); ++i) {
- screenPal[4 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F;
- screenPal[4 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F;
- screenPal[4 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F;
- screenPal[4 * i + 3] = 0;
+ screenPal[3 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F;
+ screenPal[3 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F;
+ screenPal[3 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F;
}
_paletteChanged = true;
@@ -729,21 +727,20 @@ void Screen::setInterfacePalette(const Palette &pal, uint8 r, uint8 g, uint8 b)
if (!_isAmiga)
return;
- uint8 screenPal[32 * 4];
+ uint8 screenPal[32 * 3];
assert(32 <= pal.getNumColors());
for (int i = 0; i < pal.getNumColors(); ++i) {
if (i != 0x10) {
- screenPal[4 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F;
- screenPal[4 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F;
- screenPal[4 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F;
+ screenPal[3 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F;
+ screenPal[3 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F;
+ screenPal[3 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F;
} else {
- screenPal[4 * i + 0] = (r * 0xFF) / 0x3F;
- screenPal[4 * i + 1] = (g * 0xFF) / 0x3F;
- screenPal[4 * i + 2] = (b * 0xFF) / 0x3F;
+ screenPal[3 * i + 0] = (r * 0xFF) / 0x3F;
+ screenPal[3 * i + 1] = (g * 0xFF) / 0x3F;
+ screenPal[3 * i + 2] = (b * 0xFF) / 0x3F;
}
- screenPal[4 * i + 3] = 0;
}
_paletteChanged = true;
@@ -2378,7 +2375,7 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) {
if (flags & 1)
shapeSize += 16;
- static uint8 table[274];
+ uint8 table[274];
int tableIndex = 0;
uint8 *newShape = 0;
@@ -2400,7 +2397,7 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) {
byte *src = srcPtr;
if (flags & 1) {
dst += 16;
- memset(table, 0, sizeof(uint8)*274);
+ memset(table, 0, sizeof(table));
tableIndex = 1;
}
diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp
index da96ea6821..227349754f 100644
--- a/engines/kyra/screen_lok.cpp
+++ b/engines/kyra/screen_lok.cpp
@@ -447,12 +447,11 @@ void Screen_LoK_16::mergeOverlay(int x, int y, int w, int h) {
}
void Screen_LoK_16::set16ColorPalette(const uint8 *pal) {
- uint8 palette[16 * 4];
+ uint8 palette[16 * 3];
for (int i = 0; i < 16; ++i) {
- palette[i * 4 + 0] = (pal[i * 3 + 0] * 0xFF) / 0x0F;
- palette[i * 4 + 1] = (pal[i * 3 + 1] * 0xFF) / 0x0F;
- palette[i * 4 + 2] = (pal[i * 3 + 2] * 0xFF) / 0x0F;
- palette[i * 4 + 3] = 0;
+ palette[i * 3 + 0] = (pal[i * 3 + 0] * 0xFF) / 0x0F;
+ palette[i * 3 + 1] = (pal[i * 3 + 1] * 0xFF) / 0x0F;
+ palette[i * 3 + 2] = (pal[i * 3 + 2] * 0xFF) / 0x0F;
}
_system->getPaletteManager()->setPalette(palette, 0, 16);
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index e85ea13371..ff35facbb5 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -795,11 +795,10 @@ void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) {
uint8 *d = _screenPalette->getData() + dstColorIndex * 3;
memcpy(d, s, 3);
- uint8 ci[4];
+ uint8 ci[3];
ci[0] = (d[0] << 2) | (d[0] & 3);
ci[1] = (d[1] << 2) | (d[1] & 3);
ci[2] = (d[2] << 2) | (d[2] & 3);
- ci[3] = 0;
_system->getPaletteManager()->setPalette(ci, dstColorIndex, 1);
}
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index 0343cbfeae..956bf39b5a 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -68,14 +68,14 @@ EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm), _scriptData(0), _fi
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
_scriptData->text = new byte[chunk._size];
assert(_scriptData->text);
if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size)
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('ORDR'):
+ case MKTAG('O','R','D','R'):
_scriptData->ordr = new uint16[chunk._size >> 1];
assert(_scriptData->ordr);
if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size)
@@ -85,7 +85,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
_scriptData->data = new uint16[chunk._size >> 1];
assert(_scriptData->data);
if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size)
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 68620829bb..faa80a3f21 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -84,9 +84,9 @@ public:
// Both lead to some problems in our IFF parser, either reading after the end
// of file or producing a "Chunk overread" error message. To work around this
// we need to adjust the size field properly.
- if (_formType == MKID_BE('EMC2'))
+ if (_formType == MKTAG('E','M','C','2'))
_formChunk.size -= 8;
- else if (_formType == MKID_BE('AVFS'))
+ else if (_formType == MKTAG('A','V','F','S'))
_formChunk.size += 4;
}
};
diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp
index 5cd100b69c..18878b6543 100644
--- a/engines/kyra/script_mr.cpp
+++ b/engines/kyra/script_mr.cpp
@@ -857,8 +857,6 @@ int KyraEngine_MR::o3_defineSceneAnim(EMCState *script) {
const int animId = stackPos(0);
SceneAnim &anim = _sceneAnims[animId];
- musicUpdate(0);
-
uint16 flags = anim.flags = stackPos(1);
int x = anim.x = stackPos(2);
int y = anim.y = stackPos(3);
@@ -875,7 +873,6 @@ int KyraEngine_MR::o3_defineSceneAnim(EMCState *script) {
if (flags & 8) {
_sceneAnimMovie[animId]->open(filename, 1, 0);
- musicUpdate(0);
if (_sceneAnimMovie[animId]->opened()) {
anim.wsaFlag = 1;
if (x2 == -1)
@@ -900,8 +897,6 @@ int KyraEngine_MR::o3_defineSceneAnim(EMCState *script) {
}
}
- musicUpdate(0);
-
return 9;
}
@@ -1080,7 +1075,6 @@ int KyraEngine_MR::o3_setupSceneAnimObject(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_setupSceneAnimObject(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s)", (const void *)script,
stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9),
stackPos(10), stackPos(11), stackPosString(12));
- musicUpdate(0);
setupSceneAnimObject(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8),
stackPos(9), stackPos(10), stackPos(11), stackPosString(12));
return 0;
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 28f18a1f79..1e978caf15 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -115,14 +115,14 @@ TIMInterpreter::~TIMInterpreter() {
bool TIMInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
_tim->text = new byte[chunk._size];
assert(_tim->text);
if (chunk._stream->read(_tim->text, chunk._size) != chunk._size)
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('AVTL'):
+ case MKTAG('A','V','T','L'):
_avtlChunkSize = chunk._size >> 1;
_tim->avtl = new uint16[_avtlChunkSize];
assert(_tim->avtl);
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 441436a825..c55153b802 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -1216,7 +1216,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
int chatW = 0;
int chatFirstFrame = 0;
int chatLastFrame = 0;
- int textCol = 0;
+ //int textCol = 0;
uint16 voiceIndex = 0;
@@ -1257,13 +1257,13 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
if (_flags.isTalkie) {
chatX = 82;
- textCol = 143;
+ //textCol = 143;
chatFirstFrame = 16;
chatLastFrame = 21;
voiceIndex = 41;
} else {
chatX = 62;
- textCol = 137;
+ //textCol = 137;
chatFirstFrame = 9;
chatLastFrame = 13;
}
@@ -1281,7 +1281,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
if (frm == 16)
break;
chatX = 64;
- textCol = 137;
+ //textCol = 137;
chatFirstFrame = 9;
chatLastFrame = 13;
voiceIndex = 42;
@@ -1289,7 +1289,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
if (frm == 9)
break;
chatX = 80;
- textCol = 143;
+ //textCol = 143;
chatFirstFrame = 16;
chatLastFrame = 21;
}
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index c4bdc29f57..23af24064d 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -1483,53 +1483,49 @@ bool KyraEngine_LoK::seq_skipSequence() const {
}
int KyraEngine_LoK::handleMalcolmFlag() {
- static uint16 frame = 0;
- static uint32 timer1 = 0;
- static uint32 timer2 = 0;
-
switch (_malcolmFlag) {
case 1:
- frame = 0;
+ _malcolmFrame = 0;
_malcolmFlag = 2;
- timer2 = 0;
+ _malcolmTimer2 = 0;
// Fall through to the next case
case 2:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 13) {
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 13) {
_malcolmFlag = 3;
- timer1 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
}
}
break;
case 3:
- if (_system->getMillis() < timer1) {
- if (_system->getMillis() >= timer2) {
- frame = _rnd.getRandomNumberRng(14, 17);
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() < _malcolmTimer1) {
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _malcolmFrame = _rnd.getRandomNumberRng(14, 17);
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
}
} else {
_malcolmFlag = 4;
- frame = 18;
+ _malcolmFrame = 18;
}
break;
case 4:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 25) {
- frame = 26;
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 25) {
+ _malcolmFrame = 26;
_malcolmFlag = 5;
_beadStateVar = 1;
}
@@ -1537,13 +1533,13 @@ int KyraEngine_LoK::handleMalcolmFlag() {
break;
case 5:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 31) {
- frame = 32;
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 31) {
+ _malcolmFrame = 32;
_malcolmFlag = 6;
}
}
@@ -1551,14 +1547,14 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 6:
if (_unkEndSeqVar4) {
- if (frame <= 33 && _system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_malcolmFrame <= 33 && _system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 33) {
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 33) {
_malcolmFlag = 7;
- frame = 32;
+ _malcolmFrame = 32;
_unkEndSeqVar5 = 0;
}
}
@@ -1568,20 +1564,20 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 7:
if (_unkEndSeqVar5 == 1) {
_malcolmFlag = 8;
- frame = 34;
+ _malcolmFrame = 34;
} else if (_unkEndSeqVar5 == 2) {
_malcolmFlag = 3;
- timer1 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
}
break;
case 8:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 37) {
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 37) {
_malcolmFlag = 0;
_deathHandler = 8;
return 1;
@@ -1593,10 +1589,10 @@ int KyraEngine_LoK::handleMalcolmFlag() {
snd_playSoundEffect(12);
snd_playSoundEffect(12);
for (int i = 0; i < 18; ++i) {
- timer2 = _system->getMillis() + 4 * _tickLength;
+ _malcolmTimer2 = _system->getMillis() + 4 * _tickLength;
_finalC->displayFrame(i, 0, 16, 50, 0, 0, 0);
_screen->updateScreen();
- delayUntil(timer2);
+ delayUntil(_malcolmTimer2);
}
snd_playWanderScoreViaMap(51, 1);
delay(60 * _tickLength);
@@ -1609,16 +1605,16 @@ int KyraEngine_LoK::handleMalcolmFlag() {
_screen->bitBlitRects();
assert(_veryClever);
_text->printTalkTextMessage(_veryClever[0], 60, 31, 5, 0, 2);
- timer2 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer2 = _system->getMillis() + 180 * _tickLength;
_malcolmFlag = 11;
}
break;
case 11:
- if (_system->getMillis() >= timer2) {
+ if (_system->getMillis() >= _malcolmTimer2) {
_text->restoreTalkTextMessageBkgd(2, 0);
_malcolmFlag = 3;
- timer1 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
}
break;
@@ -1630,16 +1626,12 @@ int KyraEngine_LoK::handleMalcolmFlag() {
}
int KyraEngine_LoK::handleBeadState() {
- static uint32 timer1 = 0;
- static uint32 timer2 = 0;
- static BeadState beadState1 = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static BeadState beadState2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
static const int table1[] = {
-1, -2, -4, -5, -6, -7, -6, -5,
-4, -2, -1, 0, 1, 2, 4, 5,
6, 7, 6, 5, 4, 2, 1, 0, 0
};
+
static const int table2[] = {
0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 5, 5, 4, 4,
@@ -1651,120 +1643,120 @@ int KyraEngine_LoK::handleBeadState() {
switch (_beadStateVar) {
case 0:
- if (beadState1.x != -1 && _endSequenceBackUpRect) {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ if (_beadState1.x != -1 && _endSequenceBackUpRect) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
- beadState1.x = -1;
- beadState1.tableIndex = 0;
- timer1 = 0;
- timer2 = 0;
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
+ _beadStateTimer1 = 0;
+ _beadStateTimer2 = 0;
_lastDisplayedPanPage = 0;
return 1;
case 1:
- if (beadState1.x != -1) {
+ if (_beadState1.x != -1) {
if (_endSequenceBackUpRect) {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
- beadState1.x = -1;
- beadState1.tableIndex = 0;
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
}
_beadStateVar = 2;
break;
case 2:
- if (_system->getMillis() >= timer1) {
+ if (_system->getMillis() >= _beadStateTimer1) {
int x = 0, y = 0;
- timer1 = _system->getMillis() + 4 * _tickLength;
- if (beadState1.x == -1) {
+ _beadStateTimer1 = _system->getMillis() + 4 * _tickLength;
+ if (_beadState1.x == -1) {
assert(_panPagesTable);
- beadState1.width2 = _animator->fetchAnimWidth(_panPagesTable[19], 256);
- beadState1.width = ((beadState1.width2 + 7) >> 3) + 1;
- beadState1.height = _animator->fetchAnimHeight(_panPagesTable[19], 256);
+ _beadState1.width2 = _animator->fetchAnimWidth(_panPagesTable[19], 256);
+ _beadState1.width = ((_beadState1.width2 + 7) >> 3) + 1;
+ _beadState1.height = _animator->fetchAnimHeight(_panPagesTable[19], 256);
if (!_endSequenceBackUpRect) {
- _endSequenceBackUpRect = new uint8[(beadState1.width * beadState1.height) << 3];
+ _endSequenceBackUpRect = new uint8[(_beadState1.width * _beadState1.height) << 3];
assert(_endSequenceBackUpRect);
- memset(_endSequenceBackUpRect, 0, ((beadState1.width * beadState1.height) << 3) * sizeof(uint8));
+ memset(_endSequenceBackUpRect, 0, ((_beadState1.width * _beadState1.height) << 3) * sizeof(uint8));
}
- x = beadState1.x = 60;
- y = beadState1.y = 40;
- initBeadState(x, y, x, 25, 8, &beadState2);
+ x = _beadState1.x = 60;
+ y = _beadState1.y = 40;
+ initBeadState(x, y, x, 25, 8, &_beadState2);
} else {
- if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
_beadStateVar = 3;
- timer2 = _system->getMillis() + 240 * _tickLength;
+ _beadStateTimer2 = _system->getMillis() + 240 * _tickLength;
_unkEndSeqVar4 = 0;
- beadState1.dstX = beadState1.x;
- beadState1.dstY = beadState1.y;
+ _beadState1.dstX = _beadState1.x;
+ _beadState1.dstY = _beadState1.y;
return 0;
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = x;
- beadState1.y = y;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
}
}
- _screen->copyRegionToBuffer(_screen->_curPage, x, y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyRegionToBuffer(_screen->_curPage, x, y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17)
_lastDisplayedPanPage = 0;
- _screen->addBitBlitRect(x, y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(x, y, _beadState1.width2, _beadState1.height);
}
break;
case 3:
- if (_system->getMillis() >= timer1) {
- timer1 = _system->getMillis() + 4 * _tickLength;
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ if (_system->getMillis() >= _beadStateTimer1) {
+ _beadStateTimer1 = _system->getMillis() + 4 * _tickLength;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
- beadState1.x = beadState1.dstX + table1[beadState1.tableIndex];
- beadState1.y = beadState1.dstY + table2[beadState1.tableIndex];
- _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _beadState1.x = _beadState1.dstX + table1[_beadState1.tableIndex];
+ _beadState1.y = _beadState1.dstY + table2[_beadState1.tableIndex];
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
- _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], beadState1.x, beadState1.y, 0, 0);
+ _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], _beadState1.x, _beadState1.y, 0, 0);
if (_lastDisplayedPanPage >= 17)
_lastDisplayedPanPage = 0;
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
- ++beadState1.tableIndex;
- if (beadState1.tableIndex > 24)
- beadState1.tableIndex = 0;
+ ++_beadState1.tableIndex;
+ if (_beadState1.tableIndex > 24)
+ _beadState1.tableIndex = 0;
_unkEndSeqVar4 = 1;
- if (_system->getMillis() > timer2 && _malcolmFlag == 7 && !_unkAmuletVar && !_text->printed()) {
+ if (_system->getMillis() > _beadStateTimer2 && _malcolmFlag == 7 && !_unkAmuletVar && !_text->printed()) {
snd_playSoundEffect(0x0B);
if (_currentCharacter->x1 > 233 && _currentCharacter->x1 < 305 && _currentCharacter->y1 > 85 && _currentCharacter->y1 < 105 &&
(_brandonStatusBit & 0x20)) {
- beadState1.unk8 = 290;
- beadState1.unk9 = 40;
+ _beadState1.unk8 = 290;
+ _beadState1.unk9 = 40;
_beadStateVar = 5;
} else {
_beadStateVar = 4;
- beadState1.unk8 = _currentCharacter->x1 - 4;
- beadState1.unk9 = _currentCharacter->y1 - 30;
+ _beadState1.unk8 = _currentCharacter->x1 - 4;
+ _beadState1.unk9 = _currentCharacter->y1 - 30;
}
if (_text->printed())
_text->restoreTalkTextMessageBkgd(2, 0);
- initBeadState(beadState1.x, beadState1.y, beadState1.unk8, beadState1.unk9, 12, &beadState2);
+ initBeadState(_beadState1.x, _beadState1.y, _beadState1.unk8, _beadState1.unk9, 12, &_beadState2);
_lastDisplayedPanPage = 18;
}
}
break;
case 4:
- if (_system->getMillis() >= timer1) {
+ if (_system->getMillis() >= _beadStateTimer1) {
int x = 0, y = 0;
- timer1 = _system->getMillis() + _tickLength;
- if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
+ _beadStateTimer1 = _system->getMillis() + _tickLength;
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
if (_brandonStatusBit & 20) {
_unkEndSeqVar5 = 2;
_beadStateVar = 6;
@@ -1775,27 +1767,27 @@ int KyraEngine_LoK::handleBeadState() {
_beadStateVar = 0;
}
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = x;
- beadState1.y = y;
- _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17) {
_lastDisplayedPanPage = 0;
}
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
}
break;
case 5:
- if (_system->getMillis() >= timer1) {
- timer1 = _system->getMillis() + _tickLength;
+ if (_system->getMillis() >= _beadStateTimer1) {
+ _beadStateTimer1 = _system->getMillis() + _tickLength;
int x = 0, y = 0;
- if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
- if (beadState2.dstX == 290) {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
+ if (_beadState2.dstX == 290) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
uint32 nextRun = 0;
for (int i = 0; i < 8; ++i) {
nextRun = _system->getMillis() + _tickLength;
@@ -1810,38 +1802,39 @@ int KyraEngine_LoK::handleBeadState() {
_screen->updateScreen();
delayUntil(nextRun);
}
- initBeadState(beadState1.x, beadState1.y, 63, 60, 12, &beadState2);
+ initBeadState(_beadState1.x, _beadState1.y, 63, 60, 12, &_beadState2);
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = -1;
- beadState1.tableIndex = 0;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
_beadStateVar = 0;
_malcolmFlag = 9;
}
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = x;
- beadState1.y = y;
- _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17)
_lastDisplayedPanPage = 0;
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
}
break;
case 6:
- _screen->drawShape(2, _panPagesTable[19], beadState1.x, beadState1.y, 0, 0);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->drawShape(2, _panPagesTable[19], _beadState1.x, _beadState1.y, 0, 0);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
_beadStateVar = 0;
break;
default:
break;
}
+
return 0;
}
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index 7b33fc218c..354f5732bf 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -219,12 +219,12 @@ public:
~MidiDriver_PCSpeaker();
// MidiDriver interface
- void close() {}
+ virtual void close() {}
- void send(uint32 data);
+ virtual void send(uint32 data);
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ virtual MidiChannel *allocateChannel() { return 0; }
+ virtual MidiChannel *getPercussionChannel() { return 0; }
// MidiDriver_Emulated interface
void generateSamples(int16 *buffer, int numSamples);
diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
index cd5af12106..02ba735a70 100644
--- a/engines/kyra/sound_midi.cpp
+++ b/engines/kyra/sound_midi.cpp
@@ -33,7 +33,7 @@
namespace Kyra {
-class MidiOutput : public MidiDriver {
+class MidiOutput : public MidiDriver_BASE {
public:
MidiOutput(OSystem *system, MidiDriver *output, bool isMT32, bool defaultMT32);
~MidiOutput();
@@ -46,19 +46,16 @@ public:
void setSoundSource(int source) { _curSource = source; }
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
- void metaEvent(byte type, byte *data, uint16 length);
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
+ virtual void sysEx(const byte *msg, uint16 length);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
+ // TODO: Get rid of the following two methods
void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _output->setTimerCallback(timerParam, timerProc); }
uint32 getBaseTempo() { return _output->getBaseTempo(); }
- // DUMMY
- int open() { return 0; }
- void close() {}
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
private:
void sendIntern(const byte event, const byte channel, byte param1, const byte param2);
void sendSysEx(const byte p1, const byte p2, const byte p3, const byte *buffer, const int size);
@@ -265,7 +262,7 @@ void MidiOutput::sendIntern(const byte event, const byte channel, byte param1, c
if (event == 0xC0) {
// MT32 -> GM conversion
if (!_isMT32 && _defaultMT32)
- param1 = _mt32ToGm[param1];
+ param1 = MidiDriver::_mt32ToGm[param1];
}
_output->send(event | channel, param1, param2);
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index 98c6ef3130..001faab016 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -340,10 +340,8 @@ void KyraEngine_MR::objectChatWaitToFinish() {
_emc->start(&_chatScriptState, 1);
_animNeedUpdate = false;
- while (!_animNeedUpdate && _emc->isValid(&_chatScriptState) && !shouldQuit()) {
- musicUpdate(0);
+ while (!_animNeedUpdate && _emc->isValid(&_chatScriptState) && !shouldQuit())
_emc->run(&_chatScriptState);
- }
int curFrame = _animNewFrame;
uint32 delayTime = _animDelayTime;
diff --git a/engines/kyra/timer_lok.cpp b/engines/kyra/timer_lok.cpp
index 6f4948c279..85b98be724 100644
--- a/engines/kyra/timer_lok.cpp
+++ b/engines/kyra/timer_lok.cpp
@@ -75,7 +75,6 @@ void KyraEngine_LoK::setupTimers() {
}
void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) {
- static int8 currentFrame = 0;
static const int8 frameTable[] = {
4, 5, 4, 5, 4, 5, 0, 1,
4, 5, 4, 4, 6, 4, 8, 1,
@@ -85,11 +84,11 @@ void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) {
if (_talkingCharNum < 0)
return;
- _currHeadShape = frameTable[currentFrame];
- currentFrame++;
+ _currHeadShape = frameTable[_currentHeadFrameTableIndex];
+ ++_currentHeadFrameTableIndex;
- if (frameTable[currentFrame] == -1)
- currentFrame = 0;
+ if (frameTable[_currentHeadFrameTableIndex] == -1)
+ _currentHeadFrameTableIndex = 0;
_animator->animRefreshNPC(0);
_animator->animRefreshNPC(_talkingCharNum);
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index 382ec2429d..b3371793de 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -204,7 +204,7 @@ bool VQAMovie::open(const char *filename) {
if (!_file)
return false;
- if (_file->readUint32BE() != MKID_BE('FORM')) {
+ if (_file->readUint32BE() != MKTAG('F','O','R','M')) {
warning("VQAMovie::open: Cannot find `FORM' tag");
return false;
}
@@ -212,7 +212,7 @@ bool VQAMovie::open(const char *filename) {
// For now, we ignore the size of the FORM chunk.
_file->readUint32BE();
- if (_file->readUint32BE() != MKID_BE('WVQA')) {
+ if (_file->readUint32BE() != MKTAG('W','V','Q','A')) {
warning("WQAMovie::open: Cannot find `WVQA' tag");
return false;
}
@@ -228,7 +228,7 @@ bool VQAMovie::open(const char *filename) {
uint32 size = _file->readUint32BE();
switch (tag) {
- case MKID_BE('VQHD'): // VQA header
+ case MKTAG('V','Q','H','D'): // VQA header
_header.version = _file->readUint16LE();
_header.flags = _file->readUint16LE();
_header.numFrames = _file->readUint16LE();
@@ -304,7 +304,7 @@ bool VQAMovie::open(const char *filename) {
foundHeader = true;
break;
- case MKID_BE('FINF'): // Frame info
+ case MKTAG('F','I','N','F'): // Frame info
if (!foundHeader) {
warning("VQAMovie::open: Found `FINF' before `VQHD'");
return false;
@@ -343,7 +343,7 @@ bool VQAMovie::open(const char *filename) {
if (_file->eos())
break;
- if (scanTag == MKID_BE('VQFR')) {
+ if (scanTag == MKTAG('V','Q','F','R')) {
_frameInfo[0] = (_file->pos() - 8) | 0x80000000;
break;
}
@@ -421,7 +421,7 @@ void VQAMovie::displayFrame(uint frameNum) {
int32 end;
switch (tag) {
- case MKID_BE('SND0'): // Uncompressed sound
+ case MKTAG('S','N','D','0'): // Uncompressed sound
foundSound = true;
inbuf = (byte *)malloc(size);
_file->read(inbuf, size);
@@ -429,7 +429,7 @@ void VQAMovie::displayFrame(uint frameNum) {
_stream->queueBuffer(inbuf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
break;
- case MKID_BE('SND1'): // Compressed sound, almost like AUD
+ case MKTAG('S','N','D','1'): // Compressed sound, almost like AUD
foundSound = true;
outsize = _file->readUint16LE();
insize = _file->readUint16LE();
@@ -449,13 +449,13 @@ void VQAMovie::displayFrame(uint frameNum) {
}
break;
- case MKID_BE('SND2'): // Compressed sound
+ case MKTAG('S','N','D','2'): // Compressed sound
foundSound = true;
warning("VQAMovie::displayFrame: `SND2' is not implemented");
_file->seek(size, SEEK_CUR);
break;
- case MKID_BE('VQFR'):
+ case MKTAG('V','Q','F','R'):
foundFrame = true;
end = _file->pos() + size - 8;
@@ -464,49 +464,49 @@ void VQAMovie::displayFrame(uint frameNum) {
size = _file->readUint32BE();
switch (tag) {
- case MKID_BE('CBF0'): // Full codebook
+ case MKTAG('C','B','F','0'): // Full codebook
_file->read(_codeBook, size);
break;
- case MKID_BE('CBFZ'): // Full codebook
+ case MKTAG('C','B','F','Z'): // Full codebook
inbuf = (byte *)allocBuffer(0, size);
_file->read(inbuf, size);
Screen::decodeFrame4(inbuf, _codeBook, _codeBookSize);
break;
- case MKID_BE('CBP0'): // Partial codebook
+ case MKTAG('C','B','P','0'): // Partial codebook
_compressedCodeBook = false;
_file->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
- case MKID_BE('CBPZ'): // Partial codebook
+ case MKTAG('C','B','P','Z'): // Partial codebook
_compressedCodeBook = true;
_file->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
- case MKID_BE('CPL0'): // Palette
+ case MKTAG('C','P','L','0'): // Palette
assert(size <= 3 * 256);
_file->read(_screen->getPalette(0).getData(), size);
break;
- case MKID_BE('CPLZ'): // Palette
+ case MKTAG('C','P','L','Z'): // Palette
inbuf = (byte *)allocBuffer(0, size);
_file->read(inbuf, size);
Screen::decodeFrame4(inbuf, _screen->getPalette(0).getData(), 768);
break;
- case MKID_BE('VPT0'): // Frame data
+ case MKTAG('V','P','T','0'): // Frame data
assert(size / 2 <= _numVectorPointers);
for (i = 0; i < size / 2; i++)
_vectorPointers[i] = _file->readUint16LE();
break;
- case MKID_BE('VPTZ'): // Frame data
+ case MKTAG('V','P','T','Z'): // Frame data
inbuf = (byte *)allocBuffer(0, size);
outbuf = (byte *)allocBuffer(1, 2 * _numVectorPointers);
@@ -613,13 +613,13 @@ void VQAMovie::play() {
}
switch (tag) {
- case MKID_BE('SND0'): // Uncompressed sound
+ case MKTAG('S','N','D','0'): // Uncompressed sound
inbuf = (byte *)malloc(size);
_file->read(inbuf, size);
_stream->queueBuffer(inbuf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
break;
- case MKID_BE('SND1'): // Compressed sound
+ case MKTAG('S','N','D','1'): // Compressed sound
outsize = _file->readUint16LE();
insize = _file->readUint16LE();
@@ -636,12 +636,12 @@ void VQAMovie::play() {
}
break;
- case MKID_BE('SND2'): // Compressed sound
+ case MKTAG('S','N','D','2'): // Compressed sound
warning("VQAMovie::play: `SND2' is not implemented");
_file->seek(size, SEEK_CUR);
break;
- case MKID_BE('CMDS'): // Unused tag, always empty in kyra3
+ case MKTAG('C','M','D','S'): // Unused tag, always empty in kyra3
_file->seek(size, SEEK_CUR);
break;
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index ad6e5f2a24..7c08fef627 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -56,6 +56,8 @@ LastExpressEngine::LastExpressEngine(OSystem *syst, const ADGameDescription *gd)
_font(NULL), _logic(NULL), _menu(NULL), _frameCounter(0), _lastFrameCount(0),
_graphicsMan(NULL), _resMan(NULL), _sceneMan(NULL), _soundMan(NULL),
_eventMouse(NULL), _eventTick(NULL), _eventMouseBackup(NULL), _eventTickBackup(NULL) {
+ // Setup mixer
+ syncSoundSettings();
// Adding the default directories
const Common::FSNode gameDataDir(ConfMan.get("path"));
@@ -139,7 +141,7 @@ Common::Error LastExpressEngine::run() {
// Start sound manager and setup timer
_soundMan = new SoundManager(this);
- _timer->installTimerProc(&soundTimer, 17, this);
+ _timer->installTimerProc(&soundTimer, 17000, this);
// Menu
_menu = new Menu(this);
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index ca102e237c..b0968c1956 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -95,6 +95,10 @@ Common::Error LureEngine::init() {
_gameToLoad = -1;
_initialised = true;
+
+ // Setup mixer
+ syncSoundSettings();
+
return Common::kNoError;
}
@@ -264,6 +268,8 @@ GUI::Debugger *LureEngine::getDebugger() {
}
void LureEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
Sound.syncSounds();
}
diff --git a/engines/lure/screen.cpp b/engines/lure/screen.cpp
index d00d969770..282e382bba 100644
--- a/engines/lure/screen.cpp
+++ b/engines/lure/screen.cpp
@@ -52,12 +52,26 @@ Screen::~Screen() {
delete _palette;
}
+void Screen::setSystemPalette(Palette *p, uint16 start, uint16 num) {
+ byte pal[3 * 256];
+ assert(start + num <= 256);
+
+ const byte *rawData = p->data();
+ for (uint i = 0; i < num; ++i) {
+ pal[i * 3 + 0] = rawData[(i + start) * 4 + 0];
+ pal[i * 3 + 1] = rawData[(i + start) * 4 + 1];
+ pal[i * 3 + 2] = rawData[(i + start) * 4 + 2];
+ }
+
+ _system.getPaletteManager()->setPalette(pal, start, num);
+}
+
// setPaletteEmpty
// Defaults the palette to an empty set
void Screen::setPaletteEmpty(int numEntries) {
Palette emptyPalette(numEntries, NULL, RGB64);
- _system.getPaletteManager()->setPalette(emptyPalette.data(), 0, numEntries);
+ setSystemPalette(&emptyPalette, 0, numEntries);
_palette->copyFrom(&emptyPalette);
/*
delete _palette;
@@ -73,7 +87,7 @@ void Screen::setPaletteEmpty(int numEntries) {
void Screen::setPalette(Palette *p) {
_palette->copyFrom(p);
- _system.getPaletteManager()->setPalette(_palette->data(), 0, GAME_COLOURS);
+ setSystemPalette(_palette, 0, GAME_COLOURS);
_system.updateScreen();
}
@@ -82,7 +96,7 @@ void Screen::setPalette(Palette *p) {
void Screen::setPalette(Palette *p, uint16 start, uint16 num) {
_palette->palette()->copyFrom(p->palette(), start * 4, start * 4, num * 4);
- _system.getPaletteManager()->setPalette(_palette->data(), start, num);
+ setSystemPalette(_palette, start, num);
_system.updateScreen();
}
@@ -114,7 +128,7 @@ void Screen::paletteFadeIn(Palette *p) {
}
if (changed) {
- _system.getPaletteManager()->setPalette(_palette->data(), 0, p->numEntries());
+ setSystemPalette(_palette, 0, p->numEntries());
_system.updateScreen();
_system.delayMillis(20);
while (events.pollEvent())
@@ -147,7 +161,7 @@ void Screen::paletteFadeOut(int numEntries) {
}
if (changed) {
- _system.getPaletteManager()->setPalette(_palette->data(), 0, numEntries);
+ setSystemPalette(_palette, 0, numEntries);
_system.updateScreen();
_system.delayMillis(20);
while (events.pollEvent())
diff --git a/engines/lure/screen.h b/engines/lure/screen.h
index 373683df2b..94bbab932e 100644
--- a/engines/lure/screen.h
+++ b/engines/lure/screen.h
@@ -42,6 +42,8 @@ private:
Disk &_disk;
Surface *_screen;
Palette *_palette;
+
+ void setSystemPalette(Palette *p, uint16 start, uint16 num);
public:
Screen(OSystem &system);
~Screen();
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 5f954eb337..da9e136ec3 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -97,8 +97,8 @@ SoundManager::~SoundManager() {
if (_driver) {
_driver->close();
delete _driver;
+ _driver = NULL;
}
- _driver = NULL;
g_system->deleteMutex(_soundMutex);
}
@@ -597,6 +597,7 @@ void SoundManager::doTimer() {
MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size) {
_driver = driver;
+ assert(_driver);
_channels = channels;
_soundNumber = soundNum;
_channelNumber = channelNum;
@@ -614,15 +615,11 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
else
setVolume(Sound.sfxVolume());
- _passThrough = false;
-
_parser = MidiParser::createParser_SMF();
_parser->setMidiDriver(this);
_parser->setTimerRate(_driver->getBaseTempo());
- this->open();
-
- _soundData = (uint8 *) soundData;
+ _soundData = (uint8 *)soundData;
_soundSize = size;
// Check whether the music data is compressed - if so, decompress it for the duration
@@ -654,7 +651,6 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
MidiMusic::~MidiMusic() {
_parser->unloadMusic();
delete _parser;
- this->close();
delete _decompressedSound;
}
@@ -686,23 +682,7 @@ void MidiMusic::playMusic() {
_isPlaying = true;
}
-int MidiMusic::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- return 0;
-}
-
-void MidiMusic::close() {
-}
-
void MidiMusic::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
#ifdef SOUND_CROP_CHANNELS
if ((b & 0xF) >= _numChannels) return;
byte channel = _channelNumber + (byte)(b & 0x0F);
@@ -749,7 +729,6 @@ void MidiMusic::stopMusic() {
debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::stopMusic sound %d", _soundNumber);
_isPlaying = false;
_parser->unloadMusic();
- close();
}
} // End of namespace Lure
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index f50748ab0a..dd5538085c 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -46,7 +46,7 @@ struct ChannelEntry {
uint8 volume;
};
-class MidiMusic: public MidiDriver {
+class MidiMusic: public MidiDriver_BASE {
private:
uint8 _soundNumber;
uint8 _channelNumber;
@@ -66,14 +66,12 @@ private:
uint32 songOffset(uint16 songNum) const;
uint32 songLength(uint16 songNum) const;
- bool _passThrough;
-
public:
MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size);
~MidiMusic();
void setVolume(int volume);
- int getVolume() { return _volume; }
+ int getVolume() const { return _volume; }
void playSong(uint16 songNum);
void stopSong() { stopMusic(); }
@@ -81,28 +79,18 @@ public:
void stopMusic();
void queueTuneList(int16 tuneList);
bool queueSong(uint16 songNum);
- void setPassThrough(bool b) { _passThrough = b; }
void toggleVChange();
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
- void onTimer();
-
- void metaEvent(byte type, byte *data, uint16 length);
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ void onTimer();
- uint8 channelNumber() { return _channelNumber; }
- uint8 soundNumber() { return _soundNumber; }
- bool isPlaying() { return _isPlaying; }
- bool isMusic() {return _isMusic; }
+ uint8 channelNumber() const { return _channelNumber; }
+ uint8 soundNumber() const { return _soundNumber; }
+ bool isPlaying() const { return _isPlaying; }
+ bool isMusic() const { return _isMusic; }
};
class SoundManager : public Common::Singleton<SoundManager> {
diff --git a/engines/m4/assets.h b/engines/m4/assets.h
index 3ae7fb2e22..940646b5f2 100644
--- a/engines/m4/assets.h
+++ b/engines/m4/assets.h
@@ -33,16 +33,16 @@
namespace M4 {
// Sequence chunks
-#define CHUNK_SCEN MKID_BE('SCEN')
-#define CHUNK_MACH MKID_BE('MACH')
-#define CHUNK_SEQU MKID_BE('SEQU')
-#define CHUNK_DATA MKID_BE('DATA')
-#define CHUNK_CELS MKID_BE('CELS')
+#define CHUNK_SCEN MKTAG('S','C','E','N')
+#define CHUNK_MACH MKTAG('M','A','C','H')
+#define CHUNK_SEQU MKTAG('S','E','Q','U')
+#define CHUNK_DATA MKTAG('D','A','T','A')
+#define CHUNK_CELS MKTAG('C','E','L','S')
// Sprite chunks
-#define HEAD_M4SS MKID_BE('M4SS') //'M4SS'
-#define CELS__PAL MKID_BE(' PAL') //' PAL'
-#define CELS___SS MKID_BE(' SS') //' SS'
+#define HEAD_M4SS MKTAG('M','4','S','S') //'M4SS'
+#define CELS__PAL MKTAG(' ','P','A','L') //' PAL'
+#define CELS___SS MKTAG(' ',' ','S','S') //' SS'
#define SPRITE_SET_CHAR_INFO 4
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index 70c30d28f2..2d1b8e7e4f 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -45,35 +45,35 @@ namespace M4 {
// Conversation chunks
// Header
-#define HEAD_CONV MKID_BE('CONV') // conversation
-#define CHUNK_DECL MKID_BE('DECL') // declaration
-#define CHUNK_NODE MKID_BE('NODE') // node
-#define CHUNK_LNOD MKID_BE('LNOD') // linear node
-#define CHUNK_ETRY MKID_BE('ETRY') // entry
-#define CHUNK_TEXT MKID_BE('TEXT') // text
-#define CHUNK_MESG MKID_BE('MESG') // message
+#define HEAD_CONV MKTAG('C','O','N','V') // conversation
+#define CHUNK_DECL MKTAG('D','E','C','L') // declaration
+#define CHUNK_NODE MKTAG('N','O','D','E') // node
+#define CHUNK_LNOD MKTAG('L','N','O','D') // linear node
+#define CHUNK_ETRY MKTAG('E','T','R','Y') // entry
+#define CHUNK_TEXT MKTAG('T','E','X','T') // text
+#define CHUNK_MESG MKTAG('M','E','S','G') // message
// Conversation chunks - entry related (unconditional)
-#define CHUNK_RPLY MKID_BE('RPLY') // reply
-#define CHUNK_HIDE MKID_BE('HIDE') // hide entry
-#define CHUNK_UHID MKID_BE('UHID') // unhide entry
-#define CHUNK_DSTR MKID_BE('DSTR') // destroy entry
+#define CHUNK_RPLY MKTAG('R','P','L','Y') // reply
+#define CHUNK_HIDE MKTAG('H','I','D','E') // hide entry
+#define CHUNK_UHID MKTAG('U','H','I','D') // unhide entry
+#define CHUNK_DSTR MKTAG('D','S','T','R') // destroy entry
// Conversation chunks - entry related (conditional)
-#define CHUNK_CRPL MKID_BE('CRPL') // reply
-#define CHUNK_CHDE MKID_BE('CHDE') // hide entry
-#define CHUNK_CUHD MKID_BE('CUHD') // unhide entry
-#define CHUNK_CDST MKID_BE('DDTS') // destroy entry
+#define CHUNK_CRPL MKTAG('C','R','P','L') // reply
+#define CHUNK_CHDE MKTAG('C','H','D','E') // hide entry
+#define CHUNK_CUHD MKTAG('C','U','H','D') // unhide entry
+#define CHUNK_CDST MKTAG('D','D','T','S') // destroy entry
// Conversation chunks - branching and logic (unconditional)
-#define CHUNK_ASGN MKID_BE('ASGN') // assign
-#define CHUNK_GOTO MKID_BE('GOTO') // goto chunk
-#define CHUNK_EXIT MKID_BE('EXIT') // exit/return from goto
+#define CHUNK_ASGN MKTAG('A','S','G','N') // assign
+#define CHUNK_GOTO MKTAG('G','O','T','O') // goto chunk
+#define CHUNK_EXIT MKTAG('E','X','I','T') // exit/return from goto
// Conversation chunks - branching and logic (conditional)
-#define CHUNK_CASN MKID_BE('CASN') // assign
-#define CHUNK_CCGO MKID_BE('CCGO') // goto chunk
-#define CHUNK_CEGO MKID_BE('CEGO') // exit/return from goto
+#define CHUNK_CASN MKTAG('C','A','S','N') // assign
+#define CHUNK_CCGO MKTAG('C','C','G','O') // goto chunk
+#define CHUNK_CEGO MKTAG('C','E','G','O') // exit/return from goto
// Others
-#define CHUNK_FALL MKID_BE('FALL') // fallthrough
-#define CHUNK_WRPL MKID_BE('WRPL') // weighted reply chunk
-#define CHUNK_WPRL MKID_BE('WPRL') // weighted preply chunk
+#define CHUNK_FALL MKTAG('F','A','L','L') // fallthrough
+#define CHUNK_WRPL MKTAG('W','R','P','L') // weighted reply chunk
+#define CHUNK_WPRL MKTAG('W','P','R','L') // weighted preply chunk
ConversationView::ConversationView(MadsM4Engine *vm): View(vm, Common::Rect(0,
diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp
index 101f21f48c..da828ccf5b 100644
--- a/engines/m4/dialogs.cpp
+++ b/engines/m4/dialogs.cpp
@@ -43,8 +43,8 @@ static void strToLower(char *s) {
}
const RGB8 DIALOG_PALETTE[8] = {
- {0x80, 0x80, 0x80, 0xff}, {0x90, 0x90, 0x90, 0xff}, {0x70, 0x70, 0x70, 0xff}, {0x9c, 0x9c, 0x9c, 0xff},
- {0x80, 0x80, 0x80, 0xff}, {0x90, 0x90, 0x90, 0xff}, {0xDC, 0xDC, 0xDC, 0xff}, {0x00, 0x00, 0x00, 0xff}
+ {0x80, 0x80, 0x80}, {0x90, 0x90, 0x90}, {0x70, 0x70, 0x70}, {0x9c, 0x9c, 0x9c},
+ {0x80, 0x80, 0x80}, {0x90, 0x90, 0x90}, {0xDC, 0xDC, 0xDC}, {0x00, 0x00, 0x00}
};
#define ROR16(v,amt) (((uint16)(v) >> amt) | ((uint16)(v) << (16 - amt)))
diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp
index cba32c2225..3ed419675d 100644
--- a/engines/m4/font.cpp
+++ b/engines/m4/font.cpp
@@ -81,7 +81,7 @@ Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) {
void Font::setFontM4(const char *filename) {
Common::SeekableReadStream *fontFile = _vm->res()->openFile(filename);
- if (fontFile->readUint32LE() != MKID_BE('FONT')) {
+ if (fontFile->readUint32LE() != MKTAG('F','O','N','T')) {
debugCN(kDebugGraphics, "Font::Font: FONT tag expected\n");
return;
}
@@ -92,7 +92,7 @@ void Font::setFontM4(const char *filename) {
//debugCN(kDebugGraphics, "Font::Font: _maxWidth = %d, _maxHeight = %d, fontSize = %d\n", _maxWidth, _maxHeight, fontSize);
- if (fontFile->readUint32LE() != MKID_BE('WIDT')) {
+ if (fontFile->readUint32LE() != MKTAG('W','I','D','T')) {
debugCN(kDebugGraphics, "Font::Font: WIDT tag expected\n");
return;
}
@@ -100,7 +100,7 @@ void Font::setFontM4(const char *filename) {
_charWidths = new uint8[256];
fontFile->read(_charWidths, 256);
- if (fontFile->readUint32LE() != MKID_BE('OFFS')) {
+ if (fontFile->readUint32LE() != MKTAG('O','F','F','S')) {
debugCN(kDebugGraphics, "Font::Font: OFFS tag expected\n");
return;
}
@@ -110,7 +110,7 @@ void Font::setFontM4(const char *filename) {
for (int i = 0; i < 256; i++)
_charOffs[i] = fontFile->readUint16LE();
- if (fontFile->readUint32LE() != MKID_BE('PIXS')) {
+ if (fontFile->readUint32LE() != MKTAG('P','I','X','S')) {
debugCN(kDebugGraphics, "Font::Font: PIXS tag expected\n");
return;
}
diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp
index a651510d10..5fc46d3881 100644
--- a/engines/m4/graphics.cpp
+++ b/engines/m4/graphics.cpp
@@ -795,7 +795,11 @@ void M4Surface::m4LoadBackground(Common::SeekableReadStream *source) {
palette[i].b = source->readByte() << 2;
palette[i].g = source->readByte() << 2;
palette[i].r = source->readByte() << 2;
- palette[i].u = source->readByte() << 2;
+ // FIXME - Removed u field from RGB8 as the OSystem palette is now RGB.
+ // If this is needed, then the system setPalette() call will need changing to skip this.
+ uint8 u = source->readByte() << 2;
+ if (u != 0)
+ debugC(1, kDebugGraphics, "Unused u field in Palette data non-zero: %d", u);
if ((blackIndex == 0) && !palette[i].r && !palette[i].g && !palette[i].b)
blackIndex = i;
@@ -1049,7 +1053,6 @@ void Palette::setEntry(uint index, uint8 r, uint8 g, uint8 b) {
c.r = r;
c.g = g;
c.b = b;
- c.u = 255;
g_system->getPaletteManager()->setPalette((const byte *)&c, index, 1);
}
diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h
index ecb5048b26..d58ed69403 100644
--- a/engines/m4/graphics.h
+++ b/engines/m4/graphics.h
@@ -47,7 +47,7 @@ struct BGR8 {
};
struct RGB8 {
- uint8 r, g, b, u;
+ uint8 r, g, b;
};
//later use ScummVM's Rect?
@@ -214,8 +214,8 @@ private:
MadsM4Engine *_vm;
bool _colorsChanged;
bool _fading_in_progress;
- byte _originalPalette[256 * 4];
- byte _fadedPalette[256 * 4];
+ byte _originalPalette[256 * 3];
+ byte _fadedPalette[256 * 3];
int _usageCount[256];
void reset();
diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp
index 2bdd53040a..4cc2bf8783 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -107,6 +107,8 @@ void gameMenuHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) {
MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc) {
+ // Setup mixer
+ syncSoundSettings();
// FIXME
_vm = this;
@@ -149,7 +151,6 @@ MadsM4Engine::~MadsM4Engine() {
delete _palette;
delete _globals;
delete _sound;
- delete _driver;
delete _resourceManager;
}
@@ -157,16 +158,8 @@ Common::Error MadsM4Engine::run() {
// Initialize backend
_screen = new M4Surface(true); // Special form for creating screen reference
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-
- _driver = MidiDriver::createMidi(dev);
- if (native_mt32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _midi = new MidiPlayer(this, _driver);
- _midi->setGM(true);
- _midi->setNativeMT32(native_mt32);
+ _midi = new MidiPlayer(this);
+ _midi->setGM(true); // FIXME: Really? Always?
_saveLoad = new SaveLoad(this);
_palette = new Palette(this);
diff --git a/engines/m4/m4.h b/engines/m4/m4.h
index f665df262b..a43f3e1387 100644
--- a/engines/m4/m4.h
+++ b/engines/m4/m4.h
@@ -148,7 +148,6 @@ protected:
void shutdown();
- MidiDriver *_driver;
MidiPlayer *_midi;
public:
diff --git a/engines/m4/m4_views.h b/engines/m4/m4_views.h
index 9a0651a2c5..e390904aae 100644
--- a/engines/m4/m4_views.h
+++ b/engines/m4/m4_views.h
@@ -42,7 +42,7 @@ public:
int iconIndex;
GUIInventoryItem(const char *_name, const char *_verb, M4Surface *_icon, int _iconIndex) {
- name = _name; _verb = verb; icon = _icon; iconIndex = _iconIndex;
+ name = _name; verb = _verb; icon = _icon; iconIndex = _iconIndex;
}
};
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index e88a21eb4e..fd8a609b53 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -111,8 +111,8 @@ void MadsScene::loadSceneTemporary() {
/* Existing code that eventually needs to be replaced with the proper MADS code */
// Set system palette entries
_vm->_palette->blockRange(0, 18);
- RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0},
- {0x00<<2, 0x10<<2, 0x16<<2, 0}};
+ RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2}, {0x24<<2, 0x37<<2, 0x3a<<2},
+ {0x00<<2, 0x10<<2, 0x16<<2}};
_vm->_palette->setPalette(&sysColors[0], 4, 3);
_interfaceSurface->initialise();
@@ -1127,12 +1127,10 @@ bool MadsInterfaceView::handleCheatKey(int32 keycode) {
_madsVm->scene()->_showMousePos = !_madsVm->scene()->_showMousePos;
break;
- case Common::KEYCODE_t | (Common::KEYCODE_LALT << 24):
- case Common::KEYCODE_t | (Common::KEYCODE_RALT << 24):
- {
+ case Common::KEYCODE_t | (Common::KBD_ALT << 24): {
// Teleport to room
//Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE);
-
+ // TODO: Implement teleport code
return true;
}
diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp
index f130ddc3b5..e49dbfa2e7 100644
--- a/engines/m4/midi.cpp
+++ b/engines/m4/midi.cpp
@@ -28,123 +28,34 @@
#include "m4/m4.h"
#include "m4/midi.h"
+#include "audio/midiparser.h"
+#include "common/config-manager.h"
#include "common/memstream.h"
namespace M4 {
-MidiPlayer::MidiPlayer(MadsM4Engine *vm, MidiDriver *driver) : _vm(vm), _midiData(NULL), _driver(driver), _isPlaying(false), _passThrough(false), _isGM(false) {
- memset(_channel, 0, sizeof(_channel));
- _masterVolume = 0;
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(getBaseTempo());
- open();
-}
-
-MidiPlayer::~MidiPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- _parser->setMidiDriver(NULL);
- stopMusic();
- close();
- delete _parser;
- free(_midiData);
-}
-
-void MidiPlayer::setVolume(int volume) {
- Common::StackLock lock(_mutex);
+MidiPlayer::MidiPlayer(MadsM4Engine *vm) : _vm(vm), _isGM(false) {
- if (volume < 0)
- volume = 0;
- else if (volume > 255)
- volume = 255;
-
- if (_masterVolume == volume)
- return;
-
- _masterVolume = volume;
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
- }
-}
-
-int MidiPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+ MidiPlayer::createDriver();
int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
-
-void MidiPlayer::close() {
- stopMusic();
- if (_driver)
- _driver->close();
- _driver = 0;
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (!_channel[b & 0x0F])
- return;
- }
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F:
- // End of track. (Not called when auto-looping.)
- stopMusic();
- break;
- case 0x51:
- // Set tempo. Handled by the standard MIDI parser already.
- break;
- default:
- warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiPlayer::onTimer(void *refCon) {
- MidiPlayer *midi = (MidiPlayer *)refCon;
- Common::StackLock lock(midi->_mutex);
-
- if (midi->_isPlaying)
- midi->_parser->onTimer();
+ Audio::MidiPlayer::send(b);
}
void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene) {
- stopMusic();
+ Common::StackLock lock(_mutex);
+
+ stop();
char fullname[144];
_vm->res()->changeExtension(fullname, name, "HMP");
@@ -160,11 +71,10 @@ void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger
_vm->res()->purge();
if (_midiData) {
- /*
- FILE *out = fopen("music.mid", "wb");
- fwrite(_midiData, smfSize, 1, out);
- fclose(out);
- */
+ _parser = MidiParser::createParser_SMF();
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+
_parser->loadMusic(_midiData, smfSize);
_parser->property(MidiParser::mpAutoLoop, loop);
}
@@ -174,20 +84,6 @@ void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger
_isPlaying = true;
}
-void MidiPlayer::stopMusic() {
- Common::StackLock lock(_mutex);
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- }
-
- if (_midiData) {
- free(_midiData);
- _midiData = NULL;
- }
-}
-
// This function will convert HMP music into type 1 SMF, which our SMF parser
// will be able to handle. It is based on Hans de Goede's HMP 2 MIDI file
// converter, which in turn is "based on the conversion algorithms found in
diff --git a/engines/m4/midi.h b/engines/m4/midi.h
index 8344f8d485..a544fb72aa 100644
--- a/engines/m4/midi.h
+++ b/engines/m4/midi.h
@@ -28,68 +28,32 @@
#ifndef M4_MIDI_H
#define M4_MIDI_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "common/mutex.h"
+#include "audio/midiplayer.h"
namespace M4 {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
- MidiPlayer(MadsM4Engine *vm, MidiDriver *driver);
- ~MidiPlayer();
+ MidiPlayer(MadsM4Engine *vm);
- bool isPlaying() { return _isPlaying; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
void playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene);
- void stopMusic();
- void setPassThrough(bool b) { _passThrough = b; }
void setGM(bool isGM) { _isGM = isGM; }
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
protected:
- static void onTimer(void *data);
-
MadsM4Engine *_vm;
- byte *_midiData;
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_parser;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
- bool _isPlaying;
bool _randomLoop;
- byte _masterVolume;
byte *_musicData;
uint16 *_buf;
size_t _musicDataSize;
- Common::Mutex _mutex;
-
byte *convertHMPtoSMF(byte *data, uint32 inSize, uint32 &outSize);
};
diff --git a/engines/m4/rails.cpp b/engines/m4/rails.cpp
index ff18d645e7..39cba9ab84 100644
--- a/engines/m4/rails.cpp
+++ b/engines/m4/rails.cpp
@@ -194,9 +194,8 @@ long SqrtF16(long n) {
void Rails::createEdge(int32 node1, int32 node2) {
uint32 index;
int32 x1, y1, x2, y2;
- bool valid, finished;
+ bool valid;
long deltaX, deltaY, distance;
- uint8 *walkCodePtr;
if ((node1 < 0) || (node1 >= MAXRAILNODES) || (node2 < 0) || (node2 >= MAXRAILNODES))
return;
@@ -214,8 +213,6 @@ void Rails::createEdge(int32 node1, int32 node2) {
_edges.resize(index + 1);
_edges.insert_at(index, 0);
valid = true;
- walkCodePtr = NULL;
- finished = false;
if (_nodes.size() <= (uint32)node1 || _nodes.size() <= (uint32)node2)
return;
diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp
index 70abc47960..192cab0c83 100644
--- a/engines/m4/resource.cpp
+++ b/engines/m4/resource.cpp
@@ -465,7 +465,6 @@ Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resour
bool MADSResourceManager::resourceExists(const char *resourceName) {
Common::File hagFile;
- uint32 offset, size;
// If the first character is the wildcard (resource indicator), skip over it
if (*resourceName == '*')
@@ -488,8 +487,8 @@ bool MADSResourceManager::resourceExists(const char *resourceName) {
while (++resIndex < numEntries) {
// Read in the details of the next resource
char resourceBuffer[14];
- offset = hagFile.readUint32LE();
- size = hagFile.readUint32LE();
+ hagFile.readUint32LE(); // offset
+ hagFile.readUint32LE(); // size
hagFile.read(resourceBuffer, 14);
if (!strcmp(resName, resourceBuffer))
diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp
index 57d63c153a..0f684ebced 100644
--- a/engines/m4/scene.cpp
+++ b/engines/m4/scene.cpp
@@ -149,11 +149,11 @@ void Scene::showCodes() {
for (int i = 0; i < _walkSurface->width() * _walkSurface->height(); i++)
destP[i] = (srcP[i] & 0x10) ? 0xFF : 0;
- byte colors[256 * 4];
+ byte colors[256 * 3];
memset(colors, 0, sizeof(colors));
- colors[255 * 4 + 0] = 255;
- colors[255 * 4 + 1] = 255;
- colors[255 * 4 + 2] = 255;
+ colors[255 * 3 + 0] = 255;
+ colors[255 * 3 + 1] = 255;
+ colors[255 * 3 + 2] = 255;
_vm->_palette->setPalette(colors, 0, 256);
} else {
// MADS handling
diff --git a/engines/m4/woodscript.cpp b/engines/m4/woodscript.cpp
index f45e8fa8a2..1b9d9859ef 100644
--- a/engines/m4/woodscript.cpp
+++ b/engines/m4/woodscript.cpp
@@ -164,7 +164,7 @@ WoodScript::WoodScript(MadsM4Engine *vm) {
_backgroundSurface = NULL;
- Common::Rect viewBounds = Common::Rect(0, 0, 640, 480);
+ //Common::Rect viewBounds = Common::Rect(0, 0, 640, 480);
//_surfaceView = new View(viewBounds);
}
@@ -321,12 +321,12 @@ void WoodScript::update() {
{
// FIXME: This should be done when a new palette is set
- byte palette[1024];
+ byte palette[768];
g_system->getPaletteManager()->grabPalette(palette, 0, 256);
for (int i = 0; i < 256; i++) {
- _mainPalette[i].r = palette[i * 4 + 0];
- _mainPalette[i].g = palette[i * 4 + 1];
- _mainPalette[i].b = palette[i * 4 + 2];
+ _mainPalette[i].r = palette[i * 3 + 0];
+ _mainPalette[i].g = palette[i * 3 + 1];
+ _mainPalette[i].b = palette[i * 3 + 2];
}
}
diff --git a/engines/made/database.cpp b/engines/made/database.cpp
index 2aa378edf5..8d06aa0085 100644
--- a/engines/made/database.cpp
+++ b/engines/made/database.cpp
@@ -659,7 +659,7 @@ bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String
}
uint32 header = in->readUint32BE();
- if (header != MKID_BE('SGAM')) {
+ if (header != MKTAG('S','G','A','M')) {
warning("Save game header missing");
delete in;
return false;
@@ -696,7 +696,7 @@ int16 GameDatabaseV3::savegame(const char *filename, const char *description, in
return 6;
}
strncpy(desc, description, 64);
- out->writeUint32BE(MKID_BE('SGAM'));
+ out->writeUint32BE(MKTAG('S','G','A','M'));
out->writeUint32LE(size);
out->writeUint16LE(version);
out->write(desc, 64);
@@ -715,7 +715,7 @@ int16 GameDatabaseV3::loadgame(const char *filename, int16 version) {
}
uint32 header = in->readUint32BE();
- if (header != MKID_BE('SGAM')) {
+ if (header != MKTAG('S','G','A','M')) {
warning("Save game header missing");
delete in;
return 1;
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 11f7734495..c81fa3db25 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -100,18 +100,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
_script = new ScriptInterpreter(this);
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
- MidiDriver *driver = MidiDriver::createMidi(dev);
- if (native_mt32)
- driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _music = new MusicPlayer(driver);
- _music->setNativeMT32(native_mt32);
- _music->open();
- //_music->setAdLib(adlib);
+ _music = new MusicPlayer();
// Set default sound frequency
switch (getGameID()) {
@@ -146,11 +135,15 @@ MadeEngine::~MadeEngine() {
}
void MadeEngine::syncSoundSettings() {
- _music->setVolume(ConfMan.getInt("music_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _music->setVolume(mute ? 0 : ConfMan.getInt("music_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType,
+ mute ? 0 : ConfMan.getInt("sfx_volume"));
}
int16 MadeEngine::getTicks() {
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index 8c9248a262..2e06871e13 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -37,119 +37,31 @@
namespace Made {
-MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
- memset(_channel, 0, sizeof(_channel));
- _masterVolume = 0;
- _xmidiParser = MidiParser::createParser_XMIDI();
- _smfParser = MidiParser::createParser_SMF();
-}
-
-MusicPlayer::~MusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _xmidiParser->setMidiDriver(NULL);
- _smfParser->setMidiDriver(NULL);
- delete _xmidiParser;
- delete _smfParser;
-}
-
-void MusicPlayer::setVolume(int volume) {
- volume = CLIP(volume, 0, 255);
-
- if (_masterVolume == volume)
- return;
-
- _masterVolume = volume;
-
- Common::StackLock lock(_mutex);
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
- }
-}
-
-int MusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+MusicPlayer::MusicPlayer() : _isGM(false) {
+ MidiPlayer::createDriver();
int ret = _driver->open();
- if (ret)
- return ret;
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
-void MusicPlayer::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MusicPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- else if ((b & 0xFFF0) == 0x007BB0) {
- // Only respond to All Notes Off if this channel
- // has currently been allocated
- if (!_channel[b & 0x0F])
- return;
- }
-
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
-
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stop();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MusicPlayer::onTimer(void *refCon) {
- MusicPlayer *music = (MusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
- if (music->_isPlaying)
- music->_parser->onTimer();
+ Audio::MidiPlayer::send(b);
}
void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying)
return;
@@ -159,11 +71,11 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
_isGM = true;
- if (_xmidiParser->loadMusic(midiResource->getData(), midiResource->getSize())) {
- MidiParser *parser = _xmidiParser;
+ MidiParser *parser = MidiParser::createParser_XMIDI();
+ if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
@@ -171,12 +83,16 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
setVolume(127);
- _looping = flags & MUSIC_LOOP;
+ _isLooping = flags & MUSIC_LOOP;
_isPlaying = true;
+ } else {
+ delete parser;
}
}
void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying)
return;
@@ -186,29 +102,21 @@ void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) {
_isGM = true;
- if (_smfParser->loadMusic(midiResource->getData(), midiResource->getSize())) {
- MidiParser *parser = _smfParser;
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_parser = parser;
setVolume(127);
- _looping = flags & MUSIC_LOOP;
+ _isLooping = flags & MUSIC_LOOP;
_isPlaying = true;
- }
-}
-
-void MusicPlayer::stop() {
- Common::StackLock lock(_mutex);
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
+ } else {
+ delete parser;
}
}
diff --git a/engines/made/music.h b/engines/made/music.h
index 9840c50cfa..f8f70cdad6 100644
--- a/engines/made/music.h
+++ b/engines/made/music.h
@@ -28,7 +28,7 @@
#ifndef MADE_MUSIC_H
#define MADE_MUSIC_H
-#include "audio/mididrv.h"
+#include "audio/midiplayer.h"
#include "audio/midiparser.h"
#include "common/mutex.h"
@@ -41,61 +41,21 @@ enum MusicFlags {
MUSIC_LOOP = 1
};
-class MusicPlayer : public MidiDriver {
+class MusicPlayer : public Audio::MidiPlayer {
public:
- MusicPlayer(MidiDriver *driver);
- ~MusicPlayer();
+ MusicPlayer();
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
void playXMIDI(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
void playSMF(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
- void stop();
+// void stop();
void pause();
void resume();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
- void setGM(bool isGM) { _isGM = isGM; }
-
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
protected:
-
- static void onTimer(void *data);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_xmidiParser, *_smfParser;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
-
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
};
} // End of namespace Made
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
index 34163a940d..e37bd87a7e 100644
--- a/engines/made/pmvplayer.cpp
+++ b/engines/made/pmvplayer.cpp
@@ -50,14 +50,14 @@ bool PmvPlayer::play(const char *filename) {
uint32 chunkType, chunkSize, prevChunkSize = 0;
readChunk(chunkType, chunkSize); // "MOVE"
- if (chunkType != MKID_BE('MOVE')) {
+ if (chunkType != MKTAG('M','O','V','E')) {
warning("Unexpected PMV video header, expected 'MOVE'");
delete _fd;
return false;
}
readChunk(chunkType, chunkSize); // "MHED"
- if (chunkType != MKID_BE('MHED')) {
+ if (chunkType != MKTAG('M','H','E','D')) {
warning("Unexpected PMV video header, expected 'MHED'");
delete _fd;
return false;
@@ -98,7 +98,7 @@ bool PmvPlayer::play(const char *filename) {
uint32 soundStartTime = 0, skipFrames = 0;
- uint32 frameNum, bytesRead;
+ uint32 bytesRead;
uint16 width, height, cmdOffs, pixelOffs, maskOffs, lineSize;
// TODO: Sound can still be a little choppy. A bug in the decoder or -
@@ -111,7 +111,7 @@ bool PmvPlayer::play(const char *filename) {
int32 frameTime = _vm->_system->getMillis();
readChunk(chunkType, chunkSize);
- if (chunkType != MKID_BE('MFRM')) {
+ if (chunkType != MKTAG('M','F','R','M')) {
warning("Unknown chunk type");
}
@@ -156,7 +156,7 @@ bool PmvPlayer::play(const char *filename) {
// Handle video
imageData = frameData + READ_LE_UINT32(frameData + 12) - 8;
- frameNum = READ_LE_UINT32(frameData);
+ // frameNum @0
width = READ_LE_UINT16(imageData + 8);
height = READ_LE_UINT16(imageData + 10);
cmdOffs = READ_LE_UINT16(imageData + 12);
diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp
index f8582aec40..e556e4ab38 100644
--- a/engines/made/resource.cpp
+++ b/engines/made/resource.cpp
@@ -57,7 +57,7 @@ PictureResource::~PictureResource() {
}
void PictureResource::load(byte *source, int size) {
- if (READ_BE_UINT32(source) == MKID_BE('Flex')) {
+ if (READ_BE_UINT32(source) == MKTAG('F','l','e','x')) {
loadChunked(source, size);
} else {
loadRaw(source, size);
@@ -126,13 +126,13 @@ void PictureResource::loadChunked(byte *source, int size) {
debug(0, "chunkType = %08X; chunkSize = %d", chunkType, chunkSize);
- if (chunkType == MKID_BE('Rect')) {
+ if (chunkType == MKTAG('R','e','c','t')) {
debug(0, "Rect");
sourceS->skip(4);
height = sourceS->readUint16BE();
width = sourceS->readUint16BE();
debug(0, "width = %d; height = %d", width, height);
- } else if (chunkType == MKID_BE('fMap')) {
+ } else if (chunkType == MKTAG('f','M','a','p')) {
debug(0, "fMap");
lineSize = sourceS->readUint16BE();
sourceS->skip(11);
@@ -140,21 +140,21 @@ void PictureResource::loadChunked(byte *source, int size) {
cmdOffs = sourceS->pos();
sourceS->skip(chunkSize - 14);
debug(0, "lineSize = %d; cmdFlags = %d; cmdOffs = %04X", lineSize, cmdFlags, cmdOffs);
- } else if (chunkType == MKID_BE('fLCo')) {
+ } else if (chunkType == MKTAG('f','L','C','o')) {
debug(0, "fLCo");
sourceS->skip(9);
pixelFlags = sourceS->readByte();
pixelOffs = sourceS->pos();
sourceS->skip(chunkSize - 10);
debug(0, "pixelFlags = %d; pixelOffs = %04X", pixelFlags, pixelOffs);
- } else if (chunkType == MKID_BE('fPix')) {
+ } else if (chunkType == MKTAG('f','P','i','x')) {
debug(0, "fPix");
sourceS->skip(9);
maskFlags = sourceS->readByte();
maskOffs = sourceS->pos();
sourceS->skip(chunkSize - 10);
debug(0, "maskFlags = %d; maskOffs = %04X", maskFlags, maskOffs);
- } else if (chunkType == MKID_BE('fGCo')) {
+ } else if (chunkType == MKTAG('f','G','C','o')) {
debug(0, "fGCo");
_hasPalette = true;
_paletteColorCount = chunkSize / 3;
diff --git a/engines/made/resource.h b/engines/made/resource.h
index 5d5664b4c7..ade6a23029 100644
--- a/engines/made/resource.h
+++ b/engines/made/resource.h
@@ -49,16 +49,16 @@ const int kMaxResourceCacheSize = 400 * 1024;
enum ResourceType {
- kResARCH = MKID_BE('ARCH'),
- kResFREE = MKID_BE('FREE'),
- kResOMNI = MKID_BE('OMNI'),
- kResFLEX = MKID_BE('FLEX'),
- kResSNDS = MKID_BE('SNDS'),
- kResANIM = MKID_BE('ANIM'),
- kResMENU = MKID_BE('MENU'),
- kResFONT = MKID_BE('FONT'),
- kResXMID = MKID_BE('XMID'),
- kResMIDI = MKID_BE('MIDI')
+ kResARCH = MKTAG('A','R','C','H'),
+ kResFREE = MKTAG('F','R','E','E'),
+ kResOMNI = MKTAG('O','M','N','I'),
+ kResFLEX = MKTAG('F','L','E','X'),
+ kResSNDS = MKTAG('S','N','D','S'),
+ kResANIM = MKTAG('A','N','I','M'),
+ kResMENU = MKTAG('M','E','N','U'),
+ kResFONT = MKTAG('F','O','N','T'),
+ kResXMID = MKTAG('X','M','I','D'),
+ kResMIDI = MKTAG('M','I','D','I')
};
struct ResourceSlot;
diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp
index 7a4c12eefb..2649e2bd37 100644
--- a/engines/made/screen.cpp
+++ b/engines/made/screen.cpp
@@ -32,7 +32,6 @@ namespace Made {
Screen::Screen(MadeEngine *vm) : _vm(vm) {
- _screenPalette = new byte[256 * 4];
_palette = new byte[768];
_newPalette = new byte[768];
@@ -95,7 +94,6 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) {
Screen::~Screen() {
- delete[] _screenPalette;
delete[] _palette;
delete[] _newPalette;
@@ -220,14 +218,7 @@ void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, int16 f
}
void Screen::setRGBPalette(byte *palRGB, int start, int count) {
- for (int i = 0; i < count; i++) {
- _screenPalette[i * 4 + 0] = palRGB[i * 3 + 0];
- _screenPalette[i * 4 + 1] = palRGB[i * 3 + 1];
- _screenPalette[i * 4 + 2] = palRGB[i * 3 + 2];
- _screenPalette[i * 4 + 3] = 0;
- }
-
- _vm->_system->getPaletteManager()->setPalette(_screenPalette, start, count);
+ _vm->_system->getPaletteManager()->setPalette(palRGB, start, count);
}
uint16 Screen::updateChannel(uint16 channelIndex) {
diff --git a/engines/made/screen.h b/engines/made/screen.h
index c91704ef79..e9292240a1 100644
--- a/engines/made/screen.h
+++ b/engines/made/screen.h
@@ -200,7 +200,6 @@ protected:
bool _screenLock;
bool _paletteLock;
- byte *_screenPalette;
byte *_palette, *_newPalette;
int _paletteColorCount, _oldPaletteColorCount;
bool _paletteInitialized, _needPalette;
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp
index ac4f27619b..c8111fa91b 100644
--- a/engines/mohawk/bitmap.cpp
+++ b/engines/mohawk/bitmap.cpp
@@ -80,13 +80,12 @@ void MohawkBitmap::decodeImageData(Common::SeekableReadStream *stream) {
_header.colorTable.tableSize = _data->readUint16BE();
_header.colorTable.rgbBits = _data->readByte();
_header.colorTable.colorCount = _data->readByte();
- _header.colorTable.palette = (byte *)malloc(256 * 4);
+ _header.colorTable.palette = (byte *)malloc(256 * 3);
for (uint16 i = 0; i < 256; i++) {
- _header.colorTable.palette[i * 4 + 2] = _data->readByte();
- _header.colorTable.palette[i * 4 + 1] = _data->readByte();
- _header.colorTable.palette[i * 4] = _data->readByte();
- _header.colorTable.palette[i * 4 + 3] = 0;
+ _header.colorTable.palette[i * 3 + 2] = _data->readByte();
+ _header.colorTable.palette[i * 3 + 1] = _data->readByte();
+ _header.colorTable.palette[i * 3 + 0] = _data->readByte();
}
}
@@ -623,6 +622,8 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) {
}
}
+#ifdef ENABLE_MYST
+
//////////////////////////////////////////
// Myst Bitmap Decoder
//////////////////////////////////////////
@@ -671,12 +672,12 @@ MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream* stream) {
byte *palData = NULL;
if (_info.bitsPerPixel == 8) {
- palData = (byte *)malloc(256 * 4);
+ palData = (byte *)malloc(256 * 3);
for (uint16 i = 0; i < _info.colorsUsed; i++) {
- palData[i * 4 + 2] = bmpStream->readByte();
- palData[i * 4 + 1] = bmpStream->readByte();
- palData[i * 4] = bmpStream->readByte();
- palData[i * 4 + 3] = bmpStream->readByte();
+ palData[i * 3 + 2] = bmpStream->readByte();
+ palData[i * 3 + 1] = bmpStream->readByte();
+ palData[i * 3 + 0] = bmpStream->readByte();
+ bmpStream->readByte();
}
}
@@ -722,7 +723,9 @@ MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream* stream) {
return new MohawkSurface(surface, palData);
}
-MohawkSurface *OldMohawkBitmap::decodeImage(Common::SeekableReadStream *stream) {
+#endif
+
+MohawkSurface *LivingBooksBitmap_v1::decodeImage(Common::SeekableReadStream *stream) {
Common::SeekableSubReadStreamEndian *endianStream = (Common::SeekableSubReadStreamEndian *)stream;
// 12 bytes header for the image
@@ -757,10 +760,10 @@ MohawkSurface *OldMohawkBitmap::decodeImage(Common::SeekableReadStream *stream)
_data = decompressLZ(stream, uncompressedSize);
if (endianStream->pos() != endianStream->size())
- error("OldMohawkBitmap decompression failed");
+ error("LivingBooksBitmap_v1 decompression failed");
} else {
if ((_header.format & 0xf0) != 0)
- error("Tried to use unknown OldMohawkBitmap compression (format %02x)", _header.format & 0xf0);
+ error("Tried to use unknown LivingBooksBitmap_v1 compression (format %02x)", _header.format & 0xf0);
// This is so nasty on so many levels. The original Windows LZ decompressor for the
// Living Books v1 games had knowledge of the underlying RLE8 data. While going
diff --git a/engines/mohawk/bitmap.h b/engines/mohawk/bitmap.h
index 14b8e75327..ea8a130dfc 100644
--- a/engines/mohawk/bitmap.h
+++ b/engines/mohawk/bitmap.h
@@ -144,6 +144,8 @@ private:
void handleRivenSubcommandStream(byte count, byte *&dst);
};
+#ifdef ENABLE_MYST
+
// Myst uses a different image format than that of other Mohawk games.
// It essentially uses a Windows bitmap with the LZ encoding from the
// Mohawk Bitmap format.
@@ -181,10 +183,12 @@ private:
} _info;
};
-class OldMohawkBitmap : public MohawkBitmap {
+#endif
+
+class LivingBooksBitmap_v1 : public MohawkBitmap {
public:
- OldMohawkBitmap() : MohawkBitmap() {}
- ~OldMohawkBitmap() {}
+ LivingBooksBitmap_v1() : MohawkBitmap() {}
+ ~LivingBooksBitmap_v1() {}
MohawkSurface *decodeImage(Common::SeekableReadStream *stream);
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 64e403092a..ee67c9f23c 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -24,19 +24,30 @@
*/
#include "mohawk/console.h"
+#include "mohawk/graphics.h"
+#include "mohawk/livingbooks.h"
+#include "mohawk/sound.h"
+#include "mohawk/video.h"
+
+#ifdef ENABLE_CSTIME
+#include "mohawk/cstime.h"
+#endif
+
+#ifdef ENABLE_MYST
#include "mohawk/myst.h"
#include "mohawk/myst_areas.h"
#include "mohawk/myst_scripts.h"
-#include "mohawk/graphics.h"
+#endif
+
+#ifdef ENABLE_RIVEN
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
-#include "mohawk/livingbooks.h"
-#include "mohawk/cstime.h"
-#include "mohawk/sound.h"
-#include "mohawk/video.h"
+#endif
namespace Mohawk {
+#ifdef ENABLE_MYST
+
MystConsole::MystConsole(MohawkEngine_Myst *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard));
DCmd_Register("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard));
@@ -307,6 +318,10 @@ bool MystConsole::Cmd_Resources(int argc, const char **argv) {
return true;
}
+#endif // ENABLE_MYST
+
+#ifdef ENABLE_RIVEN
+
RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard));
DCmd_Register("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard));
@@ -316,7 +331,6 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound));
DCmd_Register("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack));
DCmd_Register("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack));
- DCmd_Register("restart", WRAP_METHOD(RivenConsole, Cmd_Restart));
DCmd_Register("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots));
DCmd_Register("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode));
DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript));
@@ -355,18 +369,17 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) {
return true;
}
- uint32 *globalVar = _vm->getVar(argv[1]);
-
- if (!globalVar) {
- DebugPrintf("Unknown variable \'%s\'\n", argv[1]);
+ if (!_vm->_vars.contains(argv[1])) {
+ DebugPrintf("Unknown variable '%s'\n", argv[1]);
return true;
}
- if (argc > 2)
- *globalVar = (uint32)atoi(argv[2]);
+ uint32 &var = _vm->_vars[argv[1]];
- DebugPrintf("%s = %d\n", argv[1], *globalVar);
+ if (argc > 2)
+ var = (uint32)atoi(argv[2]);
+ DebugPrintf("%s = %d\n", argv[1], var);
return true;
}
@@ -446,14 +459,6 @@ bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) {
return false;
}
-bool RivenConsole::Cmd_Restart(int argc, const char **argv) {
- _vm->initVars();
- _vm->changeToStack(aspit);
- _vm->changeToCard(1);
-
- return false;
-}
-
bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
DebugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount());
@@ -473,11 +478,11 @@ bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
}
bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) {
- uint32 *zipModeActive = _vm->getVar("azip");
- *zipModeActive = !(*zipModeActive);
+ uint32 &zipModeActive = _vm->_vars["azip"];
+ zipModeActive = !zipModeActive;
DebugPrintf("Zip Mode is ");
- DebugPrintf((*zipModeActive) ? "Enabled" : "Disabled");
+ DebugPrintf(zipModeActive ? "Enabled" : "Disabled");
DebugPrintf("\n");
return true;
}
@@ -558,7 +563,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
// deriven.
debugN("\n\nDumping scripts for %s\'s card %d!\n", argv[1], (uint16)atoi(argv[3]));
debugN("==================================\n\n");
- Common::SeekableReadStream *cardStream = _vm->getResource(MKID_BE('CARD'), (uint16)atoi(argv[3]));
+ Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3]));
cardStream->seek(4);
RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false);
for (uint32 i = 0; i < scriptList.size(); i++) {
@@ -571,7 +576,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
debugN("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3]));
debugN("===========================================\n\n");
- Common::SeekableReadStream *hsptStream = _vm->getResource(MKID_BE('HSPT'), (uint16)atoi(argv[3]));
+ Common::SeekableReadStream *hsptStream = _vm->getResource(MKTAG('H','S','P','T'), (uint16)atoi(argv[3]));
uint16 hotspotCount = hsptStream->readUint16BE();
@@ -624,9 +629,9 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
// You'll need to look up the Rebel Tunnel puzzle on your own; the
// solution is constant.
- uint32 teleCombo = *_vm->getVar("tcorrectorder");
- uint32 prisonCombo = *_vm->getVar("pcorrectorder");
- uint32 domeCombo = *_vm->getVar("adomecombo");
+ uint32 teleCombo = _vm->_vars["tcorrectorder"];
+ uint32 prisonCombo = _vm->_vars["pcorrectorder"];
+ uint32 domeCombo = _vm->_vars["adomecombo"];
DebugPrintf("Telescope Combo:\n ");
for (int i = 0; i < 5; i++)
@@ -653,6 +658,8 @@ bool RivenConsole::Cmd_SliderState(int argc, const char **argv) {
return true;
}
+#endif // ENABLE_RIVEN
+
LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
@@ -704,6 +711,8 @@ bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) {
return true;
}
+#ifdef ENABLE_CSTIME
+
CSTimeConsole::CSTimeConsole(MohawkEngine_CSTime *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound));
DCmd_Register("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound));
@@ -806,4 +815,6 @@ bool CSTimeConsole::Cmd_InvItem(int argc, const char **argv) {
return false;
}
+#endif // ENABLE_CSTIME
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index 1dfd0bd318..cb0e8501cd 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -30,10 +30,11 @@
namespace Mohawk {
-class MohawkEngine_Myst;
-class MohawkEngine_Riven;
class MohawkEngine_LivingBooks;
-class MohawkEngine_CSTime;
+
+#ifdef ENABLE_MYST
+
+class MohawkEngine_Myst;
class MystConsole : public GUI::Debugger {
public:
@@ -59,6 +60,12 @@ private:
bool Cmd_Resources(int argc, const char **argv);
};
+#endif
+
+#ifdef ENABLE_RIVEN
+
+class MohawkEngine_Riven;
+
class RivenConsole : public GUI::Debugger {
public:
RivenConsole(MohawkEngine_Riven *vm);
@@ -75,7 +82,6 @@ private:
bool Cmd_StopSound(int argc, const char **argv);
bool Cmd_CurStack(int argc, const char **argv);
bool Cmd_ChangeStack(int argc, const char **argv);
- bool Cmd_Restart(int argc, const char **argv);
bool Cmd_Hotspots(int argc, const char **argv);
bool Cmd_ZipMode(int argc, const char **argv);
bool Cmd_RunAllBlocks(int argc, const char **argv);
@@ -86,6 +92,8 @@ private:
bool Cmd_SliderState(int argc, const char **argv);
};
+#endif
+
class LivingBooksConsole : public GUI::Debugger {
public:
LivingBooksConsole(MohawkEngine_LivingBooks *vm);
@@ -100,6 +108,10 @@ private:
bool Cmd_ChangePage(int argc, const char **argv);
};
+#ifdef ENABLE_CSTIME
+
+class MohawkEngine_CSTime;
+
class CSTimeConsole : public GUI::Debugger {
public:
CSTimeConsole(MohawkEngine_CSTime *vm);
@@ -118,6 +130,8 @@ private:
bool Cmd_InvItem(int argc, const char **argv);
};
+#endif
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/cstime_game.cpp b/engines/mohawk/cstime_game.cpp
index 5dfc9c4cf6..14e5d99e51 100644
--- a/engines/mohawk/cstime_game.cpp
+++ b/engines/mohawk/cstime_game.cpp
@@ -470,8 +470,8 @@ void CSTimeConversation::end(bool useLastClicked, bool runEvents) {
_vm->getCase()->getCurrScene()->getChar(_sourceChar)->setupAmbientAnims(true);
}
- CSTimeInterface *interface = _vm->getInterface();
- CSTimeInventoryDisplay *invDisplay = interface->getInventoryDisplay();
+ CSTimeInterface *iface = _vm->getInterface();
+ CSTimeInventoryDisplay *invDisplay = iface->getInventoryDisplay();
if (invDisplay->getState() == 4) {
invDisplay->hide();
invDisplay->setState(0);
@@ -480,8 +480,8 @@ void CSTimeConversation::end(bool useLastClicked, bool runEvents) {
setState((uint)~0);
_currHover = 0xffff;
- interface->clearTextLine();
- interface->clearDialogArea();
+ iface->clearTextLine();
+ iface->clearDialogArea();
invDisplay->show();
// TODO: stupid case 20 stuff
diff --git a/engines/mohawk/cstime_ui.cpp b/engines/mohawk/cstime_ui.cpp
index c95e276b5e..935b0321da 100644
--- a/engines/mohawk/cstime_ui.cpp
+++ b/engines/mohawk/cstime_ui.cpp
@@ -29,6 +29,7 @@
#include "mohawk/resource.h"
#include "common/algorithm.h" // find
#include "common/events.h"
+#include "graphics/fontman.h"
namespace Mohawk {
@@ -64,12 +65,15 @@ CSTimeInterface::CSTimeInterface(MohawkEngine_CSTime *vm) : _vm(vm) {
_note = new CSTimeCarmenNote(_vm);
_options = new CSTimeOptions(_vm);
- if (!_normalFont.loadFromFON("EvP14.fon"))
- error("failed to load normal font");
- if (!_dialogFont.loadFromFON("Int1212.fon"))
- error("failed to load dialog font");
- if (!_rolloverFont.loadFromFON("Int1818.fon"))
- error("failed to load rollover font");
+ // The demo uses hardcoded system fonts
+ if (!(_vm->getFeatures() & GF_DEMO)) {
+ if (!_normalFont.loadFromFON("EvP14.fon"))
+ error("failed to load normal font");
+ if (!_dialogFont.loadFromFON("Int1212.fon"))
+ error("failed to load dialog font");
+ if (!_rolloverFont.loadFromFON("Int1818.fon"))
+ error("failed to load rollover font");
+ }
_uiFeature = NULL;
_dialogTextFeature = NULL;
@@ -91,6 +95,30 @@ CSTimeInterface::~CSTimeInterface() {
delete _options;
}
+const Graphics::Font &CSTimeInterface::getNormalFont() const {
+ // HACK: Use a ScummVM GUI font in place of a system one for the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ return *FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+
+ return _normalFont;
+}
+
+const Graphics::Font &CSTimeInterface::getDialogFont() const {
+ // HACK: Use a ScummVM GUI font in place of a system one for the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ return *FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+
+ return _dialogFont;
+}
+
+const Graphics::Font &CSTimeInterface::getRolloverFont() const {
+ // HACK: Use a ScummVM GUI font in place of a system one for the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ return *FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
+
+ return _rolloverFont;
+}
+
void CSTimeInterface::cursorInstall() {
_vm->getView()->loadBitmapCursors(200);
}
diff --git a/engines/mohawk/cstime_ui.h b/engines/mohawk/cstime_ui.h
index b849ddbdfb..3ec38492d7 100644
--- a/engines/mohawk/cstime_ui.h
+++ b/engines/mohawk/cstime_ui.h
@@ -233,9 +233,9 @@ public:
const Common::Array<Common::String> &getDialogLines() { return _dialogLines; }
const Common::Array<byte> &getDialogLineColors() { return _dialogLineColors; }
- const Graphics::WinFont &getNormalFont() { return _normalFont; }
- const Graphics::WinFont &getDialogFont() { return _dialogFont; }
- const Graphics::WinFont &getRolloverFont() { return _rolloverFont; }
+ const Graphics::Font &getNormalFont() const;
+ const Graphics::Font &getDialogFont() const;
+ const Graphics::Font &getRolloverFont() const;
Common::Rect _sceneRect, _uiRect;
Common::Rect _dialogTextRect, _bookRect, _noteRect;
diff --git a/engines/mohawk/cstime_view.cpp b/engines/mohawk/cstime_view.cpp
index cad44e3b30..115b363b6e 100644
--- a/engines/mohawk/cstime_view.cpp
+++ b/engines/mohawk/cstime_view.cpp
@@ -537,7 +537,7 @@ void CSTimeModule::dialogTextDrawProc(Feature *feature) {
const Common::Array<Common::String> &lines = _vm->getInterface()->getDialogLines();
const Common::Array<byte> &colors = _vm->getInterface()->getDialogLineColors();
const Common::Rect &bounds = feature->_data.bounds;
- const Graphics::WinFont &font = _vm->getInterface()->getDialogFont();
+ const Graphics::Font &font = _vm->getInterface()->getDialogFont();
Graphics::Surface *screen = _vm->_system->lockScreen();
for (uint i = 0; i < lines.size(); i++)
@@ -553,7 +553,7 @@ void CSTimeModule::bubbleTextMoveProc(Feature *feature) {
void CSTimeModule::bubbleTextDrawProc(Feature *feature) {
Common::Rect bounds = feature->_data.bounds;
bounds.grow(-5);
- const Graphics::WinFont &font = _vm->getInterface()->getDialogFont();
+ const Graphics::Font &font = _vm->getInterface()->getDialogFont();
uint height = font.getFontHeight();
Common::Array<Common::String> lines;
diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp
index 45f3329f13..b4969f990a 100644
--- a/engines/mohawk/cursors.cpp
+++ b/engines/mohawk/cursors.cpp
@@ -23,23 +23,27 @@
*
*/
-#include "mohawk/bitmap.h"
#include "mohawk/cursors.h"
+#include "mohawk/mohawk.h"
#include "mohawk/resource.h"
-#include "mohawk/graphics.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven_cursors.h"
#include "common/macresman.h"
-#include "common/ne_exe.h"
#include "common/system.h"
+#include "common/winexe_ne.h"
+#include "common/winexe_pe.h"
#include "graphics/cursorman.h"
+#include "graphics/wincursor.h"
+
+#ifdef ENABLE_MYST
+#include "mohawk/bitmap.h"
+#include "mohawk/myst.h"
+#endif
namespace Mohawk {
static const byte s_bwPalette[] = {
- 0x00, 0x00, 0x00, 0x00, // Black
- 0xFF, 0xFF, 0xFF, 0x00 // White
+ 0x00, 0x00, 0x00, // Black
+ 0xFF, 0xFF, 0xFF // White
};
void CursorManager::showCursor() {
@@ -83,15 +87,16 @@ void CursorManager::setCursor(uint16 id) {
setDefaultCursor();
}
-void CursorManager::decodeMacXorCursor(Common::SeekableReadStream *stream, byte *cursor) {
+void CursorManager::setMacXorCursor(Common::SeekableReadStream *stream) {
assert(stream);
- assert(cursor);
+
+ byte cursorBitmap[16 * 16];
// Get black and white data
for (int i = 0; i < 32; i++) {
byte imageByte = stream->readByte();
for (int b = 0; b < 8; b++)
- cursor[i * 8 + b] = (imageByte & (0x80 >> b)) ? 1 : 2;
+ cursorBitmap[i * 8 + b] = (imageByte & (0x80 >> b)) ? 1 : 2;
}
// Apply mask data
@@ -99,30 +104,22 @@ void CursorManager::decodeMacXorCursor(Common::SeekableReadStream *stream, byte
byte imageByte = stream->readByte();
for (int b = 0; b < 8; b++)
if ((imageByte & (0x80 >> b)) == 0)
- cursor[i * 8 + b] = 0;
+ cursorBitmap[i * 8 + b] = 0;
}
-}
-
-void CursorManager::setStandardCursor(Common::SeekableReadStream *stream) {
- // The Broderbund devs decided to rip off the Mac format, it seems.
- // However, they reversed the x/y hotspot. That makes it totally different!!!!
- assert(stream);
- byte cursorBitmap[16 * 16];
- decodeMacXorCursor(stream, cursorBitmap);
uint16 hotspotY = stream->readUint16BE();
uint16 hotspotX = stream->readUint16BE();
CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0);
CursorMan.replaceCursorPalette(s_bwPalette, 1, 2);
-
- delete stream;
}
void DefaultCursorManager::setCursor(uint16 id) {
- setStandardCursor(_vm->getResource(_tag, id));
+ setMacXorCursor(_vm->getResource(_tag, id));
}
+#ifdef ENABLE_MYST
+
MystCursorManager::MystCursorManager(MohawkEngine_Myst *vm) : _vm(vm) {
_bmpDecoder = new MystBitmap();
}
@@ -167,118 +164,7 @@ void MystCursorManager::setDefaultCursor() {
setCursor(kDefaultMystCursor);
}
-void RivenCursorManager::setCursor(uint16 id) {
- // All of Riven's cursors are hardcoded. See riven_cursors.h for these definitions.
-
- switch (id) {
- case 1002:
- // Zip Mode
- CursorMan.replaceCursor(s_zipModeCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(s_zipModeCursorPalette, 1, ARRAYSIZE(s_zipModeCursorPalette) / 4);
- break;
- case 2003:
- // Hand Over Object
- CursorMan.replaceCursor(s_objectHandCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 2004:
- // Grabbing/Using Object
- CursorMan.replaceCursor(s_grabbingHandCursor, 13, 13, 6, 6, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3000:
- // Standard Hand
- CursorMan.replaceCursor(s_standardHandCursor, 15, 16, 6, 0, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3001:
- // Pointing Left
- CursorMan.replaceCursor(s_pointingLeftCursor, 15, 13, 0, 3, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3002:
- // Pointing Right
- CursorMan.replaceCursor(s_pointingRightCursor, 15, 13, 14, 3, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3003:
- // Pointing Down (Palm Up)
- CursorMan.replaceCursor(s_pointingDownCursorPalmUp, 13, 16, 3, 15, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3004:
- // Pointing Up (Palm Up)
- CursorMan.replaceCursor(s_pointingUpCursorPalmUp, 13, 16, 3, 0, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3005:
- // Pointing Left (Curved)
- CursorMan.replaceCursor(s_pointingLeftCursorBent, 15, 13, 0, 5, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3006:
- // Pointing Right (Curved)
- CursorMan.replaceCursor(s_pointingRightCursorBent, 15, 13, 14, 5, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3007:
- // Pointing Down (Palm Down)
- CursorMan.replaceCursor(s_pointingDownCursorPalmDown, 15, 16, 7, 15, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 4001:
- // Red Marble
- CursorMan.replaceCursor(s_redMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_redMarbleCursorPalette, 1, ARRAYSIZE(s_redMarbleCursorPalette) / 4);
- break;
- case 4002:
- // Orange Marble
- CursorMan.replaceCursor(s_orangeMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_orangeMarbleCursorPalette, 1, ARRAYSIZE(s_orangeMarbleCursorPalette) / 4);
- break;
- case 4003:
- // Yellow Marble
- CursorMan.replaceCursor(s_yellowMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_yellowMarbleCursorPalette, 1, ARRAYSIZE(s_yellowMarbleCursorPalette) / 4);
- break;
- case 4004:
- // Green Marble
- CursorMan.replaceCursor(s_greenMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_greenMarbleCursorPalette, 1, ARRAYSIZE(s_greenMarbleCursorPalette) / 4);
- break;
- case 4005:
- // Blue Marble
- CursorMan.replaceCursor(s_blueMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_blueMarbleCursorPalette, 1, ARRAYSIZE(s_blueMarbleCursorPalette) / 4);
- break;
- case 4006:
- // Violet Marble
- CursorMan.replaceCursor(s_violetMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_violetMarbleCursorPalette, 1, ARRAYSIZE(s_violetMarbleCursorPalette) / 4);
- break;
- case 5000:
- // Pellet
- CursorMan.replaceCursor(s_pelletCursor, 8, 8, 4, 4, 0);
- CursorMan.replaceCursorPalette(s_pelletCursorPalette, 1, ARRAYSIZE(s_pelletCursorPalette) / 4);
- break;
- case 9000:
- // Hide Cursor
- CursorMan.showMouse(false);
- break;
- default:
- error("Cursor %d does not exist!", id);
- }
-
- if (id != 9000) // Show Cursor
- CursorMan.showMouse(true);
-
- // Should help in cases where we need to hide the cursor immediately.
- g_system->updateScreen();
-}
-
-void RivenCursorManager::setDefaultCursor() {
- setCursor(kRivenMainCursor);
-}
+#endif
NECursorManager::NECursorManager(const Common::String &appName) {
_exe = new Common::NEResources();
@@ -295,16 +181,14 @@ NECursorManager::~NECursorManager() {
}
void NECursorManager::setCursor(uint16 id) {
- if (!_exe) {
- Common::Array<Common::NECursorGroup> cursors = _exe->getCursors();
-
- for (uint32 i = 0; i < cursors.size(); i++) {
- if (cursors[i].id == id) {
- Common::NECursor *cursor = cursors[i].cursors[0];
- CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), 0);
- CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256);
- return;
- }
+ if (_exe) {
+ Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id);
+
+ if (cursorGroup) {
+ Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor;
+ CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor());
+ CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256);
+ return;
}
}
@@ -321,6 +205,8 @@ MacCursorManager::MacCursorManager(const Common::String &appName) {
delete _resFork;
_resFork = 0;
}
+ } else {
+ _resFork = 0;
}
}
@@ -334,22 +220,33 @@ void MacCursorManager::setCursor(uint16 id) {
return;
}
- Common::SeekableReadStream *stream = _resFork->getResource(MKID_BE('CURS'), id);
+ // Try a color cursor first
+ Common::SeekableReadStream *stream = _resFork->getResource(MKTAG('c','r','s','r'), id);
- if (!stream) {
- setDefaultCursor();
+ if (stream) {
+ byte *cursor, *palette;
+ int width, height, hotspotX, hotspotY, keyColor, palSize;
+
+ _resFork->convertCrsrCursor(stream, &cursor, width, height, hotspotX, hotspotY, keyColor, true, &palette, palSize);
+
+ CursorMan.replaceCursor(cursor, width, height, hotspotX, hotspotY, keyColor);
+ CursorMan.replaceCursorPalette(palette, 0, palSize);
+
+ delete[] cursor;
+ delete[] palette;
+ delete stream;
return;
}
- byte cursorBitmap[16 * 16];
- decodeMacXorCursor(stream, cursorBitmap);
- uint16 hotspotX = stream->readUint16BE();
- uint16 hotspotY = stream->readUint16BE();
-
- CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0);
- CursorMan.replaceCursorPalette(s_bwPalette, 1, 2);
+ // Fall back to b&w cursors
+ stream = _resFork->getResource(MKTAG('C','U','R','S'), id);
- delete stream;
+ if (stream) {
+ setMacXorCursor(stream);
+ delete stream;
+ } else {
+ setDefaultCursor();
+ }
}
LivingBooksCursorManager_v2::LivingBooksCursorManager_v2() {
@@ -368,10 +265,40 @@ LivingBooksCursorManager_v2::~LivingBooksCursorManager_v2() {
void LivingBooksCursorManager_v2::setCursor(uint16 id) {
if (_sysArchive && _sysArchive->hasResource(ID_TCUR, id)) {
- setStandardCursor(_sysArchive->getResource(ID_TCUR, id));
+ setMacXorCursor(_sysArchive->getResource(ID_TCUR, id));
} else {
// TODO: Handle generated cursors
}
}
+PECursorManager::PECursorManager(const Common::String &appName) {
+ _exe = new Common::PEResources();
+
+ if (!_exe->loadFromEXE(appName)) {
+ // Not all have cursors anyway, so this is not a problem
+ delete _exe;
+ _exe = 0;
+ }
+}
+
+PECursorManager::~PECursorManager() {
+ delete _exe;
+}
+
+void PECursorManager::setCursor(uint16 id) {
+ if (_exe) {
+ Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id);
+
+ if (cursorGroup) {
+ Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor;
+ CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor());
+ CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256);
+ return;
+ }
+ }
+
+ // Last resort (not all have cursors)
+ setDefaultCursor();
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/cursors.h b/engines/mohawk/cursors.h
index a542ddb7c3..f8a9429689 100644
--- a/engines/mohawk/cursors.h
+++ b/engines/mohawk/cursors.h
@@ -31,6 +31,7 @@
namespace Common {
class MacResManager;
class NEResources;
+ class PEResources;
class SeekableReadStream;
class String;
}
@@ -39,25 +40,6 @@ namespace Common {
namespace Mohawk {
-// 803-805 are animated, one large bmp which is in chunks - these are NEVER USED
-// Other cursors (200, 300, 400, 500, 600, 700) are not the same in each stack
-enum {
- kDefaultMystCursor = 100, // The default hand
- kWhitePageCursor = 800, // Holding a white page
- kRedPageCursor = 801, // Holding a red page
- kBluePageCursor = 802, // Holding a blue page
- // kDroppingWhitePageAnimCursor = 803,
- // kDroppingRedPageAnimCursor = 804,
- // kDroppingBluePageAnimCursor = 805,
- kNewMatchCursor = 900, // Match that has not yet been lit
- kLitMatchCursor = 901, // Match that's burning
- kDeadMatchCursor = 902, // Match that's been extinguished
- kKeyCursor = 903, // Key in Lighthouse in Stoneship
- kRotateClockwiseCursor = 904, // Rotate gear clockwise (boiler on Myst)
- kRotateCounterClockwiseCursor = 905, // Rotate gear counter clockwise (boiler on Myst)
- kMystZipModeCursor = 999 // Zip Mode cursor
-};
-
enum {
kRivenOpenHandCursor = 2003,
kRivenClosedHandCursor = 2004,
@@ -68,8 +50,6 @@ enum {
class MohawkArchive;
class MohawkEngine;
-class MohawkEngine_Myst;
-class MystBitmap;
class CursorManager {
public:
@@ -80,13 +60,11 @@ public:
virtual void hideCursor();
virtual void setCursor(uint16 id);
virtual void setDefaultCursor();
+ virtual bool hasSource() const { return false; }
protected:
- // Handles the Mac version of the xor/and map cursor
- void decodeMacXorCursor(Common::SeekableReadStream *stream, byte *cursor);
-
- // Set a tCUR resource as the current cursor
- void setStandardCursor(Common::SeekableReadStream *stream);
+ // Set a Mac XOR/AND map cursor to the screen
+ void setMacXorCursor(Common::SeekableReadStream *stream);
};
// The default Mohawk cursor manager
@@ -97,12 +75,37 @@ public:
~DefaultCursorManager() {}
void setCursor(uint16 id);
+ bool hasSource() const { return true; }
private:
MohawkEngine *_vm;
uint32 _tag;
};
+#ifdef ENABLE_MYST
+
+// 803-805 are animated, one large bmp which is in chunks - these are NEVER USED
+// Other cursors (200, 300, 400, 500, 600, 700) are not the same in each stack
+enum {
+ kDefaultMystCursor = 100, // The default hand
+ kWhitePageCursor = 800, // Holding a white page
+ kRedPageCursor = 801, // Holding a red page
+ kBluePageCursor = 802, // Holding a blue page
+ // kDroppingWhitePageAnimCursor = 803,
+ // kDroppingRedPageAnimCursor = 804,
+ // kDroppingBluePageAnimCursor = 805,
+ kNewMatchCursor = 900, // Match that has not yet been lit
+ kLitMatchCursor = 901, // Match that's burning
+ kDeadMatchCursor = 902, // Match that's been extinguished
+ kKeyCursor = 903, // Key in Lighthouse in Stoneship
+ kRotateClockwiseCursor = 904, // Rotate gear clockwise (boiler on Myst)
+ kRotateCounterClockwiseCursor = 905, // Rotate gear counter clockwise (boiler on Myst)
+ kMystZipModeCursor = 999 // Zip Mode cursor
+};
+
+class MohawkEngine_Myst;
+class MystBitmap;
+
// The cursor manager for Myst
// Uses WDIB + CLRC resources
class MystCursorManager : public CursorManager {
@@ -114,31 +117,23 @@ public:
void hideCursor();
void setCursor(uint16 id);
void setDefaultCursor();
+ bool hasSource() const { return true; }
private:
MohawkEngine_Myst *_vm;
MystBitmap *_bmpDecoder;
};
+#endif // ENABLE_MYST
-// The cursor manager for Riven
-// Uses hardcoded cursors
-class RivenCursorManager : public CursorManager {
-public:
- RivenCursorManager() {}
- ~RivenCursorManager() {}
-
- void setCursor(uint16 id);
- void setDefaultCursor();
-};
-
-// The cursor manager for NE exe's
+// The cursor manager for NE EXE's
class NECursorManager : public CursorManager {
public:
NECursorManager(const Common::String &appName);
~NECursorManager();
void setCursor(uint16 id);
+ bool hasSource() const { return _exe != 0; }
private:
Common::NEResources *_exe;
@@ -151,6 +146,7 @@ public:
~MacCursorManager();
void setCursor(uint16 id);
+ bool hasSource() const { return _resFork != 0; }
private:
Common::MacResManager *_resFork;
@@ -164,11 +160,25 @@ public:
~LivingBooksCursorManager_v2();
void setCursor(uint16 id);
+ bool hasSource() const { return _sysArchive != 0; }
private:
MohawkArchive *_sysArchive;
};
+// The cursor manager for PE EXE's
+class PECursorManager : public CursorManager {
+public:
+ PECursorManager(const Common::String &appName);
+ ~PECursorManager();
+
+ void setCursor(uint16 id);
+ bool hasSource() const { return _exe != 0; }
+
+private:
+ Common::PEResources *_exe;
+};
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 51e4f89189..cad24b55f1 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -30,10 +30,19 @@
#include "common/file.h"
#include "common/savefile.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven.h"
#include "mohawk/livingbooks.h"
+
+#ifdef ENABLE_CSTIME
#include "mohawk/cstime.h"
+#endif
+
+#ifdef ENABLE_MYST
+#include "mohawk/myst.h"
+#endif
+
+#ifdef ENABLE_RIVEN
+#include "mohawk/riven.h"
+#endif
namespace Mohawk {
@@ -78,6 +87,8 @@ bool MohawkEngine::hasFeature(EngineFeature f) const {
(f == kSupportsRTL);
}
+#ifdef ENABLE_MYST
+
bool MohawkEngine_Myst::hasFeature(EngineFeature f) const {
return
MohawkEngine::hasFeature(f)
@@ -85,6 +96,10 @@ bool MohawkEngine_Myst::hasFeature(EngineFeature f) const {
|| (f == kSupportsSavingDuringRuntime);
}
+#endif
+
+#ifdef ENABLE_RIVEN
+
bool MohawkEngine_Riven::hasFeature(EngineFeature f) const {
return
MohawkEngine::hasFeature(f)
@@ -92,6 +107,8 @@ bool MohawkEngine_Riven::hasFeature(EngineFeature f) const {
|| (f == kSupportsSavingDuringRuntime);
}
+#endif
+
} // End of Namespace Mohawk
static const PlainGameDescriptor mohawkGames[] = {
@@ -104,15 +121,16 @@ static const PlainGameDescriptor mohawkGames[] = {
{"csworld", "Where in the World is Carmen Sandiego?"},
{"csamtrak", "Where in America is Carmen Sandiego? (The Great Amtrak Train Adventure)"},
{"carmentq", "Carmen Sandiego's ThinkQuick Challenge"},
+ {"carmentqc", "Carmen Sandiego's ThinkQuick Challenge Custom Question Creator"},
{"maggiesfa", "Maggie's Farmyard Adventure"},
{"jamesmath", "James Discovers/Explores Math"},
{"treehouse", "The Treehouse"},
{"greeneggs", "Green Eggs and Ham"},
- {"seussabc", "Dr Seuss ABC"},
+ {"seussabc", "Dr Seuss's ABC"},
{"1stdegree", "In the 1st Degree"},
{"csusa", "Where in the USA is Carmen Sandiego?"},
{"tortoise", "Aesop's Fables: The Tortoise and the Hare"},
- {"arthur", "Arthur's Teacher Troubles"},
+ {"arthur", "Arthur's Teacher Trouble"},
{"grandma", "Just Grandma and Me"},
{"ruff", "Ruff's Bone"},
{"newkid", "The New Kid on the Block"},
@@ -124,6 +142,9 @@ static const PlainGameDescriptor mohawkGames[] = {
{"lbsampler", "Living Books Sampler"},
{"bearfight", "The Berenstain Bears Get in a Fight"},
{"arthurcomp", "Arthur's Computer Adventure"},
+ {"harryhh","Harry and the Haunted House"},
+ {"stellaluna", "Stellaluna"},
+ {"sheila", "Sheila Rae, the Brave"},
{0, 0}
};
@@ -228,11 +249,21 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
switch (gd->gameType) {
case Mohawk::GType_MYST:
case Mohawk::GType_MAKINGOF:
+#ifdef ENABLE_MYST
*engine = new Mohawk::MohawkEngine_Myst(syst, gd);
break;
+#else
+ warning("Myst support not compiled in");
+ return false;
+#endif
case Mohawk::GType_RIVEN:
+#ifdef ENABLE_RIVEN
*engine = new Mohawk::MohawkEngine_Riven(syst, gd);
break;
+#else
+ warning("Riven support not compiled in");
+ return false;
+#endif
case Mohawk::GType_LIVINGBOOKSV1:
case Mohawk::GType_LIVINGBOOKSV2:
case Mohawk::GType_LIVINGBOOKSV3:
@@ -241,8 +272,13 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
*engine = new Mohawk::MohawkEngine_LivingBooks(syst, gd);
break;
case Mohawk::GType_CSTIME:
+#ifdef ENABLE_CSTIME
*engine = new Mohawk::MohawkEngine_CSTime(syst, gd);
break;
+#else
+ warning("CSTime support not compiled in");
+ return false;
+#endif
case Mohawk::GType_ZOOMBINI:
case Mohawk::GType_CSWORLD:
case Mohawk::GType_CSAMTRAK:
@@ -250,10 +286,10 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
case Mohawk::GType_TREEHOUSE:
case Mohawk::GType_1STDEGREE:
case Mohawk::GType_CSUSA:
- error ("Unsupported Mohawk Engine");
- break;
+ warning("Unsupported Mohawk Engine");
+ return false;
default:
- error ("Unknown Mohawk Engine");
+ error("Unknown Mohawk Engine");
}
}
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index ae37a22dd3..a8f9ee557b 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -522,6 +522,77 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // Harry and the Haunted House v1.0E
+ // English Windows 3.11
+ // From strangerke
+ {
+ {
+ "harryhh",
+ "",
+ AD_ENTRY1("HHHB.LB", "267bb6e3c8f237ca98b02c07b9c4013f"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
+ // Harry and the Haunted House v1.0E
+ // French Windows 3.11
+ // From strangerke
+ {
+ {
+ "harryhh",
+ "",
+ AD_ENTRY1("HHHF.LB", "7e5da86f19935bdf8fa89bbd39446543"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
+ // Harry and the Haunted House v1.0E
+ // German Windows 3.11
+ // From strangerke
+ {
+ {
+ "harryhh",
+ "",
+ AD_ENTRY1("HHHD.LB", "85c0a816efeb679739158789befb2be8"),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
+ // Harry and the Haunted House 1.1
+ // From pacifist
+ {
+ {
+ "harryhh",
+ "",
+ AD_ENTRY1("HARRY.512", "8d786f0998f27e44603a2202d6786c25"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "HARRY.EXE"
+ },
+
{
{
"carmentq",
@@ -539,6 +610,21 @@ static const MohawkGameDescription gameDescriptions[] = {
{
{
+ "carmentqc",
+ "",
+ AD_ENTRY1("Outline.txt", "6a281eefe72987afb0f8fb6cf84553f5"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV5,
+ 0,
+ 0
+ },
+
+ {
+ {
"maggiesfa",
"",
AD_ENTRY1("Outline", "b7dc6e65fa9e80784a5bb8b557aa37c4"),
@@ -798,6 +884,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"TORTOISE.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "tortoise",
+ "Demo v1.1",
+ AD_ENTRY1("TORTOISE.512", "14400a3358a3f1148e4d4b47bc3523c9"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "TORTOISE.EXE"
+ },
+
{
{
"tortoise",
@@ -858,6 +960,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"ARTHUR.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "arthur",
+ "Demo v1.1",
+ AD_ENTRY1("ARTHUR.512", "dabdd466dea26ab5ecb9415cf73f8601"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "ARTHUR.EXE"
+ },
+
{
{
"arthur",
@@ -888,6 +1006,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"Living Books Player"
},
+ // Just Grandma and Me 2.0
+ // From pacifist
+ {
+ {
+ "grandma",
+ "v2.0",
+ AD_ENTRY1("OUTLINE", "159c18b663c58d1aa17ad5e1ab1f0e12"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
{
{
"grandma",
@@ -918,6 +1053,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"GRANDMA.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "grandma",
+ "Demo v1.1",
+ AD_ENTRY1("GRANDMA.512", "4f616647245bb4e37e6dab7557dad304"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "GRANDMA.EXE"
+ },
+
{
{
"grandma",
@@ -948,6 +1099,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"Living Books Player"
},
+ // Ruff's Bone 1.0
+ // From pacifist
+ {
+ {
+ "ruff",
+ "",
+ AD_ENTRY1("RUFF.512", "3dbda0de6f47a64d1714d89f5a5f60d1"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "RUFF.EXE"
+ },
+
{
{
"ruff",
@@ -963,6 +1131,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"RUFF.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "ruff",
+ "Demo",
+ AD_ENTRY1("RUFF.512", "07b9d013e2400d61ca268892a76de4d2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "RUFF.EXE"
+ },
+
{
{
"ruff",
@@ -1008,6 +1192,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"NEWKID.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "newkid",
+ "Demo v1.1",
+ AD_ENTRY1("NEWKID.512", "de576f3481f62e84eda03b4d2307492b"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "NEWKID.EXE"
+ },
+
{
{
"newkid",
@@ -1069,6 +1269,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"BIRTHDAY.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "arthurbday",
+ "Demo",
+ AD_ENTRY1("BIRTHDAY.512", "2946b1e06f59ea607b8b29dfc6ba8976"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "BIRTHDAY.EXE"
+ },
+
{
{
"arthurbday",
@@ -1114,6 +1330,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"Little Monster at School"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "lilmonster",
+ "Demo",
+ AD_ENTRY1("MONSTER.512", "029e57f1fc8dd1f93f6623a1841f0df2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "MONSTER.EXE"
+ },
+
{
{
"catinthehat",
@@ -1156,7 +1388,7 @@ static const MohawkGameDescription gameDescriptions[] = {
},
GType_LIVINGBOOKSV4,
0,
- 0,
+ 0
},
{
@@ -1171,7 +1403,25 @@ static const MohawkGameDescription gameDescriptions[] = {
},
GType_LIVINGBOOKSV4,
0,
+ 0
+ },
+
+ // Rugrats Adventure Game
+ // French Windows
+ // From Strangerke
+ {
+ {
+ "rugrats",
+ "",
+ AD_ENTRY1("outline", "36225e0b4986a80135cfdd9643cc7030"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV4,
0,
+ 0
},
{
@@ -1325,6 +1575,40 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // Stellaluna 1.0
+ // From pacifist
+ {
+ {
+ "stellaluna",
+ "",
+ AD_ENTRY1("STELLA.LB", "763bb4a4721aebb5af316ca8e1b478ed"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
+ // Sheila Rae the Brave 1.0
+ // From pacifist
+ {
+ {
+ "sheila",
+ "",
+ AD_ENTRY1("SHEILA.LB", "c28a60f615a46384d9a8941fc5c89d63"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
{ AD_TABLE_END_MARKER, 0, 0, 0 }
};
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index f1a5586127..c5a0c7e86d 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -24,21 +24,27 @@
*/
#include "mohawk/mohawk.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven.h"
#include "mohawk/dialogs.h"
#include "gui/gui-manager.h"
#include "common/savefile.h"
#include "common/translation.h"
+#ifdef ENABLE_MYST
+#include "mohawk/myst.h"
+#endif
+
+#ifdef ENABLE_RIVEN
+#include "mohawk/riven.h"
+#endif
+
namespace Mohawk {
// This used to have GUI::Dialog("MohawkDummyDialog"), but that doesn't work with the gui branch merge :P (Sorry, Tanoku!)
InfoDialog::InfoDialog(MohawkEngine *vm, const Common::String &message) : _vm(vm), GUI::Dialog(0, 0, 1, 1), _message(message) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
- _text = new GUI::StaticTextWidget(this, 4, 4, 10, 10, _message, Graphics::kTextAlignCenter);
+ _text = new GUI::StaticTextWidget(this, 0, 0, 10, 10, _message, Graphics::kTextAlignCenter);
}
void InfoDialog::setInfoText(const Common::String &message) {
@@ -58,7 +64,7 @@ void InfoDialog::reflowLayout() {
_x = (screenW - width) / 2;
_y = (screenH - height) / 2;
- _text->setSize(_w - 8, _h);
+ _text->setSize(_w, _h);
}
PauseDialog::PauseDialog(MohawkEngine *vm, const Common::String &message) : InfoDialog(vm, message) {
@@ -77,6 +83,8 @@ enum {
kWaterCmd = 'WATR'
};
+#ifdef ENABLE_MYST
+
MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
_transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
@@ -111,6 +119,10 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
}
}
+#endif
+
+#ifdef ENABLE_RIVEN
+
RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
_waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd);
@@ -125,17 +137,17 @@ RivenOptionsDialog::~RivenOptionsDialog() {
void RivenOptionsDialog::open() {
Dialog::open();
- _zipModeCheckbox->setState(*_vm->getVar("azip") != 0);
- _waterEffectCheckbox->setState(*_vm->getVar("waterenabled") != 0);
+ _zipModeCheckbox->setState(_vm->_vars["azip"] != 0);
+ _waterEffectCheckbox->setState(_vm->_vars["waterenabled"] != 0);
}
void RivenOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kZipCmd:
- *_vm->getVar("azip") = _zipModeCheckbox->getState() ? 1 : 0;
+ _vm->_vars["azip"] = _zipModeCheckbox->getState() ? 1 : 0;
break;
case kWaterCmd:
- *_vm->getVar("waterenabled") = _waterEffectCheckbox->getState() ? 1 : 0;
+ _vm->_vars["waterenabled"] = _waterEffectCheckbox->getState() ? 1 : 0;
break;
case GUI::kCloseCmd:
close();
@@ -145,4 +157,6 @@ void RivenOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, u
}
}
+#endif
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index d4e3a3331b..106a1566fc 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -38,8 +38,6 @@
namespace Mohawk {
class MohawkEngine;
-class MohawkEngine_Myst;
-class MohawkEngine_Riven;
class InfoDialog : public GUI::Dialog {
protected:
@@ -71,6 +69,10 @@ public:
virtual void handleKeyDown(Common::KeyState state);
};
+#ifdef ENABLE_MYST
+
+class MohawkEngine_Myst;
+
class MystOptionsDialog : public GUI::OptionsDialog {
public:
MystOptionsDialog(MohawkEngine_Myst *vm);
@@ -84,6 +86,12 @@ private:
GUI::CheckboxWidget *_transitionsCheckbox;
};
+#endif
+
+#ifdef ENABLE_RIVEN
+
+class MohawkEngine_Riven;
+
class RivenOptionsDialog : public GUI::OptionsDialog {
public:
RivenOptionsDialog(MohawkEngine_Riven *vm);
@@ -97,6 +105,8 @@ private:
GUI::CheckboxWidget *_waterEffectCheckbox;
};
+#endif
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index be2fe01c4d..81d2b6f019 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -25,17 +25,26 @@
#include "mohawk/resource.h"
#include "mohawk/graphics.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven.h"
#include "mohawk/livingbooks.h"
-#include "mohawk/cstime.h"
#include "common/substream.h"
#include "engines/util.h"
-#include "graphics/jpeg.h"
#include "graphics/primitives.h"
#include "gui/message.h"
+#ifdef ENABLE_CSTIME
+#include "mohawk/cstime.h"
+#endif
+
+#ifdef ENABLE_MYST
+#include "mohawk/myst.h"
+#include "graphics/jpeg.h"
+#endif
+
+#ifdef ENABLE_RIVEN
+#include "mohawk/riven.h"
+#endif
+
namespace Mohawk {
MohawkSurface::MohawkSurface() : _surface(0), _palette(0) {
@@ -73,9 +82,9 @@ void MohawkSurface::convertToTrueColor() {
for (uint16 i = 0; i < _surface->h; i++) {
for (uint16 j = 0; j < _surface->w; j++) {
byte palIndex = *((byte *)_surface->pixels + i * _surface->pitch + j);
- byte r = _palette[palIndex * 4];
- byte g = _palette[palIndex * 4 + 1];
- byte b = _palette[palIndex * 4 + 2];
+ byte r = _palette[palIndex * 3 + 0];
+ byte g = _palette[palIndex * 3 + 1];
+ byte b = _palette[palIndex * 3 + 2];
if (pixelFormat.bytesPerPixel == 2)
*((uint16 *)surface->getBasePtr(j, i)) = pixelFormat.RGBToColor(r, g, b);
else
@@ -136,13 +145,13 @@ void GraphicsManager::setPalette(uint16 id) {
uint16 colorStart = tpalStream->readUint16BE();
uint16 colorCount = tpalStream->readUint16BE();
- byte *palette = new byte[colorCount * 4];
+ byte *palette = new byte[colorCount * 3];
for (uint16 i = 0; i < colorCount; i++) {
- palette[i * 4] = tpalStream->readByte();
- palette[i * 4 + 1] = tpalStream->readByte();
- palette[i * 4 + 2] = tpalStream->readByte();
- palette[i * 4 + 3] = tpalStream->readByte();
+ palette[i * 3 + 0] = tpalStream->readByte();
+ palette[i * 3 + 1] = tpalStream->readByte();
+ palette[i * 3 + 2] = tpalStream->readByte();
+ tpalStream->readByte();
}
delete tpalStream;
@@ -246,6 +255,15 @@ void GraphicsManager::copyAnimImageSectionToScreen(MohawkSurface *image, Common:
getVM()->_system->unlockScreen();
}
+void GraphicsManager::addImageToCache(uint16 id, MohawkSurface *surface) {
+ if (_cache.contains(id))
+ error("Image %d already in cache", id);
+
+ _cache[id] = surface;
+}
+
+#ifdef ENABLE_MYST
+
MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) {
_bmpDecoder = new MystBitmap();
@@ -611,6 +629,10 @@ void MystGraphics::drawLine(const Common::Point &p1, const Common::Point &p2, ui
_backBuffer->drawLine(p1.x, p1.y, p2.x, p2.y, color);
}
+#endif // ENABLE_MYST
+
+#ifdef ENABLE_RIVEN
+
RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm) {
_bitmapDecoder = new MohawkBitmap();
@@ -630,6 +652,9 @@ RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm
_scheduledTransition = -1; // no transition
_dirtyScreen = false;
_inventoryDrawn = false;
+
+ _creditsImage = 302;
+ _creditsPos = 0;
}
RivenGraphics::~RivenGraphics() {
@@ -748,7 +773,7 @@ void RivenGraphics::clearWaterEffects() {
bool RivenGraphics::runScheduledWaterEffects() {
// Don't run the effect if it's disabled
- if (*_vm->getVar("waterenabled") == 0)
+ if (_vm->_vars["waterenabled"] == 0)
return false;
Graphics::Surface *screen = NULL;
@@ -840,6 +865,17 @@ void RivenGraphics::runScheduledTransition() {
_scheduledTransition = -1; // Clear scheduled transition
}
+void RivenGraphics::clearMainScreen() {
+ _mainScreen->fillRect(Common::Rect(0, 0, 608, 392), _pixelFormat.RGBToColor(0, 0, 0));
+}
+
+void RivenGraphics::fadeToBlack() {
+ // Self-explanatory
+ scheduleTransition(16);
+ clearMainScreen();
+ runScheduledTransition();
+}
+
void RivenGraphics::showInventory() {
// Don't redraw the inventory
if (_inventoryDrawn)
@@ -864,8 +900,8 @@ void RivenGraphics::showInventory() {
// you get Catherine's journal and the trap book. Near the end,
// you lose the trap book and have just the two journals.
- bool hasCathBook = *_vm->getVar("acathbook") != 0;
- bool hasTrapBook = *_vm->getVar("atrapbook") != 0;
+ bool hasCathBook = _vm->_vars["acathbook"] != 0;
+ bool hasTrapBook = _vm->_vars["atrapbook"] != 0;
if (!hasCathBook) {
drawInventoryImage(101, g_atrusJournalRect1);
@@ -955,8 +991,64 @@ void RivenGraphics::drawExtrasImage(uint16 id, Common::Rect dstRect) {
_dirtyScreen = true;
}
+void RivenGraphics::beginCredits() {
+ // Clear the old cache
+ clearCache();
+
+ // Now cache all the credits images
+ for (uint16 i = 302; i <= 320; i++) {
+ MohawkSurface *surface = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, i));
+ surface->convertToTrueColor();
+ addImageToCache(i, surface);
+ }
+
+ // And clear our screen too
+ clearMainScreen();
+}
+
+void RivenGraphics::updateCredits() {
+ if ((_creditsImage == 303 || _creditsImage == 304) && _creditsPos == 0)
+ fadeToBlack();
+
+ if (_creditsImage < 304) {
+ // For the first two credit images, they are faded from black to the image and then out again
+ scheduleTransition(16);
+
+ Graphics::Surface *frame = findImage(_creditsImage++)->getSurface();
+
+ for (int y = 0; y < frame->h; y++)
+ memcpy(_mainScreen->getBasePtr(124, y), frame->getBasePtr(0, y), frame->pitch);
+
+ runScheduledTransition();
+ } else {
+ // Otheriwse, we're scrolling
+ // Move the screen up one row
+ memmove(_mainScreen->pixels, _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1));
+
+ // Only update as long as we're not before the last frame
+ // Otherwise, we're just moving up a row (which we already did)
+ if (_creditsImage <= 320) {
+ // Copy the next row to the bottom of the screen
+ Graphics::Surface *frame = findImage(_creditsImage)->getSurface();
+ memcpy(_mainScreen->getBasePtr(124, _mainScreen->h - 1), frame->getBasePtr(0, _creditsPos), frame->pitch);
+ _creditsPos++;
+
+ if (_creditsPos == _mainScreen->h) {
+ _creditsImage++;
+ _creditsPos = 0;
+ }
+ }
+
+ // Now flush the new screen
+ _vm->_system->copyRectToScreen((byte *)_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
+ _vm->_system->updateScreen();
+ }
+}
+
+#endif // ENABLE_RIVEN
+
LBGraphics::LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height) : GraphicsManager(), _vm(vm) {
- _bmpDecoder = _vm->isPreMohawk() ? new OldMohawkBitmap() : new MohawkBitmap();
+ _bmpDecoder = _vm->isPreMohawk() ? new LivingBooksBitmap_v1() : new MohawkBitmap();
initGraphics(width, height, true);
}
@@ -1005,13 +1097,13 @@ void LBGraphics::setPalette(uint16 id) {
if (_vm->isPreMohawk()) {
Common::SeekableSubReadStreamEndian *ctblStream = _vm->wrapStreamEndian(ID_CTBL, id);
uint16 colorCount = ctblStream->readUint16();
- byte *palette = new byte[colorCount * 4];
+ byte *palette = new byte[colorCount * 3];
for (uint16 i = 0; i < colorCount; i++) {
- palette[i * 4] = ctblStream->readByte();
- palette[i * 4 + 1] = ctblStream->readByte();
- palette[i * 4 + 2] = ctblStream->readByte();
- palette[i * 4 + 3] = ctblStream->readByte();
+ palette[i * 3 + 0] = ctblStream->readByte();
+ palette[i * 3 + 1] = ctblStream->readByte();
+ palette[i * 3 + 2] = ctblStream->readByte();
+ ctblStream->readByte();
}
delete ctblStream;
@@ -1023,6 +1115,8 @@ void LBGraphics::setPalette(uint16 id) {
}
}
+#ifdef ENABLE_CSTIME
+
CSTimeGraphics::CSTimeGraphics(MohawkEngine_CSTime *vm) : GraphicsManager(), _vm(vm) {
_bmpDecoder = new MohawkBitmap();
@@ -1055,4 +1149,6 @@ Common::Array<MohawkSurface *> CSTimeGraphics::decodeImages(uint16 id) {
return _bmpDecoder->decodeImages(_vm->getResource(ID_TBMH, id));
}
+#endif
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index 89189d442a..5cac68c510 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -33,26 +33,14 @@
#include "graphics/pict.h"
namespace Graphics {
-
-class JPEG;
-
+ class JPEG;
}
namespace Mohawk {
class MohawkEngine;
-class MohawkEngine_Myst;
-class MohawkEngine_Riven;
class MohawkEngine_LivingBooks;
-class MohawkEngine_CSTime;
class MohawkBitmap;
-class MystBitmap;
-
-enum RectState{
- kRectEnabled,
- kRectDisabled,
- kRectUnreachable
-};
class MohawkSurface {
public:
@@ -110,6 +98,7 @@ protected:
virtual Common::Array<MohawkSurface *> decodeImages(uint16 id);
virtual MohawkEngine *getVM() = 0;
+ void addImageToCache(uint16 id, MohawkSurface *surface);
private:
// An image cache that stores images until clearCache() is called
@@ -117,6 +106,17 @@ private:
Common::HashMap<uint16, Common::Array<MohawkSurface*> > _subImageCache;
};
+#ifdef ENABLE_MYST
+
+class MystBitmap;
+class MohawkEngine_Myst;
+
+enum RectState {
+ kRectEnabled,
+ kRectDisabled,
+ kRectUnreachable
+};
+
class MystGraphics : public GraphicsManager {
public:
MystGraphics(MohawkEngine_Myst*);
@@ -161,17 +161,11 @@ private:
Common::Rect _viewport;
};
-struct SFXERecord {
- // Record values
- uint16 frameCount;
- Common::Rect rect;
- uint16 speed;
- Common::Array<Common::SeekableReadStream*> frameScripts;
+#endif // ENABLE_MYST
- // Cur frame
- uint16 curFrame;
- uint32 lastFrameTime;
-};
+#ifdef ENABLE_RIVEN
+
+class MohawkEngine_Riven;
class RivenGraphics : public GraphicsManager {
public:
@@ -195,11 +189,17 @@ public:
// Transitions
void scheduleTransition(uint16 id, Common::Rect rect = Common::Rect(0, 0, 608, 392));
void runScheduledTransition();
+ void fadeToBlack();
// Inventory
void showInventory();
void hideInventory();
+ // Credits
+ void beginCredits();
+ void updateCredits();
+ uint getCurCreditsImage() { return _creditsImage; }
+
protected:
MohawkSurface *decodeImage(uint16 id);
MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
@@ -209,6 +209,17 @@ private:
MohawkBitmap *_bitmapDecoder;
// Water Effects
+ struct SFXERecord {
+ // Record values
+ uint16 frameCount;
+ Common::Rect rect;
+ uint16 speed;
+ Common::Array<Common::SeekableReadStream*> frameScripts;
+
+ // Cur frame
+ uint16 curFrame;
+ uint32 lastFrameTime;
+ };
Common::Array<SFXERecord> _waterEffects;
// Transitions
@@ -224,8 +235,14 @@ private:
Graphics::Surface *_mainScreen;
bool _dirtyScreen;
Graphics::PixelFormat _pixelFormat;
+ void clearMainScreen();
+
+ // Credits
+ uint _creditsImage, _creditsPos;
};
+#endif // ENABLE_RIVEN
+
class LBGraphics : public GraphicsManager {
public:
LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height);
@@ -244,6 +261,10 @@ private:
MohawkEngine_LivingBooks *_vm;
};
+#ifdef ENABLE_CSTIME
+
+class MohawkEngine_CSTime;
+
class CSTimeGraphics : public GraphicsManager {
public:
CSTimeGraphics(MohawkEngine_CSTime *vm);
@@ -261,6 +282,8 @@ private:
MohawkEngine_CSTime *_vm;
};
+#endif
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp
index 560d99e121..4ea742dff6 100644
--- a/engines/mohawk/installer_archive.cpp
+++ b/engines/mohawk/installer_archive.cpp
@@ -40,11 +40,6 @@ InstallerArchive::~InstallerArchive() {
close();
}
-struct DirectoryEntry {
- uint16 fileCount;
- Common::String name;
-};
-
bool InstallerArchive::open(const Common::String &filename) {
close();
@@ -60,68 +55,55 @@ bool InstallerArchive::open(const Common::String &filename) {
return false;
}
- // Let's move to the directory
+ // Let's pull some relevant data from the header
_stream->seek(41);
- uint32 offset = _stream->readUint32LE();
- _stream->seek(offset);
+ uint32 directoryTableOffset = _stream->readUint32LE();
+ /* uint32 directoryTableSize = */ _stream->readUint32LE();
+ uint16 directoryCount = _stream->readUint16LE();
+ uint32 fileTableOffset = _stream->readUint32LE();
+ /* uint32 fileTableSize = */ _stream->readUint32LE();
+
+ // We need to have at least one directory in order for the archive to be valid
+ if (directoryCount == 0) {
+ close();
+ return false;
+ }
- // Now read in each file from the directory
+ // TODO: Currently, we only support getting files from the first directory
+ // To that end, get the number of files from that entry
+ _stream->seek(directoryTableOffset);
uint16 fileCount = _stream->readUint16LE();
debug(2, "File count = %d", fileCount);
- _stream->skip(9);
-
- Common::Array<DirectoryEntry> directories;
-
- for (uint16 i = 0; i < fileCount;) {
- uint16 dirFileCount = _stream->readUint16LE();
+ // Following the directory table is the file table with files stored recursively
+ // by directory. Since we're only using the first directory, we can just go
+ // right to that one.
+ _stream->seek(fileTableOffset);
- if (dirFileCount == 0) {
- // We've found a file
- FileEntry entry;
+ for (uint16 i = 0; i < fileCount; i++) {
+ FileEntry entry;
- _stream->skip(1); // Unknown
+ _stream->skip(3); // Unknown
- entry.uncompressedSize = _stream->readUint32LE();
- entry.compressedSize = _stream->readUint32LE();
- entry.offset = _stream->readUint32LE();
+ entry.uncompressedSize = _stream->readUint32LE();
+ entry.compressedSize = _stream->readUint32LE();
+ entry.offset = _stream->readUint32LE();
- _stream->skip(14); // Unknown
+ _stream->skip(14); // Unknown
- byte nameLength = _stream->readByte();
- Common::String name;
- while (nameLength--)
- name += _stream->readByte();
+ byte nameLength = _stream->readByte();
+ Common::String name;
+ while (nameLength--)
+ name += _stream->readByte();
- _stream->skip(13); // Unknown
+ _stream->skip(13); // Unknown
- _map[name] = entry;
- i++;
+ _map[name] = entry;
- debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
- entry.offset, entry.compressedSize, entry.uncompressedSize);
- } else {
- // We've found a directory
- DirectoryEntry dirEntry;
-
- dirEntry.fileCount = dirFileCount;
- /* uint16 entrySize = */ _stream->readUint16LE();
-
- uint16 nameLength = _stream->readUint16LE();
- while (nameLength--)
- dirEntry.name += _stream->readByte();
-
- directories.push_back(dirEntry);
-
- _stream->skip(5); // Unknown
-
- debug(3, "Ignoring directory '%s'", dirEntry.name.c_str());
- }
+ debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
+ entry.offset, entry.compressedSize, entry.uncompressedSize);
}
- // TODO: Handle files in directories
- // Per directory found follows DirectoryEntry::fileCount files
-
return true;
}
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index 45c430e7e8..556210cb43 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -36,6 +36,8 @@
#include "engines/util.h"
+#include "gui/message.h"
+
namespace Mohawk {
// read a null-terminated string from a stream
@@ -70,6 +72,48 @@ Common::Rect MohawkEngine_LivingBooks::readRect(Common::SeekableSubReadStreamEnd
return rect;
}
+LBPage::LBPage(MohawkEngine_LivingBooks *vm) : _vm(vm) {
+ _code = NULL;
+ _mhk = NULL;
+
+ _baseId = 0;
+ _cascade = false;
+}
+
+void LBPage::open(MohawkArchive *mhk, uint16 baseId) {
+ _mhk = mhk;
+ _baseId = baseId;
+
+ _vm->addArchive(_mhk);
+ if (_vm->hasResource(ID_BCOD, baseId))
+ _code = new LBCode(_vm, baseId);
+
+ loadBITL(baseId);
+ for (uint i = 0; i < _items.size(); i++)
+ _vm->addItem(_items[i]);
+
+ for (uint32 i = 0; i < _items.size(); i++)
+ _items[i]->init();
+}
+
+void LBPage::itemDestroyed(LBItem *item) {
+ for (uint i = 0; i < _items.size(); i++)
+ if (item == _items[i]) {
+ _items.remove_at(i);
+ return;
+ }
+ error("itemDestroyed didn't find item");
+}
+
+LBPage::~LBPage() {
+ delete _code;
+ _vm->removeItems(_items);
+ for (uint i = 0; i < _items.size(); i++)
+ delete _items[i];
+ _vm->removeArchive(_mhk);
+ delete _mhk;
+}
+
MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
_needsUpdate = false;
_needsRedraw = false;
@@ -80,11 +124,11 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa
_alreadyShowedIntro = false;
- _code = NULL;
-
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "livingbooks");
+ _page = NULL;
+
const Common::FSNode gameDataDir(ConfMan.get("path"));
// Rugrats
SearchMan.addSubDirectoryMatching(gameDataDir, "program");
@@ -115,6 +159,9 @@ Common::Error MohawkEngine_LivingBooks::run() {
debug("Starting Living Books Title \'%s\'", _title.c_str());
if (!_copyright.empty())
debug("Copyright: %s", _copyright.c_str());
+ debug("This book has %d page(s) in %d language(s).", _numPages, _numLanguages);
+ if (_poetryMode)
+ debug("Running in poetry mode.");
if (!_screenWidth || !_screenHeight)
error("Could not find xRes/yRes variables");
@@ -173,8 +220,7 @@ Common::Error MohawkEngine_LivingBooks::run() {
case Common::KEYCODE_ESCAPE:
if (_curMode == kLBIntroMode)
- if (!loadPage(kLBControlMode, 1, 1))
- loadPage(kLBControlMode, 1, 0);
+ tryLoadPageStart(kLBControlMode, 1);
break;
case Common::KEYCODE_LEFT:
@@ -268,21 +314,18 @@ Common::String MohawkEngine_LivingBooks::stringForMode(LBMode mode) {
void MohawkEngine_LivingBooks::destroyPage() {
_sound->stopSound();
+ _lastSoundOwner = 0;
+ _lastSoundId = 0;
+ _soundLockOwner = 0;
+
_gfx->clearCache();
_video->stopVideos();
_eventQueue.clear();
- delete _code;
- _code = NULL;
-
- for (uint32 i = 0; i < _items.size(); i++)
- delete _items[i];
- _items.clear();
-
- for (uint32 i = 0; i < _mhk.size(); i++)
- delete _mhk[i];
- _mhk.clear();
+ delete _page;
+ assert(_items.empty());
+ _page = NULL;
_notifyEvents.clear();
@@ -300,26 +343,42 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
else
base = Common::String::format("Page%d", page);
- Common::String filename;
+ Common::String filename, leftover;
- filename = getFileNameFromConfig(name, base);
+ filename = getFileNameFromConfig(name, base, leftover);
_readOnly = false;
if (filename.empty()) {
- filename = getFileNameFromConfig(name, base + ".r");
+ leftover.clear();
+ filename = getFileNameFromConfig(name, base + ".r", leftover);
_readOnly = true;
}
// TODO: fading between pages
bool fade = false;
- if (filename.hasSuffix(" fade")) {
+ if (leftover.contains("fade")) {
fade = true;
- filename = Common::String(filename.c_str(), filename.size() - 5);
+ }
+ if (leftover.contains("read")) {
+ _readOnly = true;
+ }
+ if (leftover.contains("load")) {
+ // FIXME: don't ignore this
+ warning("ignoring 'load' for filename '%s'", filename.c_str());
+ }
+ if (leftover.contains("cut")) {
+ // FIXME: don't ignore this
+ warning("ignoring 'cut' for filename '%s'", filename.c_str());
+ }
+ if (leftover.contains("killgag")) {
+ // FIXME: don't ignore this
+ warning("ignoring 'killgag' for filename '%s'", filename.c_str());
}
MohawkArchive *pageArchive = createMohawkArchive();
if (!filename.empty() && pageArchive->open(filename)) {
- _mhk.push_back(pageArchive);
+ _page = new LBPage(this);
+ _page->open(pageArchive, 1000);
} else {
delete pageArchive;
debug(2, "Could not find page %d.%d for '%s'", page, subpage, name.c_str());
@@ -337,7 +396,7 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
}
}
- debug(1, "Stack Version: %d", getResourceVersion());
+ debug(1, "Page Version: %d", _page->getResourceVersion());
_curMode = mode;
_curPage = page;
@@ -347,13 +406,6 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
_gfx->setPalette(1000);
- if (hasResource(ID_BCOD, 1000))
- _code = new LBCode(this);
-
- loadBITL(1000);
- for (uint32 i = 0; i < _items.size(); i++)
- _items[i]->init();
-
_phase = 0;
_introDone = false;
@@ -378,10 +430,6 @@ void MohawkEngine_LivingBooks::updatePage() {
// hard-coded control page startup
LBItem *item;
- item = getItemById(10);
- if (item)
- item->togglePlaying(false);
-
uint16 page = _curPage;
if (getFeatures() & GF_LB_10) {
// Living Books 1.0 had the meanings of these pages reversed
@@ -473,6 +521,12 @@ void MohawkEngine_LivingBooks::updatePage() {
for (uint32 i = 0; i < _items.size(); i++)
_items[i]->startPhase(_phase);
+ if (_curMode == kLBControlMode) {
+ LBItem *item = getItemById(10);
+ if (item)
+ item->togglePlaying(false);
+ }
+
_phase++;
break;
@@ -496,7 +550,9 @@ void MohawkEngine_LivingBooks::updatePage() {
switch (delayedEvent.type) {
case kLBDelayedEventDestroy:
_items.remove_at(i);
+ i--;
delete delayedEvent.item;
+ _page->itemDestroyed(delayedEvent.item);
if (_focus == delayedEvent.item)
_focus = NULL;
break;
@@ -524,6 +580,39 @@ void MohawkEngine_LivingBooks::updatePage() {
}
}
+void MohawkEngine_LivingBooks::addArchive(MohawkArchive *archive) {
+ _mhk.push_back(archive);
+}
+
+void MohawkEngine_LivingBooks::removeArchive(MohawkArchive *archive) {
+ for (uint i = 0; i < _mhk.size(); i++) {
+ if (archive != _mhk[i])
+ continue;
+ _mhk.remove_at(i);
+ return;
+ }
+
+ error("removeArchive didn't find archive");
+}
+
+void MohawkEngine_LivingBooks::addItem(LBItem *item) {
+ _items.push_back(item);
+}
+
+void MohawkEngine_LivingBooks::removeItems(const Common::Array<LBItem *> &items) {
+ for (uint i = 0; i < items.size(); i++) {
+ bool found = false;
+ for (uint16 j = 0; j < _items.size(); j++) {
+ if (items[i] != _items[j])
+ continue;
+ found = true;
+ _items.remove_at(j);
+ break;
+ }
+ assert(found);
+ }
+}
+
LBItem *MohawkEngine_LivingBooks::getItemById(uint16 id) {
for (uint16 i = 0; i < _items.size(); i++)
if (_items[i]->getId() == id)
@@ -532,6 +621,14 @@ LBItem *MohawkEngine_LivingBooks::getItemById(uint16 id) {
return NULL;
}
+LBItem *MohawkEngine_LivingBooks::getItemByName(Common::String name) {
+ for (uint16 i = 0; i < _items.size(); i++)
+ if (_items[i]->getName() == name)
+ return _items[i];
+
+ return NULL;
+}
+
void MohawkEngine_LivingBooks::setFocus(LBItem *focus) {
_focus = focus;
}
@@ -551,12 +648,60 @@ void MohawkEngine_LivingBooks::queueDelayedEvent(DelayedEvent event) {
_eventQueue.push(event);
}
-// Only 1 VSRN resource per stack, Id 1000
-uint16 MohawkEngine_LivingBooks::getResourceVersion() {
- Common::SeekableReadStream *versionStream = getResource(ID_VRSN, 1000);
+bool MohawkEngine_LivingBooks::playSound(LBItem *source, uint16 resourceId) {
+ if (_lastSoundId && !_sound->isPlaying(_lastSoundId))
+ _lastSoundId = 0;
+
+ if (!source->isAmbient() || !_sound->isPlaying()) {
+ if (!_soundLockOwner) {
+ if (_lastSoundId && _lastSoundOwner != source->getId())
+ if (source->getSoundPriority() >= _lastSoundPriority)
+ return false;
+ } else {
+ if (_soundLockOwner != source->getId() && source->getSoundPriority() >= _maxSoundPriority)
+ return false;
+ }
+
+ if (_lastSoundId)
+ _sound->stopSound(_lastSoundId);
+
+ _lastSoundOwner = source->getId();
+ _lastSoundPriority = source->getSoundPriority();
+ }
+
+ _lastSoundId = resourceId;
+ _sound->playSound(resourceId);
+
+ return true;
+}
+
+void MohawkEngine_LivingBooks::lockSound(LBItem *owner, bool lock) {
+ if (!lock) {
+ _soundLockOwner = 0;
+ return;
+ }
+
+ if (_soundLockOwner || (owner->isAmbient() && _sound->isPlaying()))
+ return;
+
+ if (_lastSoundId && !_sound->isPlaying(_lastSoundId))
+ _lastSoundId = 0;
+ _soundLockOwner = owner->getId();
+ _maxSoundPriority = owner->getSoundPriority();
+ if (_lastSoundId && _maxSoundPriority <= _lastSoundPriority) {
+ _sound->stopSound(_lastSoundId);
+ _lastSoundId = 0;
+ }
+}
+
+// Only 1 VSRN resource per page
+uint16 LBPage::getResourceVersion() {
+ Common::SeekableReadStream *versionStream = _vm->getResource(ID_VRSN, _baseId);
+
+ // FIXME: some V2 games have very strange version entries
if (versionStream->size() != 2)
- warning("Version Record size mismatch");
+ debug(1, "Version Record size mismatch");
uint16 version = versionStream->readUint16BE();
@@ -564,40 +709,43 @@ uint16 MohawkEngine_LivingBooks::getResourceVersion() {
return version;
}
-void MohawkEngine_LivingBooks::loadBITL(uint16 resourceId) {
- Common::SeekableSubReadStreamEndian *bitlStream = wrapStreamEndian(ID_BITL, resourceId);
+void LBPage::loadBITL(uint16 resourceId) {
+ Common::SeekableSubReadStreamEndian *bitlStream = _vm->wrapStreamEndian(ID_BITL, resourceId);
while (true) {
- Common::Rect rect = readRect(bitlStream);
+ Common::Rect rect = _vm->readRect(bitlStream);
uint16 type = bitlStream->readUint16();
LBItem *res;
switch (type) {
case kLBPictureItem:
- res = new LBPictureItem(this, rect);
+ res = new LBPictureItem(_vm, this, rect);
break;
case kLBAnimationItem:
- res = new LBAnimationItem(this, rect);
+ res = new LBAnimationItem(_vm, this, rect);
break;
case kLBPaletteItem:
- res = new LBPaletteItem(this, rect);
+ res = new LBPaletteItem(_vm, this, rect);
break;
case kLBGroupItem:
- res = new LBGroupItem(this, rect);
+ res = new LBGroupItem(_vm, this, rect);
break;
case kLBSoundItem:
- res = new LBSoundItem(this, rect);
+ res = new LBSoundItem(_vm, this, rect);
break;
case kLBLiveTextItem:
- res = new LBLiveTextItem(this, rect);
+ res = new LBLiveTextItem(_vm, this, rect);
break;
case kLBMovieItem:
- res = new LBMovieItem(this, rect);
+ res = new LBMovieItem(_vm, this, rect);
+ break;
+ case kLBMiniGameItem:
+ res = new LBMiniGameItem(_vm, this, rect);
break;
default:
warning("Unknown item type %04x", type);
case 3: // often used for buttons
- res = new LBItem(this, rect);
+ res = new LBItem(_vm, this, rect);
break;
}
@@ -615,17 +763,27 @@ Common::SeekableSubReadStreamEndian *MohawkEngine_LivingBooks::wrapStreamEndian(
}
Common::String MohawkEngine_LivingBooks::getStringFromConfig(const Common::String &section, const Common::String &key) {
+ Common::String x, leftover;
+ _bookInfoFile.getKey(key, section, x);
+ Common::String tmp = removeQuotesFromString(x, leftover);
+ if (!leftover.empty())
+ warning("while parsing config key '%s' from section '%s', string '%s' was left after '%s'",
+ key.c_str(), section.c_str(), leftover.c_str(), tmp.c_str());
+ return tmp;
+}
+
+Common::String MohawkEngine_LivingBooks::getStringFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover) {
Common::String x;
_bookInfoFile.getKey(key, section, x);
- return removeQuotesFromString(x);
+ return removeQuotesFromString(x, leftover);
}
int MohawkEngine_LivingBooks::getIntFromConfig(const Common::String &section, const Common::String &key) {
return atoi(getStringFromConfig(section, key).c_str());
}
-Common::String MohawkEngine_LivingBooks::getFileNameFromConfig(const Common::String &section, const Common::String &key) {
- Common::String string = getStringFromConfig(section, key);
+Common::String MohawkEngine_LivingBooks::getFileNameFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover) {
+ Common::String string = getStringFromConfig(section, key, leftover);
Common::String x;
uint32 i = 0;
@@ -640,17 +798,23 @@ Common::String MohawkEngine_LivingBooks::getFileNameFromConfig(const Common::Str
return (getPlatform() == Common::kPlatformMacintosh) ? convertMacFileName(x) : convertWinFileName(x);
}
-Common::String MohawkEngine_LivingBooks::removeQuotesFromString(const Common::String &string) {
- // The last char isn't necessarily a quote, the line could have "fade" in it
- // (which is then handled in loadPage).
+Common::String MohawkEngine_LivingBooks::removeQuotesFromString(const Common::String &string, Common::String &leftover) {
+ if (string.empty())
+ return string;
- // Some versions wrap in quotations, some don't...
- Common::String tmp = string;
- for (uint32 i = 0; i < tmp.size(); i++) {
- if (tmp[i] == '\"') {
- tmp.deleteChar(i);
- i--;
- }
+ char quoteChar = string[0];
+ if (quoteChar != '\"' && quoteChar != '\'')
+ return string;
+
+ Common::String tmp;
+ bool inLeftover = false;
+ for (uint32 i = 1; i < string.size(); i++) {
+ if (inLeftover)
+ leftover += string[i];
+ else if (string[i] == quoteChar)
+ inLeftover = true;
+ else
+ tmp += string[i];
}
return tmp;
@@ -675,6 +839,8 @@ Common::String MohawkEngine_LivingBooks::convertWinFileName(const Common::String
Common::String filename;
for (uint32 i = 0; i < string.size(); i++) {
+ if (i == 0 && (string[i] == '/' || string[i] == '\\')) // ignore slashes at start
+ continue;
if (string[i] == '\\')
filename += '/';
else
@@ -713,20 +879,18 @@ bool MohawkEngine_LivingBooks::tryDefaultPage() {
if (_curMode == kLBCreditsMode || _curMode == kLBPreviewMode) {
// go to options page
if (getFeatures() & GF_LB_10) {
- if (loadPage(kLBControlMode, 2, 0))
+ if (tryLoadPageStart(kLBControlMode, 2))
return true;
} else {
- if (loadPage(kLBControlMode, 3, 0))
+ if (tryLoadPageStart(kLBControlMode, 3))
return true;
}
- } else {
- // go to menu page
- if (loadPage(kLBControlMode, 1, 1))
- return true;
- if (loadPage(kLBControlMode, 1, 0))
- return true;
}
+ // go to menu page
+ if (tryLoadPageStart(kLBControlMode, 1))
+ return true;
+
return false;
}
@@ -760,9 +924,11 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
switch (controlId) {
case 1:
if (getFeatures() & GF_LB_10) {
- loadPage(kLBControlMode, 2, 0);
+ if (!tryLoadPageStart(kLBControlMode, 2))
+ error("couldn't load options page");
} else {
- loadPage(kLBControlMode, 3, 0);
+ if (!tryLoadPageStart(kLBControlMode, 3))
+ error("couldn't load options page");
}
break;
@@ -776,7 +942,7 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
item = getItemById(199 + _curLanguage);
if (item) {
item->setVisible(true);
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
}
break;
@@ -790,15 +956,17 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
item = getItemById(12);
if (item) {
item->setVisible(true);
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
}
break;
case 4:
if (getFeatures() & GF_LB_10) {
- loadPage(kLBControlMode, 3, 0);
+ if (!tryLoadPageStart(kLBControlMode, 3))
+ error("couldn't load quit page");
} else {
- loadPage(kLBControlMode, 2, 0);
+ if (!tryLoadPageStart(kLBControlMode, 2))
+ error("couldn't load quit page");
}
break;
@@ -807,21 +975,22 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
if (item)
item->destroySelf();
item = getItemById(11);
- if (item)
+ if (item) {
item->setVisible(true);
- if (item)
item->togglePlaying(false);
+ }
break;
case 11:
item = getItemById(11);
if (item)
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
break;
case 12:
// start game, in play mode
- loadPage(kLBPlayMode, 1, 0);
+ if (!tryLoadPageStart(kLBPlayMode, 1))
+ error("couldn't start play mode");
break;
default:
@@ -835,7 +1004,8 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
_curLanguage = newLanguage;
} else if (controlId >= 200 && controlId < 200 + (uint)_numLanguages) {
// start game, in read mode
- loadPage(kLBReadMode, 1, 0);
+ if (!tryLoadPageStart(kLBReadMode, 1))
+ error("couldn't start read mode");
}
break;
}
@@ -864,7 +1034,6 @@ void MohawkEngine_LivingBooks::handleUIPoetryMenuClick(uint controlId) {
break;
case 7:
- case 0xA:
item = getItemById(10);
if (item)
item->destroySelf();
@@ -874,14 +1043,25 @@ void MohawkEngine_LivingBooks::handleUIPoetryMenuClick(uint controlId) {
item = getItemById(12);
if (item) {
item->setVisible(true);
- item->togglePlaying(controlId == 7);
+ item->togglePlaying(false, true);
+ }
+ break;
+
+ case 0xA:
+ item = getItemById(10);
+ if (item)
+ item->destroySelf();
+ item = getItemById(11);
+ if (item) {
+ item->setVisible(true);
+ item->togglePlaying(false);
}
break;
case 0xB:
- item = getItemById(12);
+ item = getItemById(11);
if (item)
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
break;
case 0xC:
@@ -923,7 +1103,7 @@ void MohawkEngine_LivingBooks::handleUIQuitClick(uint controlId) {
case 11:
item = getItemById(11);
if (item)
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
break;
case 12:
@@ -933,7 +1113,8 @@ void MohawkEngine_LivingBooks::handleUIQuitClick(uint controlId) {
case 13:
// 'no', go back to menu
- loadPage(kLBControlMode, 1, 0);
+ if (!tryLoadPageStart(kLBControlMode, 1))
+ error("couldn't return to menu");
break;
}
}
@@ -949,7 +1130,7 @@ void MohawkEngine_LivingBooks::handleUIOptionsClick(uint controlId) {
item = getItemById(202);
if (item) {
item->setVisible(true);
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
}
break;
@@ -994,11 +1175,13 @@ void MohawkEngine_LivingBooks::handleUIOptionsClick(uint controlId) {
break;
case 4:
- loadPage(kLBCreditsMode, 1, 0);
+ if (!tryLoadPageStart(kLBCreditsMode, 1))
+ error("failed to start credits");
break;
case 5:
- loadPage(kLBPreviewMode, 1, 0);
+ if (!tryLoadPageStart(kLBPreviewMode, 1))
+ error("failed to start preview");
break;
case 202:
@@ -1055,7 +1238,7 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) {
case kLBNotifyGoToControls:
debug(2, "kLBNotifyGoToControls: %d", event.param);
- if (!loadPage(kLBControlMode, 1, 0))
+ if (!tryLoadPageStart(kLBControlMode, 1))
error("couldn't load controls page");
break;
@@ -1085,7 +1268,7 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) {
case kLBNotifyGotoQuit:
debug(2, "kLBNotifyGotoQuit: %d", event.param);
- if (!loadPage(kLBControlMode, 2, 0))
+ if (!tryLoadPageStart(kLBControlMode, 2))
error("couldn't load quit page");
break;
@@ -1119,9 +1302,10 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) {
if (!event.newMode)
event.newMode = _curMode;
if (!loadPage((LBMode)event.newMode, event.newPage, event.newSubpage)) {
- if (event.newSubpage != 0 || !loadPage((LBMode)event.newMode, event.newPage, 1))
- error("kLBNotifyChangeMode failed to move to mode %d, page %d.%d",
- event.newMode, event.newPage, event.newSubpage);
+ if (event.newPage != 0 || !loadPage((LBMode)event.newMode, _curPage, event.newSubpage))
+ if (event.newSubpage != 0 || !loadPage((LBMode)event.newMode, event.newPage, 1))
+ error("kLBNotifyChangeMode failed to move to mode %d, page %d.%d",
+ event.newMode, event.newPage, event.newSubpage);
}
}
break;
@@ -1247,11 +1431,17 @@ NodeState LBAnimationNode::update(bool seeking) {
break;
}
- assert(entry.size == 4);
- uint16 strLen = READ_BE_UINT16(entry.data + 2);
-
- if (strLen)
- error("String length for unnamed wave file");
+ Common::String cue;
+ uint pos = 2;
+ while (pos < entry.size) {
+ char in = entry.data[pos];
+ if (!in)
+ break;
+ pos++;
+ cue += in;
+ }
+ if (pos == entry.size)
+ error("Cue in sound kLBAnimOp wasn't null-terminated");
switch (entry.opcode) {
case kLBAnimOpPlaySound:
@@ -1264,7 +1454,7 @@ NodeState LBAnimationNode::update(bool seeking) {
if (seeking)
break;
debug(4, "b: WaitForSound(%0d)", soundResourceId);
- if (!_parent->soundPlaying(soundResourceId))
+ if (!_parent->soundPlaying(soundResourceId, cue))
break;
_currentEntry--;
return kLBNodeWaiting;
@@ -1597,6 +1787,11 @@ void LBAnimation::seek(uint16 pos) {
_lastTime = 0;
_currentFrame = 0;
+ if (_currentSound != 0xffff) {
+ _vm->_sound->stopSound(_currentSound);
+ _currentSound = 0xffff;
+ }
+
for (uint32 i = 0; i < _nodes.size(); i++)
_nodes[i]->reset();
@@ -1625,11 +1820,27 @@ void LBAnimation::stop() {
void LBAnimation::playSound(uint16 resourceId) {
_currentSound = resourceId;
- _vm->_sound->playSound(_currentSound);
+ _vm->_sound->playSound(_currentSound, Audio::Mixer::kMaxChannelVolume, false, &_cueList);
}
-bool LBAnimation::soundPlaying(uint16 resourceId) {
- return _currentSound == resourceId && _vm->_sound->isPlaying(_currentSound);
+bool LBAnimation::soundPlaying(uint16 resourceId, const Common::String &cue) {
+ if (_currentSound != resourceId)
+ return false;
+ if (!_vm->_sound->isPlaying(_currentSound))
+ return false;
+
+ if (cue.empty())
+ return true;
+
+ uint samples = _vm->_sound->getNumSamplesPlayed(_currentSound);
+ for (uint i = 0; i < _cueList.pointCount; i++) {
+ if (_cueList.points[i].sampleFrame > samples)
+ break;
+ if (_cueList.points[i].name == cue)
+ return false;
+ }
+
+ return true;
}
bool LBAnimation::transparentAt(int x, int y) {
@@ -1662,7 +1873,7 @@ LBScriptEntry::~LBScriptEntry() {
delete subentries[i];
}
-LBItem::LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : _vm(vm), _rect(rect) {
+LBItem::LBItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : _vm(vm), _page(page), _rect(rect) {
_phase = 0;
_loopMode = 0;
@@ -1685,6 +1896,7 @@ LBItem::LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : _vm(vm), _rect
_loops = 0;
_isAmbient = false;
+ _doHitTest = true;
}
LBItem::~LBItem() {
@@ -1790,6 +2002,11 @@ LBScriptEntry *LBItem::parseScriptEntry(uint16 type, uint16 &size, Common::Seeka
warning("ignoring target '%s' in script entry", target.c_str());
size -= target.size() + 1;
}
+
+ if (size % 2 == 1) {
+ stream->skip(1);
+ size--;
+ }
}
if (entry->argc) {
@@ -1810,17 +2027,19 @@ LBScriptEntry *LBItem::parseScriptEntry(uint16 type, uint16 &size, Common::Seeka
}
}
- if (type == kLBMsgListScript && entry->opcode == 0xfffb) {
- uint16 u1 = stream->readUint16();
- uint16 u2 = stream->readUint16();
- uint16 u3 = stream->readUint16();
- warning("unknown 0xfffb: %04x, %04x, %04x", u1, u2, u3);
+ if (type == kLBMsgListScript && entry->opcode == kLBOpJumpUnlessExpression) {
+ if (size < 6)
+ error("not enough bytes (%d) in kLBOpJumpUnlessExpression, event 0x%04x", size, entry->event);
+ entry->offset = stream->readUint32();
+ entry->target = stream->readUint16();
+ debug(4, "kLBOpJumpUnlessExpression: offset %08x, target %d", entry->offset, entry->target);
size -= 6;
}
- if (type == kLBMsgListScript && entry->opcode == 0xfffd) {
- uint16 u1 = stream->readUint16();
- uint16 u2 = stream->readUint16();
- warning("unknown 0xfffd: %04x, %04x", u1, u2);
+ if (type == kLBMsgListScript && entry->opcode == kLBOpJumpToExpression) {
+ if (size < 4)
+ error("not enough bytes (%d) in kLBOpJumpToExpression, event 0x%04x", size, entry->event);
+ entry->offset = stream->readUint32();
+ debug(4, "kLBOpJumpToExpression: offset %08x", entry->offset);
size -= 4;
}
@@ -1880,8 +2099,8 @@ LBScriptEntry *LBItem::parseScriptEntry(uint16 type, uint16 &size, Common::Seeka
error("not enough bytes (%d) in kLBEventNotified, opcode 0x%04x", size, entry->opcode);
entry->matchFrom = stream->readUint16();
entry->matchNotify = stream->readUint16();
- debug(4, "kLBEventNotified: unknowns %04x, %04x",
- entry->matchFrom, entry->matchNotify);
+ debug(4, "kLBEventNotified: matches %04x (from %04x)",
+ entry->matchNotify, entry->matchFrom);
size -= 4;
}
@@ -1964,22 +2183,22 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd
debug(2, "kLBSetPlayPhase: %d", _phase);
break;
- case kLBUnknown6F:
+ case kLBSetKeyNotify:
{
+ // FIXME: variable-size notifies, targets
if (size != 18)
error("0x6f had wrong size (%d)", size);
- uint u1 = stream->readUint16();
- uint u2 = stream->readUint16();
uint event = stream->readUint16();
+ LBKey key;
+ stream->read(&key, 4);
uint opcode = stream->readUint16();
uint param = stream->readUint16();
uint u6 = stream->readUint16();
uint u7 = stream->readUint16();
uint u8 = stream->readUint16();
uint u9 = stream->readUint16();
- // FIXME: this is scripting stuff
- warning("0x6f: unknown: item %s, unknowns: %04x, %04x, event %04x, opcode %04x, param %04x, unknowns %04x, %04x, %04x, %04x",
- _desc.c_str(), u1, u2, event, opcode, param, u6, u7, u8, u9);
+ warning("ignoring kLBSetKeyNotify: item %s, key code %02x (modifier mask %d, char %d, repeat %d), event %04x, opcode %04x, param %04x, unknowns %04x, %04x, %04x, %04x",
+ _desc.c_str(), key.code, key.modifiers, key.char_, key.repeats, event, opcode, param, u6, u7, u8, u9);
}
break;
@@ -2013,28 +2232,28 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd
_isAmbient = true;
break;
- case kLBUnknown7D:
+ case kLBSetKeyEvent:
{
+ // FIXME: targets
if (size != 10)
- error("0x7d had wrong size (%d)", size);
- uint u1 = stream->readUint16();
- uint key = stream->readUint16();
+ error("kLBSetKeyEvent had wrong size (%d)", size);
uint u3 = stream->readUint16();
+ LBKey key;
+ stream->read(&key, 4);
uint target = stream->readUint16();
- byte event = stream->readByte();
- byte u4 = stream->readByte();
+ uint16 event = stream->readUint16();
// FIXME: this is scripting stuff: what to run when key is pressed
- warning("0x7d: unknown: item %s, unknown %04x, key %04x, unknown %04x, target %d, event %02x, unknown %02x",
- _desc.c_str(), u1, key, u3, target, event, u4);
+ warning("ignoring kLBSetKeyEvent: item %s, key code %02x (modifier mask %d, char %d, repeat %d) unknown %04x, target %d, event %04x",
+ _desc.c_str(), key.code, key.modifiers, key.char_, key.repeats, u3, target, event);
}
break;
- case kLBUnknown80:
+ case kLBSetHitTest:
{
assert(size == 2);
- uint id = stream->readUint16();
- warning("0x80: unknown: item %s, id %04x", _desc.c_str(), id);
- // FIXME
+ uint val = stream->readUint16();
+ _doHitTest = (bool)val;
+ debug(2, "kLBSetHitTest (on %s): value %04x", _desc.c_str(), val);
}
break;
@@ -2042,9 +2261,9 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd
{
assert(size == 4);
uint offset = stream->readUint32();
- if (!_vm->_code)
+ if (!_page->_code)
error("no BCOD?");
- _vm->_code->runCode(this, offset);
+ _page->_code->runCode(this, offset);
}
break;
@@ -2148,7 +2367,7 @@ bool LBItem::togglePlaying(bool playing, bool restart) {
if (_controlMode >= kLBControlHideMouse) {
debug(2, "Hiding cursor");
_vm->_cursor->hideCursor();
- // TODO: lock sound?
+ _vm->lockSound(this, true);
if (_controlMode >= kLBControlPauseItems) {
debug(2, "Disabling all");
@@ -2186,7 +2405,7 @@ void LBItem::done(bool onlyNotify) {
if (_controlMode >= kLBControlHideMouse) {
debug(2, "Showing cursor");
_vm->_cursor->showCursor();
- // TODO: unlock sound?
+ _vm->lockSound(this, false);
if (_controlMode >= kLBControlPauseItems) {
debug(2, "Enabling all");
@@ -2272,7 +2491,7 @@ void LBItem::stop() {
void LBItem::notify(uint16 data, uint16 from) {
if (_timingMode == kLBAutoSync) {
// TODO: is this correct?
- if (_periodMin == from && _periodMax == data) {
+ if (_periodMin == data && _periodMax == from) {
debug(2, "Handling notify 0x%04x (from %d)", data, from);
setNextTime(0, 0);
}
@@ -2289,7 +2508,7 @@ void LBItem::runScript(uint event, uint16 data, uint16 from) {
continue;
if (event == kLBEventNotified) {
- if (entry->matchFrom != from || entry->matchNotify != data)
+ if ((entry->matchFrom && entry->matchFrom != from) || entry->matchNotify != data)
continue;
}
@@ -2323,9 +2542,9 @@ void LBItem::runScript(uint event, uint16 data, uint16 from) {
}
}
-void LBItem::runScriptEntry(LBScriptEntry *entry) {
+int LBItem::runScriptEntry(LBScriptEntry *entry) {
if (entry->state == 0xffff)
- return;
+ return 0;
uint start = 0;
uint count = entry->argc;
@@ -2333,7 +2552,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
if (!count)
count = 1;
- switch (entry->param) {
+ if (entry->opcode != kLBOpRunSubentries) switch (entry->param) {
case 0xfffe:
// Run once (disable self after run).
entry->state = 0xffff;
@@ -2350,7 +2569,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
case 0:
// Disable..
entry->state = 0xffff;
- return;
+ return 0;
case 1:
// Stay at the end.
entry->state = count - 1;
@@ -2388,7 +2607,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
debug(2, "Target %04x (%04x) doesn't exist, skipping", targetId, param);
continue;
}
- debug(2, "Target: %04x (%04x) '%s'", targetId, param, _desc.c_str());
+ debug(2, "Target: %04x (%04x) '%s'", targetId, param, target->_desc.c_str());
} else {
target = this;
debug(2, "Self-target on '%s'", _desc.c_str());
@@ -2433,7 +2652,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
break;
case kLBOpRewind:
- target->seek(0);
+ target->seek(1);
break;
case kLBOpStop:
@@ -2511,16 +2730,31 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
break;
case kLBOpSendExpression:
- if (!_vm->_code)
+ if (!_page->_code)
error("no BCOD?");
- _vm->_code->runCode(this, entry->offset);
+ _page->_code->runCode(this, entry->offset);
break;
case kLBOpRunSubentries:
for (uint i = 0; i < entry->subentries.size(); i++) {
LBScriptEntry *subentry = entry->subentries[i];
- runScriptEntry(subentry);
+ int e = runScriptEntry(subentry);
+
+ switch (subentry->opcode) {
+ case kLBOpJumpUnlessExpression:
+ debug(2, "JumpUnless got %d (to %d, on %d, of %d)", e, subentry->target, i, entry->subentries.size());
+ if (!e)
+ i = subentry->target - 1;
+ break;
+ case kLBOpBreakExpression:
+ debug(2, "BreakExpression");
+ i = entry->subentries.size();
+ case kLBOpJumpToExpression:
+ debug(2, "JumpToExpression got %d (on %d, of %d)", e, i, entry->subentries.size());
+ i = e - 1;
+ break;
+ }
}
break;
@@ -2528,11 +2762,24 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
runCommand(entry->command);
break;
+ case kLBOpJumpUnlessExpression:
+ case kLBOpBreakExpression:
+ case kLBOpJumpToExpression:
+ if (!_page->_code)
+ error("no BCOD?");
+ {
+ LBValue r = _page->_code->runCode(this, entry->offset);
+ // FIXME
+ return r.integer;
+ }
+
default:
error("Unknown script opcode (type 0x%04x, event 0x%04x, opcode 0x%04x, param 0x%04x, target '%s')",
entry->type, entry->event, entry->opcode, entry->param, target->_desc.c_str());
}
}
+
+ return 0;
}
void LBItem::setNextTime(uint16 min, uint16 max) {
@@ -2544,24 +2791,6 @@ void LBItem::setNextTime(uint16 min, uint16 max, uint32 start) {
debug(9, "nextTime is now %d frames away", _nextTime - (uint)(_vm->_system->getMillis() / 16));
}
-bool LBValue::operator==(const LBValue &x) const {
- if (type != x.type) return false;
-
- switch (type) {
- case kLBValueString:
- return string == x.string;
-
- case kLBValueInteger:
- return integer == x.integer;
- default:
- error("Unknown type when testing for equality");
- }
-}
-
-bool LBValue::operator!=(const LBValue &x) const {
- return !(*this == x);
-}
-
enum LBTokenType {
kLBNoToken,
kLBNameToken,
@@ -2815,7 +3044,7 @@ bool LBItem::checkCondition(const Common::String &condition) {
return false; // unreachable
}
-LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBSoundItem");
_running = false;
}
@@ -2847,7 +3076,8 @@ bool LBSoundItem::togglePlaying(bool playing, bool restart) {
return false;
_running = true;
- _vm->_sound->playSound(_resourceId, Audio::Mixer::kMaxChannelVolume, false);
+ debug(4, "sound %d play for item %d (%s)", _resourceId, _itemId, _desc.c_str());
+ _vm->playSound(this, _resourceId);
return true;
}
@@ -2860,7 +3090,7 @@ void LBSoundItem::stop() {
LBItem::stop();
}
-LBGroupItem::LBGroupItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBGroupItem::LBGroupItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBGroupItem");
_starting = false;
}
@@ -2892,6 +3122,16 @@ void LBGroupItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStre
}
}
+void LBGroupItem::destroySelf() {
+ LBItem::destroySelf();
+
+ for (uint i = 0; i < _groupEntries.size(); i++) {
+ LBItem *item = _vm->getItemById(_groupEntries[i].entryId);
+ if (item)
+ item->destroySelf();
+ }
+}
+
void LBGroupItem::setEnabled(bool enabled) {
if (_starting) {
_starting = false;
@@ -2965,7 +3205,7 @@ void LBGroupItem::stop() {
}
}
-LBPaletteItem::LBPaletteItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBPaletteItem::LBPaletteItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBPaletteItem");
_fadeInStart = 0;
@@ -2988,8 +3228,17 @@ void LBPaletteItem::readData(uint16 type, uint16 size, Common::SeekableSubReadSt
if (_drawStart + _drawCount > 256)
error("encountered palette trying to set more than 256 colors");
assert(size == 8 + _drawCount * 4);
- _palette = new byte[_drawCount * 4];
- stream->read(_palette, _drawCount * 4);
+
+ // TODO: _drawCount is really more like _drawEnd, so once we're sure that
+ // there's really no use for the palette entries before _drawCount, we
+ // might want to just discard them here, at load time.
+ _palette = new byte[_drawCount * 3];
+ for (uint i = 0; i < _drawCount; i++) {
+ _palette[i*3 + 0] = stream->readByte();
+ _palette[i*3 + 1] = stream->readByte();
+ _palette[i*3 + 2] = stream->readByte();
+ stream->readByte();
+ }
}
break;
@@ -3027,7 +3276,7 @@ void LBPaletteItem::update() {
// TODO: actual fading-in
if (_visible && _globalVisible) {
- _vm->_system->getPaletteManager()->setPalette(_palette + _drawStart * 4, _drawStart, _drawCount);
+ _vm->_system->getPaletteManager()->setPalette(_palette + _drawStart * 3, _drawStart, _drawCount - _drawStart);
_vm->_needsRedraw = true;
}
}
@@ -3041,7 +3290,7 @@ void LBPaletteItem::update() {
LBItem::update();
}
-LBLiveTextItem::LBLiveTextItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBLiveTextItem::LBLiveTextItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
_currentPhrase = 0xFFFF;
_currentWord = 0xFFFF;
debug(3, "new LBLiveTextItem");
@@ -3133,6 +3382,11 @@ bool LBLiveTextItem::contains(Common::Point point) {
void LBLiveTextItem::paletteUpdate(uint16 word, bool on) {
_vm->_needsRedraw = true;
+ // Sometimes the last phrase goes out-of-bounds, the original engine
+ // only checks the words which are valid in the palette updating code.
+ if (word >= _words.size())
+ return;
+
if (_resourceId) {
// with a resource, we draw a bitmap in draw() rather than changing the palette
return;
@@ -3199,7 +3453,7 @@ void LBLiveTextItem::drawWord(uint word, uint yPos) {
}
void LBLiveTextItem::handleMouseDown(Common::Point pos) {
- if (_neverEnabled || !_enabled || !_globalEnabled || _currentPhrase != 0xFFFF)
+ if (_neverEnabled || !_enabled || !_globalEnabled || _playing)
return LBItem::handleMouseDown(pos);
pos.x -= _rect.left;
@@ -3218,7 +3472,7 @@ void LBLiveTextItem::handleMouseDown(Common::Point pos) {
return;
}
_currentWord = i;
- _vm->_sound->playSound(soundId);
+ _vm->playSound(this, soundId);
paletteUpdate(_currentWord, true);
return;
}
@@ -3231,16 +3485,13 @@ bool LBLiveTextItem::togglePlaying(bool playing, bool restart) {
if (!playing)
return LBItem::togglePlaying(playing, restart);
if (_neverEnabled || !_enabled || !_globalEnabled)
- return (_currentPhrase != 0xFFFF);
+ return _playing;
// TODO: handle this properly
_vm->_sound->stopSound();
_currentWord = 0xFFFF;
-
- // some LiveText items don't have any phrases!
- if (_phrases.size() > 0)
- _currentPhrase = 0;
+ _currentPhrase = 0xFFFF;
return true;
}
@@ -3252,7 +3503,7 @@ void LBLiveTextItem::stop() {
}
void LBLiveTextItem::notify(uint16 data, uint16 from) {
- if (_neverEnabled || !_enabled || !_globalEnabled || _currentPhrase == 0xFFFF)
+ if (_neverEnabled || !_enabled || !_globalEnabled || !_playing)
return LBItem::notify(data, from);
if (_currentWord != 0xFFFF) {
@@ -3270,8 +3521,10 @@ void LBLiveTextItem::notify(uint16 data, uint16 from) {
}
_currentPhrase = i;
// TODO: not sure this is the correct logic
- if (i == _phrases.size() - 1)
+ if (i == _phrases.size() - 1) {
_currentPhrase = 0xFFFF;
+ done(true);
+ }
} else if (_phrases[i].highlightEnd == data && _phrases[i].endId == from) {
debug(2, "Disabling phrase %d", i);
for (uint j = 0; j < _phrases[i].wordCount; j++) {
@@ -3284,7 +3537,7 @@ void LBLiveTextItem::notify(uint16 data, uint16 from) {
LBItem::notify(data, from);
}
-LBPictureItem::LBPictureItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBPictureItem::LBPictureItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBPictureItem");
}
@@ -3309,6 +3562,9 @@ bool LBPictureItem::contains(Common::Point point) {
if (!LBItem::contains(point))
return false;
+ if (!_doHitTest)
+ return true;
+
// TODO: only check pixels if necessary
return !_vm->_gfx->imageIsTransparentAt(_resourceId, false, point.x - _rect.left, point.y - _rect.top);
}
@@ -3324,7 +3580,7 @@ void LBPictureItem::draw() {
_vm->_gfx->copyAnimImageToScreen(_resourceId, _rect.left, _rect.top);
}
-LBAnimationItem::LBAnimationItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBAnimationItem::LBAnimationItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
_anim = NULL;
_running = false;
debug(3, "new LBAnimationItem");
@@ -3336,26 +3592,32 @@ LBAnimationItem::~LBAnimationItem() {
void LBAnimationItem::setEnabled(bool enabled) {
if (_running) {
- if (enabled && _neverEnabled)
+ if (enabled && _globalEnabled && _neverEnabled)
_anim->start();
else if (!_neverEnabled && !enabled && _enabled && _globalEnabled)
- if (_running) {
- _anim->stop();
- }
+ _anim->stop();
}
return LBItem::setEnabled(enabled);
}
bool LBAnimationItem::contains(Common::Point point) {
- return LBItem::contains(point) && !_anim->transparentAt(point.x, point.y);
+ if (!LBItem::contains(point))
+ return false;
+
+ if (!_doHitTest)
+ return true;
+
+ return !_anim->transparentAt(point.x, point.y);
}
void LBAnimationItem::update() {
if (!_neverEnabled && _enabled && _globalEnabled && _running) {
bool wasDone = _anim->update();
- if (wasDone)
+ if (wasDone) {
+ _running = false;
done(true);
+ }
}
LBItem::update();
@@ -3417,7 +3679,7 @@ void LBAnimationItem::draw() {
_anim->draw();
}
-LBMovieItem::LBMovieItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBMovieItem::LBMovieItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBMovieItem");
}
@@ -3446,4 +3708,39 @@ bool LBMovieItem::togglePlaying(bool playing, bool restart) {
return LBItem::togglePlaying(playing, restart);
}
+LBMiniGameItem::LBMiniGameItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
+ debug(3, "new LBMiniGameItem");
+}
+
+LBMiniGameItem::~LBMiniGameItem() {
+}
+
+bool LBMiniGameItem::togglePlaying(bool playing, bool restart) {
+ // HACK: Since we don't support any of these hardcoded mini games yet,
+ // just skip to the most logical page. For optional minigames, this
+ // will return the player to the previous page. For mandatory minigames,
+ // this will send the player to the next page.
+ // TODO: Document mini games from Arthur's Reading Race
+
+ uint16 destPage;
+
+ // Figure out what minigame we have and bring us back to a page where
+ // the player can continue
+ if (_desc == "Kitch") // Green Eggs and Ham: Kitchen minigame
+ destPage = 4;
+ else if (_desc == "Eggs") // Green Eggs and Ham: Eggs minigame
+ destPage = 5;
+ else if (_desc == "Fall") // Green Eggs and Ham: Fall minigame
+ destPage = 13;
+ else
+ error("Unknown minigame '%s'", _desc.c_str());
+
+ GUI::MessageDialog dialog(Common::String::format("The '%s' minigame is not supported yet.", _desc.c_str()));
+ dialog.runModal();
+
+ _vm->addNotifyEvent(NotifyEvent(kLBNotifyChangePage, destPage));
+
+ return false;
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 186502d532..cd3b206d57 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -29,6 +29,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/console.h"
#include "mohawk/graphics.h"
+#include "mohawk/sound.h"
#include "common/config-file.h"
#include "common/substream.h"
@@ -42,6 +43,17 @@
namespace Mohawk {
+#define LBKEY_MOD_CTRL 1
+#define LBKEY_MOD_ALT 2
+#define LBKEY_MOD_SHIFT 4
+
+struct LBKey {
+ byte code;
+ byte modifiers;
+ byte char_;
+ byte repeats;
+};
+
enum NodeState {
kLBNodeDone = 0,
kLBNodeRunning = 1,
@@ -88,6 +100,7 @@ enum {
kLBPaletteAItem = 0x44, // unused?
kLBPaletteItem = 0x45,
kLBProxyItem = 0x46,
+ kLBMiniGameItem = 666, // EVIL!!!!
kLBXDataFileItem = 0x3e9,
kLBDiscDectectorItem = 0xfa1
};
@@ -151,7 +164,7 @@ enum {
kLBSetOneShot = 0x6d, // unused?
kLBSetPlayPhase = 0x6e,
// from here, 2.x+
- kLBUnknown6F = 0x6f,
+ kLBSetKeyNotify = 0x6f,
kLBCommand = 0x70,
kLBPaletteAData = 0x71, // unused?
kLBPaletteXData = 0x72,
@@ -165,10 +178,10 @@ enum {
kLBGlobalSetVisible = 0x7a, // unused?
kLBSetAmbient = 0x7b,
kLBUnknown7C = 0x7c, // unused?
- kLBUnknown7D = 0x7d,
+ kLBSetKeyEvent = 0x7d,
kLBUnknown7E = 0x7e, // unused? (rect flag)
kLBSetParent = 0x7f, // unused?
- kLBUnknown80 = 0x80, // unused? TODO: sets +36
+ kLBSetHitTest = 0x80,
// from here, rugrats
kLBUnknown194 = 0x194
};
@@ -204,6 +217,9 @@ enum {
kLBOpScriptEnable = 0x1b,
kLBOpUnknown1C = 0x1c,
kLBOpSendExpression = 0x1d,
+ kLBOpJumpUnlessExpression = 0xfffb,
+ kLBOpBreakExpression = 0xfffc,
+ kLBOpJumpToExpression = 0xfffd,
kLBOpRunSubentries = 0xfffe,
kLBOpRunCommand = 0xffff
};
@@ -221,6 +237,7 @@ enum {
};
class MohawkEngine_LivingBooks;
+class LBPage;
class LBGraphics;
class LBAnimation;
@@ -251,6 +268,8 @@ struct LBScriptEntry {
// kLBOpSendExpression
uint32 offset;
+ // kLBOpJumpUnlessExpression
+ uint16 target;
Common::String command;
Common::Array<Common::String> conditions;
@@ -301,7 +320,7 @@ public:
void stop();
void playSound(uint16 resourceId);
- bool soundPlaying(uint16 resourceId);
+ bool soundPlaying(uint16 resourceId, const Common::String &cue);
bool transparentAt(int x, int y);
@@ -323,7 +342,10 @@ protected:
Common::Array<LBAnimationNode *> _nodes;
uint16 _tempo;
+
uint16 _currentSound;
+ CueList _cueList;
+
uint32 _lastTime, _currentFrame;
bool _running;
@@ -336,7 +358,7 @@ class LBItem {
friend class LBCode;
public:
- LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect);
+ LBItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect);
virtual ~LBItem();
void readFrom(Common::SeekableSubReadStreamEndian *stream);
@@ -364,9 +386,14 @@ public:
virtual void notify(uint16 data, uint16 from); // 0x1A
uint16 getId() { return _itemId; }
+ const Common::String &getName() { return _desc; }
+ const Common::Rect &getRect() { return _rect; }
+ uint16 getSoundPriority() { return _soundMode; }
+ bool isAmbient() { return _isAmbient; }
protected:
MohawkEngine_LivingBooks *_vm;
+ LBPage *_page;
void setNextTime(uint16 min, uint16 max);
void setNextTime(uint16 min, uint16 max, uint32 start);
@@ -387,10 +414,11 @@ protected:
Common::Point _relocPoint;
bool _isAmbient;
+ bool _doHitTest;
Common::Array<LBScriptEntry *> _scriptEntries;
void runScript(uint event, uint16 data = 0, uint16 from = 0);
- void runScriptEntry(LBScriptEntry *entry);
+ int runScriptEntry(LBScriptEntry *entry);
LBValue parseValue(const Common::String &command, uint &pos);
void runCommand(const Common::String &command);
@@ -401,7 +429,7 @@ protected:
class LBSoundItem : public LBItem {
public:
- LBSoundItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBSoundItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBSoundItem();
void update();
@@ -419,10 +447,11 @@ struct GroupEntry {
class LBGroupItem : public LBItem {
public:
- LBGroupItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBGroupItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
+ void destroySelf();
void setEnabled(bool enabled);
void setGlobalEnabled(bool enabled);
bool contains(Common::Point point);
@@ -442,7 +471,7 @@ protected:
class LBPaletteItem : public LBItem {
public:
- LBPaletteItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBPaletteItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBPaletteItem();
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
@@ -469,7 +498,7 @@ struct LiveTextPhrase {
class LBLiveTextItem : public LBItem {
public:
- LBLiveTextItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBLiveTextItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
@@ -498,7 +527,7 @@ protected:
class LBPictureItem : public LBItem {
public:
- LBPictureItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBPictureItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
@@ -509,7 +538,7 @@ public:
class LBAnimationItem : public LBItem {
public:
- LBAnimationItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBAnimationItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBAnimationItem();
void setEnabled(bool enabled);
@@ -530,15 +559,23 @@ protected:
class LBMovieItem : public LBItem {
public:
- LBMovieItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBMovieItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBMovieItem();
void update();
bool togglePlaying(bool playing, bool restart);
};
+class LBMiniGameItem : public LBItem {
+public:
+ LBMiniGameItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
+ ~LBMiniGameItem();
+
+ bool togglePlaying(bool playing, bool restart);
+};
+
struct NotifyEvent {
- NotifyEvent(uint t, uint p) : type(t), param(p) { }
+ NotifyEvent(uint t, uint p) : type(t), param(p), newUnknown(0), newMode(0), newPage(0), newSubpage(0) { }
uint type;
uint param;
@@ -561,6 +598,30 @@ struct DelayedEvent {
DelayedEventType type;
};
+class LBPage {
+public:
+ LBPage(MohawkEngine_LivingBooks *vm);
+ ~LBPage();
+
+ void open(MohawkArchive *mhk, uint16 baseId);
+ uint16 getResourceVersion();
+
+ void itemDestroyed(LBItem *item);
+
+ LBCode *_code;
+
+protected:
+ MohawkEngine_LivingBooks *_vm;
+
+ MohawkArchive *_mhk;
+ Common::Array<LBItem *> _items;
+
+ uint16 _baseId;
+ bool _cascade;
+
+ void loadBITL(uint16 resourceId);
+};
+
class MohawkEngine_LivingBooks : public MohawkEngine {
protected:
Common::Error run();
@@ -581,13 +642,22 @@ public:
Common::Rect readRect(Common::SeekableSubReadStreamEndian *stream);
GUI::Debugger *getDebugger() { return _console; }
+ void addArchive(MohawkArchive *archive);
+ void removeArchive(MohawkArchive *Archive);
+ void addItem(LBItem *item);
+ void removeItems(const Common::Array<LBItem *> &items);
+
LBItem *getItemById(uint16 id);
+ LBItem *getItemByName(Common::String name);
void setFocus(LBItem *focus);
void setEnableForAll(bool enable, LBItem *except = 0);
void notifyAll(uint16 data, uint16 from);
void queueDelayedEvent(DelayedEvent event);
+ bool playSound(LBItem *source, uint16 resourceId);
+ void lockSound(LBItem *owner, bool lock);
+
bool isBigEndian() const { return getGameType() != GType_LIVINGBOOKSV1 || getPlatform() == Common::kPlatformMacintosh; }
bool isPreMohawk() const;
@@ -597,11 +667,13 @@ public:
void prevPage();
void nextPage();
- LBCode *_code;
-
// TODO: make private
Common::HashMap<Common::String, LBValue> _variables;
+ // helper functions, also used by LBProxyItem
+ Common::String getFileNameFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover);
+ MohawkArchive *createMohawkArchive() const;
+
private:
LivingBooksConsole *_console;
Common::ConfigFile _bookInfoFile;
@@ -615,6 +687,7 @@ private:
LBMode _curMode;
uint16 _curPage, _curSubPage;
uint16 _phase;
+ LBPage *_page;
Common::Array<LBItem *> _items;
Common::Queue<DelayedEvent> _eventQueue;
LBItem *_focus;
@@ -622,8 +695,11 @@ private:
bool loadPage(LBMode mode, uint page, uint subpage);
void updatePage();
- uint16 getResourceVersion();
- void loadBITL(uint16 resourceId);
+ uint16 _lastSoundOwner, _lastSoundId;
+ uint16 _lastSoundPriority;
+ uint16 _soundLockOwner;
+ uint16 _maxSoundPriority;
+
void loadSHP(uint16 resourceId);
bool tryDefaultPage();
@@ -649,17 +725,14 @@ private:
bool _alreadyShowedIntro;
// String Manipulation Functions
- Common::String removeQuotesFromString(const Common::String &string);
+ Common::String removeQuotesFromString(const Common::String &string, Common::String &leftover);
Common::String convertMacFileName(const Common::String &string);
Common::String convertWinFileName(const Common::String &string);
// Configuration File Functions
Common::String getStringFromConfig(const Common::String &section, const Common::String &key);
+ Common::String getStringFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover);
int getIntFromConfig(const Common::String &section, const Common::String &key);
- Common::String getFileNameFromConfig(const Common::String &section, const Common::String &key);
-
- // Platform/Version functions
- MohawkArchive *createMohawkArchive() const;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/livingbooks_code.cpp b/engines/mohawk/livingbooks_code.cpp
index a11ac1cfe9..84f69af2ac 100644
--- a/engines/mohawk/livingbooks_code.cpp
+++ b/engines/mohawk/livingbooks_code.cpp
@@ -28,18 +28,119 @@
namespace Mohawk {
-LBCode::LBCode(MohawkEngine_LivingBooks *vm) : _vm(vm) {
- Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, 1000);
+bool LBValue::operator==(const LBValue &x) const {
+ if (type != x.type) {
+ if (isNumeric() && x.isNumeric())
+ return toDouble() == x.toDouble();
+ else
+ return false;
+ }
+
+ switch (type) {
+ case kLBValueString:
+ return string == x.string;
+ case kLBValueInteger:
+ return integer == x.integer;
+ case kLBValueReal:
+ return real == x.real;
+ case kLBValuePoint:
+ return point == x.point;
+ case kLBValueRect:
+ return rect == x.rect;
+ case kLBValueItemPtr:
+ return item == x.item;
+ default:
+ error("Unknown type when testing for equality");
+ }
+}
+
+bool LBValue::operator!=(const LBValue &x) const {
+ return !(*this == x);
+}
+
+bool LBValue::isNumeric() const {
+ if (type == kLBValueInteger || type == kLBValueReal)
+ return true;
+
+ // TODO: string checks
+
+ return false;
+}
+
+bool LBValue::isZero() const {
+ return toInt() == 0; // FIXME
+}
+
+Common::String LBValue::toString() const {
+ switch (type) {
+ case kLBValueString:
+ return string;
+ case kLBValueInteger:
+ return Common::String::format("%d", integer);
+ case kLBValueReal:
+ return Common::String::format("%f", real);
+ default:
+ return string; // FIXME
+ }
+}
+
+int LBValue::toInt() const {
+ return integer; // FIXME
+}
+
+double LBValue::toDouble() const {
+ return real; // FIXME
+}
+
+Common::Point LBValue::toPoint() const {
+ switch (type) {
+ case kLBValueString:
+ // FIXME
+ return Common::Point();
+ case kLBValueInteger:
+ return Common::Point(integer, integer);
+ case kLBValuePoint:
+ return point;
+ default:
+ error("failed to convert to point");
+ }
+}
+
+Common::Rect LBValue::toRect() const {
+ switch (type) {
+ case kLBValueString:
+ // FIXME
+ return Common::Rect();
+ case kLBValueInteger:
+ return Common::Rect(integer, integer, integer, integer);
+ case kLBValueRect:
+ return rect;
+ case kLBValueItemPtr:
+ return item->getRect();
+ default:
+ error("failed to convert to rect");
+ }
+}
+
+LBCode::LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId) : _vm(vm) {
+ Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, baseId);
+
uint32 totalSize = bcodStream->readUint32();
if (totalSize != (uint32)bcodStream->size())
error("BCOD had size %d, but claimed to be of size %d", bcodStream->size(), totalSize);
- size = bcodStream->readUint32();
- if (size + 8 > totalSize)
- error("BCOD code was of size %d, beyond size %d", size, totalSize);
- data = new byte[size];
- bcodStream->read(data, size);
+ _size = bcodStream->readUint32();
+ if (_size + 8 > totalSize)
+ error("BCOD code was of size %d, beyond size %d", _size, totalSize);
+
+ _data = new byte[_size];
+ bcodStream->read(_data, _size);
+
uint16 pos = 0;
while (bcodStream->pos() < bcodStream->size()) {
+ if (bcodStream->pos() + 1 == bcodStream->size()) {
+ warning("ran out of bytes while reading strings");
+ break;
+ }
uint16 unknown = bcodStream->readUint16();
if (unknown != 0) {
warning("unknown was %04x, not zero, while reading strings", unknown);
@@ -48,287 +149,812 @@ LBCode::LBCode(MohawkEngine_LivingBooks *vm) : _vm(vm) {
break;
}
Common::String string = _vm->readString(bcodStream);
- strings[pos] = string;
+ _strings[pos] = string;
debug(2, "read '%s' from BCOD at 0x%04x", string.c_str(), pos);
pos += 2 + string.size() + 1;
}
}
LBCode::~LBCode() {
- delete[] data;
+ delete[] _data;
}
-Common::Array<LBValue> LBCode::readParams(LBItem *src, uint32 &offset) {
- Common::Array<LBValue> params;
-
- if (offset + 1 >= size)
- error("went off the end of code");
+LBValue LBCode::runCode(LBItem *src, uint32 offset) {
+ // TODO: re-entrancy issues?
+ _currSource = src;
+ _currOffset = offset;
- byte numParams = data[offset];
- offset++;
+ return runCode(kTokenEndOfFile);
+}
- if (!numParams) {
- debugN("()\n");
- return params;
+void LBCode::nextToken() {
+ if (_currOffset + 1 >= _size) {
+ // TODO
+ warning("went off the end of code");
+ _currToken = kTokenEndOfFile;
+ _currValue = LBValue();
+ return;
}
- byte nextToken = data[offset];
- offset++;
- if (nextToken != kLBCodeTokenOpenBracket)
- error("missing ( before code parameter list (got %02x)", nextToken);
- debugN("(");
+ _currToken = _data[_currOffset++];
- for (uint i = 0; i < numParams; i++) {
- if (i != 0) {
- nextToken = data[offset];
- offset++;
- if (nextToken != ',')
- error("missing , between code parameters (got %02x)", nextToken);
- debugN(", ");
+ // We slurp any value associated with the parameter here too, to simplify things.
+ switch (_currToken) {
+ case kTokenIdentifier:
+ {
+ uint16 offset = READ_BE_UINT16(_data + _currOffset);
+ // TODO: check string exists
+ _currValue = _strings[offset];
+ _currOffset += 2;
}
+ break;
- nextToken = data[offset];
- offset++;
-
- LBValue nextValue;
-
- switch (nextToken) {
- case kLBCodeTokenLiteral:
- {
- byte literalType = data[offset];
- offset++;
- if (literalType == kLBCodeLiteralInteger) {
- uint16 intValue = READ_BE_UINT16(data + offset);
- offset += 2;
- nextValue.type = kLBValueInteger;
- nextValue.integer = intValue;
- debugN("%d", nextValue.integer);
- } else
- error("unknown literal type %02x in code", literalType);
- }
+ case kTokenLiteral:
+ {
+ byte literalType = _data[_currOffset++];
+ switch (literalType) {
+ case kLBCodeLiteralInteger:
+ _currValue = READ_BE_UINT16(_data + _currOffset);
+ _currOffset += 2;
break;
+ default:
+ error("unknown kTokenLiteral type %02x", literalType);
+ }
+ }
+ break;
- case kLBCodeTokenString:
- {
- uint16 stringOffset = READ_BE_UINT16(data + offset);
- offset += 2;
- // TODO: check string exists
- nextValue.type = kLBValueString;
- nextValue.string = strings[stringOffset];
- debugN("\"%s\"", nextValue.string.c_str());
- }
- break;
+ case kTokenConstMode:
+ case kTokenConstEventId:
+ case 0x5e: // TODO: ??
+ case kTokenKeycode:
+ _currValue = READ_BE_UINT16(_data + _currOffset);
+ _currOffset += 2;
+ break;
- case kLBCodeTokenChar:
- {
- uint16 stringOffset = READ_BE_UINT16(data + offset);
- offset += 2;
- // TODO: check string exists
- nextValue.type = kLBValueString;
- nextValue.string = strings[stringOffset];
- debugN("'%s'", nextValue.string.c_str());
- }
- break;
+ case kTokenGeneralCommand:
+ case kTokenItemCommand:
+ case kTokenNotifyCommand:
+ case kTokenPropListCommand:
+ case kTokenRectCommand:
+ _currValue = _data[_currOffset++];
+ //_currValue = READ_BE_UINT16(_data + _currOffset);
+ //_currOffset += 2;
+ break;
- case kLBCodeTokenLong: // FIXME: wrong?
- {
- uint32 intValue = READ_BE_UINT32(data + offset);
- offset += 4;
- nextValue.type = kLBValueInteger;
- nextValue.integer = intValue;
- debugN("%d", nextValue.integer);
- }
- break;
+ case kTokenString:
+ {
+ uint16 offset = READ_BE_UINT16(_data + _currOffset);
+ // TODO: check string exists
+ _currValue = _strings[offset];
+ _currOffset += 2;
+ }
+ break;
- case 0x31:
- {
- // TODO
- uint16 intValue = READ_BE_UINT16(data + offset);
- offset += 2;
- nextValue.type = kLBValueInteger;
- nextValue.integer = intValue;
- debugN("%d", nextValue.integer);
- }
- break;
+ default:
+ _currValue = LBValue();
+ break;
+ }
+}
- case 0x4d:
- // TODO
- runCodeCommand(src, offset);
- break;
+LBValue LBCode::runCode(byte terminator) {
+ LBValue result;
- case 0x5f:
- // keycode
- nextValue.type = kLBValueInteger;
- nextValue.integer = data[offset];
- debugN("%d", nextValue.integer);
- offset++;
- offset++; // TODO
+ while (true) {
+ nextToken();
+ if (_currToken == kTokenEndOfFile)
break;
+ parseStatement();
+ if (_stack.size())
+ result = _stack.pop();
+ if (_currToken == terminator || _currToken == kTokenEndOfFile)
+ break;
+ if (_currToken != kTokenEndOfStatement && _currToken != kTokenEndOfFile)
+ error("missing EOS (got %02x)", _currToken);
+ debugN("\n");
+ }
- default:
- error("unknown token %02x in code parameter", nextToken);
- }
+ return result;
+}
- params.push_back(nextValue);
+void LBCode::parseStatement() {
+ parseComparisons();
+
+ if (_currToken != kTokenAnd && _currToken != kTokenOr)
+ return;
+ byte op = _currToken;
+ if (op == kTokenAnd)
+ debugN(" && ");
+ else
+ debugN(" || ");
+
+ nextToken();
+ parseComparisons();
+
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ bool result;
+ if (op == kTokenAnd)
+ result = !val1.isZero() && !val2.isZero();
+ else
+ result = !val1.isZero() || !val2.isZero();
+
+ debugN(" [--> %s]", result ? "true" : "false");
+ _stack.push(result);
+}
+
+void LBCode::parseComparisons() {
+ parseConcat();
+
+ if (_currToken != kTokenEquals && _currToken != kTokenLessThan && _currToken != kTokenGreaterThan &&
+ _currToken != kTokenLessThanEq && _currToken != kTokenGreaterThanEq && _currToken != kTokenNotEq)
+ return;
+ byte comparison = _currToken;
+ switch (comparison) {
+ case kTokenEquals:
+ debugN(" == ");
+ break;
+ case kTokenLessThan:
+ debugN(" < ");
+ break;
+ case kTokenGreaterThan:
+ debugN(" > ");
+ break;
+ case kTokenLessThanEq:
+ debugN(" <= ");
+ break;
+ case kTokenGreaterThanEq:
+ debugN(" >= ");
+ break;
+ case kTokenNotEq:
+ debugN(" != ");
+ break;
}
- nextToken = data[offset];
- offset++;
- if (nextToken != kLBCodeTokenCloseBracket)
- error("missing ) after code parameter list (got %02x)", nextToken);
- debugN(")");
+ nextToken();
+ parseConcat();
+
+ if (_stack.size() < 2)
+ error("comparison didn't get enough values");
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ bool result = false;
+ // FIXME: should work for non-integers!!
+ switch (comparison) {
+ case kTokenEquals:
+ result = (val1 == val2);
+ break;
+ case kTokenLessThan:
+ result = (val1.integer < val2.integer);
+ break;
+ case kTokenGreaterThan:
+ result = (val1.integer > val2.integer);
+ break;
+ case kTokenLessThanEq:
+ result = (val1.integer <= val2.integer);
+ break;
+ case kTokenGreaterThanEq:
+ result = (val1.integer >= val2.integer);
+ break;
+ case kTokenNotEq:
+ result = (val1 != val2);
+ break;
+ }
- return params;
+ debugN(" [--> %s]", result ? "true" : "false");
+ _stack.push(result);
}
-void LBCode::runCodeCommand(LBItem *src, uint32 &offset) {
- if (offset + 1 >= size)
- error("went off the end of code");
+void LBCode::parseConcat() {
+ parseArithmetic1();
- byte commandType = data[offset];
- offset++;
+ if (_currToken != kTokenConcat)
+ return;
- switch (commandType) {
- case 0x23:
- {
- debugN("setViewOrigin");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
- break;
+ debugN(" & ");
+ nextToken();
+ parseArithmetic1();
- case 0x36:
- {
- debugN("setWorld");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
- break;
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ Common::String result = val1.toString() + val2.toString();
+ debugN(" [--> \"%s\"]", result.c_str());
+ _stack.push(result);
+}
+
+void LBCode::parseArithmetic1() {
+ parseArithmetic2();
+
+ if (_currToken != kTokenMinus && _currToken != kTokenPlus)
+ return;
+
+ byte op = _currToken;
+ if (op == kTokenMinus)
+ debugN(" - ");
+ else if (op == kTokenPlus)
+ debugN(" + ");
+
+ nextToken();
+ parseArithmetic2();
+
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ LBValue result;
+ // TODO: cope with non-integers
+ if (op == kTokenMinus)
+ result = val1.toInt() - val2.toInt();
+ else
+ result = val1.toInt() + val2.toInt();
+ _stack.push(result);
+}
+
+void LBCode::parseArithmetic2() {
+ // FIXME: other math operators
+ parseMain();
+}
+
+void LBCode::parseMain() {
+ byte prefix = 0;
+ if (_currToken == kTokenMinus || _currToken == kTokenPlus) {
+ debugN("%s", _currToken == kTokenMinus ? "-" : "+");
+ prefix = _currToken;
+ nextToken();
+ }
- case 0x42:
+ switch (_currToken) {
+ case kTokenIdentifier:
+ assert(_currValue.type == kLBValueString);
{
- debugN("setPlayParams");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() > 8)
- error("too many parameters (%d) to setPlayParams", params.size());
- if (!params.size())
- error("no target for setPlayParams");
- LBItem *target;
- if (params[0].string.equalsIgnoreCase("self")) {
- target = src;
+ Common::String varname = _currValue.string;
+ debugN("%s", varname.c_str());
+ nextToken();
+ if (varname.equalsIgnoreCase("self")) {
+ _stack.push(LBValue(_currSource));
+ if (_currToken == kTokenAssign)
+ error("attempted assignment to self");
+ break;
+ } else if (_currToken == kTokenAssign) {
+ debugN(" = ");
+ nextToken();
+ parseStatement();
+ if (!_stack.size())
+ error("assignment failed");
+ LBValue *val = &_vm->_variables[varname];
+ *val = _stack.pop();
+ _stack.push(*val);
} else {
- error("didn't understand target '%s'", params[0].string.c_str());
+ _stack.push(_vm->_variables[varname]);
}
- // TODO: type-checking
- switch (params.size()) {
- case 8:
- target->_soundMode = params[7].integer;
- case 7:
- target->_controlMode = params[6].integer;
- case 6:
- // TODO: _relocPoint?
- case 5:
- // TODO: _periodMin/Max
- case 4:
- target->_timingMode = params[3].integer;
- case 3:
- // TODO: _delayMin/Max
- case 2:
- target->_loopMode = params[1].integer;
+ // FIXME: pre/postincrement for non-integers
+ if (_currToken == kTokenPlusPlus) {
+ debugN("++");
+ _vm->_variables[varname].integer++;
+ nextToken();
+ } else if (_currToken == kTokenMinusMinus) {
+ debugN("--");
+ _vm->_variables[varname].integer--;
+ nextToken();
}
}
break;
- case 0x50:
- {
- debugN("setKeyEvent");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() != 2)
- error("incorrect number of parameters (%d) to setKeyEvent", params.size());
- // FIXME: params[0] is key, params[1] is opcode id
- }
+ case kTokenLiteral:
+ case kTokenConstMode:
+ case kTokenConstEventId:
+ case 0x5e: // TODO: ??
+ case kTokenKeycode:
+ assert(_currValue.type == kLBValueInteger);
+ debugN("%d", _currValue.integer);
+ _stack.push(_currValue);
+ nextToken();
break;
- case 0x51:
- {
- debugN("setHitTest");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() > 2)
- error("incorrect number of parameters (%d) to setHitTest", params.size());
- // TODO
- }
+ case kTokenString:
+ assert(_currValue.type == kLBValueString);
+ debugN("\"%s\"", _currValue.string.c_str());
+ _stack.push(_currValue);
+ nextToken();
break;
- case 0x52:
- {
- debugN("key");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
+ case kTokenTrue:
+ debugN("TRUE");
+ _stack.push(true);
+ nextToken();
+ break;
+ case kTokenFalse:
+ debugN("FALSE");
+ _stack.push(false);
+ nextToken();
break;
- case 0x5E:
- {
- debugN("setPageFade");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
+ case kTokenOpenBracket:
+ debugN("(");
+ nextToken();
+ parseStatement();
+ if (_currToken != kTokenCloseBracket)
+ error("no kTokenCloseBracket (%02x), multiple entries?", _currToken);
+ debugN(")");
+ nextToken();
+ break;
+
+ case kTokenNot:
+ debugN("!");
+ nextToken();
+ // not parseStatement, ! takes predecence over logical ops
+ parseComparisons();
+ if (!_stack.size())
+ error("not op failed");
+ _stack.push(_stack.pop().isZero() ? 1 : 0);
+ break;
+
+ case kTokenGeneralCommand:
+ runGeneralCommand();
+ break;
+
+ case kTokenItemCommand:
+ runItemCommand();
+ break;
+
+ case kTokenNotifyCommand:
+ runNotifyCommand();
break;
default:
- error("unknown command %02x in code", commandType);
+ error("unknown token %02x in code", _currToken);
+ }
+
+ if (prefix) {
+ if (!_stack.size())
+ error("+/- prefix failed");
+ LBValue val = _stack.pop();
+ assert(val.isNumeric());
+ // FIXME
+ if (prefix == kTokenMinus)
+ val.integer--;
+ else
+ val.integer++;
+ _stack.push(val);
}
}
-void LBCode::runCodeItemCommand(LBItem *src, uint32 &offset) {
- if (offset + 1 >= size)
+Common::Array<LBValue> LBCode::readParams() {
+ Common::Array<LBValue> params;
+
+ if (_currOffset + 1 >= _size)
error("went off the end of code");
- byte commandType = data[offset];
- offset++;
+ byte numParams = _data[_currOffset++];
- switch (commandType) {
- case 0x1d:
- {
- debugN("setParent");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() > 2)
- error("incorrect number of parameters (%d) to setParent", params.size());
- // TODO
+ if (!numParams) {
+ debugN("()\n");
+ nextToken();
+ return params;
+ }
+
+ nextToken();
+ if (_currToken != kTokenOpenBracket)
+ error("missing ( before code parameter list (got %02x)", _currToken);
+ nextToken();
+ debugN("(");
+
+ for (uint i = 0; i < numParams; i++) {
+ if (i != 0) {
+ if (_currToken != ',')
+ error("missing , between code parameters (got %02x)", _currToken);
+ debugN(", ");
+ nextToken();
}
- break;
- default:
- error("unknown item command %02x in code", commandType);
+ parseStatement();
+ if (!_stack.size())
+ error("stack empty");
+ LBValue nextValue = _stack.pop();
+
+ params.push_back(nextValue);
}
+
+ if (_currToken != kTokenCloseBracket)
+ error("missing ) after code parameter list (got %02x)", _currToken);
+ nextToken();
+ debugN(")");
+
+ return params;
}
-void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
- if (offset + 1 >= size)
- error("went off the end of code");
+Common::Rect LBCode::getRectFromParams(const Common::Array<LBValue> &params) {
+ if (params.size() == 0) {
+ assert(_currSource);
+ return _currSource->getRect();
+ } else if (params.size() == 1) {
+ const LBValue &val = params[0];
+ LBItem *item = _vm->getItemByName(val.toString());
+ if (item)
+ return item->getRect();
+ else
+ return val.toRect();
+ } else
+ error("getRectFromParams got called with weird state");
+}
+
+struct CodeCommandInfo {
+ const char *name;
+ typedef void (LBCode::*CommandFunc)(const Common::Array<LBValue> &params);
+ CommandFunc func;
+};
+
+#define NUM_GENERAL_COMMANDS 129
+CodeCommandInfo generalCommandInfo[NUM_GENERAL_COMMANDS] = {
+ { "eval", 0 },
+ { "random", 0 },
+ { "stringLen", 0 },
+ { "substring", 0 },
+ { "max", 0 },
+ { "min", 0 },
+ { "abs", 0 },
+ { "getRect", &LBCode::cmdGetRect }, // also "makeRect"
+ { "makePt", 0 }, // also "makePair"
+ { "topLeft", &LBCode::cmdTopLeft },
+ { "bottomRight", &LBCode::cmdBottomRight },
+ { "mousePos", 0 },
+ { "top", &LBCode::cmdTop },
+ { "left", &LBCode::cmdLeft },
+ { "bottom", &LBCode::cmdBottom },
+ // 0x10
+ { "right", &LBCode::cmdRight },
+ { "xpos", 0 },
+ { "ypos", 0 },
+ { "playFrom", 0 },
+ { "move", 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { "setDragParams", 0 },
+ { "resetDragParams", 0 },
+ { "enableRollover", &LBCode::cmdUnimplemented /* FIXME */ },
+ { "setCursor", 0 },
+ { "width", 0 },
+ { "height", 0 },
+ { "getFrameBounds", 0 }, // also "getFrameRect"
+ { "traceRect", 0 },
+ { "sqrt", 0 },
+ // 0x20
+ { "deleteVar", 0 },
+ { "saveVars", 0 },
+ { "scriptLink", 0 },
+ { "setViewOrigin", &LBCode::cmdUnimplemented },
+ { "rectSect", 0 },
+ { "getViewOrigin", 0 },
+ { "getViewRect", 0 },
+ { "getPage", 0 },
+ { "getWorldRect", 0 },
+ { "isWorldWrap", 0 },
+ { "newList", 0 },
+ { "deleteList", 0 },
+ { "add", 0 },
+ { 0, 0 },
+ { "addAt", 0 },
+ { "getAt", 0 },
+ // 0x30
+ { 0, 0 },
+ { "getIndex", 0 },
+ { "setAt", 0 },
+ { "listLen", 0 },
+ { "deleteAt", 0 },
+ { "clearList", 0 },
+ { "setWorld", 0 },
+ { "setProperty", 0 },
+ { "getProperty", 0 },
+ { "copyList", 0 },
+ { "invoke", 0 },
+ { "exec", 0 },
+ { "return", 0 },
+ { "sendSync", 0 },
+ { "moveViewOrigin", 0 },
+ { "addToGroup", 0 },
+ // 0x40
+ { "removeFromGroup", 0 },
+ { "clearGroup", 0 },
+ { "setPlayParams", &LBCode::cmdSetPlayParams },
+ { "autoEvent", 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { "getID", 0 },
+ { "setCursorPosition", 0 },
+ { "getTime", 0 },
+ { "logWriteLn", 0 },
+ { "logWrite", 0 },
+ { "getLanguage", 0 },
+ { "setLanguage", 0 },
+ { "getSequence", 0 },
+ { "setSequence", 0 },
+ { "getFileSpec", 0 },
+ // 0x50
+ { "setKeyEvent", &LBCode::cmdSetKeyEvent },
+ { "setHitTest", &LBCode::cmdSetHitTest },
+ { "key", &LBCode::cmdKey },
+ { "deleteKeyEvent", 0 },
+ { "setDisplay", &LBCode::cmdUnimplemented },
+ { "getDisplay", 0 },
+ { 0, 0 },
+ { "lbxCreate", 0 },
+ { "lbxFunc", 0 },
+ { "waitCursor", 0 },
+ { "debugBreak", 0 },
+ { "menuItemEnable", 0 },
+ { "showChannel", 0 },
+ { "hideChannel", 0 },
+ { "setPageFade", 0 },
+ { "normalize", 0 },
+ // 0x60 (v5+)
+ { "addEvent", 0 },
+ { "setCueEvent", 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { "getName", 0 },
+ { "getProperties", 0 },
+ { "createItem", 0 },
+ { "setProperties", 0 },
+ { "alert", 0 },
+ { "getUniqueID", 0 },
+ { "isNumeric", 0 },
+ { "setKeyFocus", 0 },
+ { "getKeyFocus", 0 },
+ { "isItem", 0 },
+ { "itemHit", 0 },
+ { "getItem ", 0 },
+ // 0x70
+ { 0, 0 },
+ { "setCascade", 0 },
+ { "getCascade", 0 },
+ { "getRes", 0 },
+ { "setRes", 0 },
+ { "getFilename", 0 },
+ { "resEnumNames", 0 },
+ { "isList", 0 },
+ { "resetRect", 0 },
+ { "setVolume", 0 },
+ { "getVolume", 0 },
+ { "pause", 0 },
+ { "getTextWidth", 0 },
+ { "setItemVolume", 0 },
+ { "setSoundLoop", 0 },
+ // 0x80
+ { "setClipboard", 0 },
+ { "getResDuration", 0 }
+};
+
+void LBCode::runGeneralCommand() {
+ byte commandType = _currValue.integer;
+
+ if (commandType == 0 || commandType > NUM_GENERAL_COMMANDS)
+ error("bad command type 0x%02x in runGeneralCommand", commandType);
+
+ CodeCommandInfo &info = generalCommandInfo[commandType - 1];
+ debugN("%s", info.name);
+ Common::Array<LBValue> params = readParams();
+
+ if (!info.func)
+ error("general command '%s' (0x%02x) unimplemented", info.name, commandType);
+ (this->*(info.func))(params);
+}
+
+void LBCode::cmdUnimplemented(const Common::Array<LBValue> &params) {
+ warning("unimplemented command called");
+}
+
+void LBCode::cmdGetRect(const Common::Array<LBValue> &params) {
+ if (params.size() < 2) {
+ _stack.push(getRectFromParams(params));
+ } else if (params.size() == 2) {
+ Common::Point p1 = params[0].toPoint();
+ Common::Point p2 = params[1].toPoint();
+ _stack.push(Common::Rect(p1.x, p1.y, p2.x, p2.y));
+ } else if (params.size() == 4) {
+ _stack.push(Common::Rect(params[0].toInt(), params[1].toInt(), params[2].toInt(), params[3].toInt()));
+ } else
+ error("incorrect number of parameters (%d) to getRect", params.size());
+}
+
+void LBCode::cmdTopLeft(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to topLeft", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(Common::Point(rect.top, rect.left));
+}
+
+void LBCode::cmdBottomRight(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to bottomRight", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(Common::Point(rect.bottom, rect.right));
+}
+
+void LBCode::cmdTop(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to top", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.top);
+}
+
+void LBCode::cmdLeft(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to left", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.left);
+}
+
+void LBCode::cmdBottom(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to bottom", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.bottom);
+}
+
+void LBCode::cmdRight(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to right", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.right);
+}
+
+void LBCode::cmdSetPlayParams(const Common::Array<LBValue> &params) {
+ if (params.size() > 8)
+ error("too many parameters (%d) to setPlayParams", params.size());
+ if (!params.size())
+ error("no target for setPlayParams");
+
+ if (params[0].type != kLBValueItemPtr)
+ error("first param to setPlayParams wasn't item");
+ LBItem *target = params[0].item;
+
+ // TODO: type-checking
+ switch (params.size()) {
+ case 8:
+ target->_soundMode = params[7].integer;
+ case 7:
+ target->_controlMode = params[6].integer;
+ case 6:
+ // TODO: _relocPoint?
+ case 5:
+ // TODO: _periodMin/Max
+ case 4:
+ target->_timingMode = params[3].integer;
+ case 3:
+ // TODO: _delayMin/Max
+ case 2:
+ target->_loopMode = params[1].integer;
+ }
+}
+
+void LBCode::cmdSetKeyEvent(const Common::Array<LBValue> &params) {
+ if (params.size() != 2)
+ error("incorrect number of parameters (%d) to setKeyEvent", params.size());
+
+ // FIXME: params[0] is key, params[1] is opcode id
+ warning("ignoring setKeyEvent");
+}
+
+void LBCode::cmdSetHitTest(const Common::Array<LBValue> &params) {
+ if (params.size() > 2)
+ error("incorrect number of parameters (%d) to setHitTest", params.size());
+ warning("ignoring setHitTest");
+}
+
+void LBCode::cmdKey(const Common::Array<LBValue> &params) {
+ _stack.push(0); // FIXME
+ warning("ignoring Key");
+}
+
+#define NUM_ITEM_COMMANDS 34
+CodeCommandInfo itemCommandInfo[NUM_ITEM_COMMANDS] = {
+ { "clone", 0 },
+ { "destroy", 0 },
+ { "dragBeginFrom", 0 },
+ { "dragEnd", 0 },
+ { "enableLocal", 0 },
+ { "enable", 0 },
+ { "showLocal", 0 },
+ { "show", 0 },
+ { "getFrame", 0 },
+ { "getParent", 0 },
+ { "getPosition" , 0 },
+ { "getText", 0 },
+ { "getZNext", 0 },
+ { "getZPrev", 0 },
+ { "hitTest", 0 },
+ // 0x10
+ { "isAmbient", 0 },
+ { "isEnabled", 0 },
+ { "isMuted", 0 },
+ { "isPlaying", &LBCode::itemIsPlaying },
+ { "isVisible", 0 },
+ { "isLoaded", 0 },
+ { "isDragging", 0 },
+ { "load", 0 },
+ { "moveTo", 0 },
+ { "mute", 0 },
+ { "play", 0 },
+ { "seek", 0 },
+ { "seekToFrame", 0 },
+ { "setParent", &LBCode::itemSetParent },
+ { "setZOrder", 0 },
+ { "setText", 0 },
+ // 0x20
+ { "stop", 0 },
+ { "unload", 0 },
+ { "unloadSync", 0}
+};
+
+void LBCode::runItemCommand() {
+ byte commandType = _currValue.integer;
+
+ if (commandType == 0 || commandType > NUM_ITEM_COMMANDS)
+ error("bad command type 0x%02x in runItemCommand", commandType);
+
+ CodeCommandInfo &info = itemCommandInfo[commandType - 1];
+ debugN("%s", info.name);
+ Common::Array<LBValue> params = readParams();
+
+ if (!info.func)
+ error("item command '%s' (0x%02x) unimplemented", info.name, commandType);
+ (this->*(info.func))(params);
+}
- byte commandType = data[offset];
- offset++;
+void LBCode::itemIsPlaying(const Common::Array<LBValue> &params) {
+ // TODO
+ warning("ignoring isPlaying");
+ _stack.push(0);
+}
+
+void LBCode::itemSetParent(const Common::Array<LBValue> &params) {
+ if (params.size() > 2)
+ error("incorrect number of parameters (%d) to setParent", params.size());
+ // TODO
+ warning("ignoring setParent");
+}
+
+void LBCode::runNotifyCommand() {
+ byte commandType = _currValue.integer;
switch (commandType) {
case kLBNotifyChangePage:
{
debugN("goto");
- Common::Array<LBValue> params = readParams(src, offset);
+ Common::Array<LBValue> params = readParams();
// TODO: type-checking
+ NotifyEvent notifyEvent(kLBNotifyChangePage, 0);
switch (params.size()) {
- case 1:
- _vm->addNotifyEvent(NotifyEvent(kLBNotifyChangePage, params[0].integer));
+ case 4:
+ notifyEvent.type = kLBNotifyChangeMode; // FIXME: type 8?
+ notifyEvent.newUnknown = params[0].integer; // FIXME: this is newLanguage
+ notifyEvent.newMode = params[1].integer;
+ notifyEvent.newPage = params[2].integer;
+ notifyEvent.newSubpage = params[3].integer;
break;
case 2:
- // FIXME
- case 4:
- // FIXME
+ notifyEvent.type = kLBNotifyChangeMode;
+ // FIXME: newPage and newSubpage?
+ error("can't handle goto with 2 params");
+ break;
+
+ case 1:
+ notifyEvent.param = params[0].integer;
+ break;
+
+ case 0:
+ // FIXME: use cur page?
+ error("can't handle goto with 0 params");
+ break;
default:
error("incorrect number of parameters (%d) to goto", params.size());
}
+ _vm->addNotifyEvent(notifyEvent);
}
break;
@@ -336,7 +962,7 @@ void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
case kLBNotifyGotoQuit:
{
debugN(commandType == kLBNotifyGoToControls ? "gotocontrol" : "gotoquit");
- Common::Array<LBValue> params = readParams(src, offset);
+ Common::Array<LBValue> params = readParams();
if (params.size() != 0)
error("incorrect number of parameters (%d) to notify", params.size());
_vm->addNotifyEvent(NotifyEvent(commandType, 0));
@@ -346,61 +972,25 @@ void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
case kLBNotifyIntroDone:
{
debugN("startphasemain");
- Common::Array<LBValue> params = readParams(src, offset);
+ Common::Array<LBValue> params = readParams();
if (params.size() != 0)
error("incorrect number of parameters (%d) to startphasemain", params.size());
_vm->addNotifyEvent(NotifyEvent(kLBNotifyIntroDone, 1));
}
break;
- default:
- error("unknown notify command %02x in code", commandType);
- }
-}
-
-void LBCode::runCode(LBItem *src, uint32 offset) {
- while (true) {
- if (offset + 1 >= size) {
- warning("went off the end of code");
- return;
- }
-
- byte tokenType = data[offset];
- offset++;
-
- switch (tokenType) {
- case 0x01: // FIXME
- case kLBCodeTokenEndOfFile:
- return;
-
- case 0x4D:
- runCodeCommand(src, offset);
- break;
-
- case 0x4E:
- runCodeItemCommand(src, offset);
- break;
-
- case 0x4F:
- runCodeNotifyCommand(src, offset);
- break;
-
- default:
- debugN("at %04x: %02x ", offset - 1, tokenType);
- for (uint i = 0; i < size; i++)
- debugN("%02x ", data[offset++]);
- debugN("\n");
- error("unknown token %02x in code", tokenType);
+ case kLBNotifyQuit:
+ {
+ debugN("quit");
+ Common::Array<LBValue> params = readParams();
+ if (params.size() != 0)
+ error("incorrect number of parameters (%d) to quit", params.size());
+ _vm->addNotifyEvent(NotifyEvent(kLBNotifyQuit, 0));
}
+ break;
- byte nextToken = data[offset];
- offset++;
- if (nextToken != kLBCodeTokenEndOfStatement)
- warning("missing EndOfStatement after code statement (got %04x)", nextToken);
- if (nextToken == kLBCodeTokenEndOfFile)
- return;
-
- debugN("\n");
+ default:
+ error("unknown notify command %02x in code", commandType);
}
}
diff --git a/engines/mohawk/livingbooks_code.h b/engines/mohawk/livingbooks_code.h
index 7960e79035..cd9ac1004a 100644
--- a/engines/mohawk/livingbooks_code.h
+++ b/engines/mohawk/livingbooks_code.h
@@ -26,6 +26,8 @@
#ifndef MOHAWK_LIVINGBOOKS_CODE_H
#define MOHAWK_LIVINGBOOKS_CODE_H
+#include "common/rect.h"
+#include "common/stack.h"
#include "common/substream.h"
namespace Mohawk {
@@ -35,18 +37,81 @@ class LBItem;
enum LBValueType {
kLBValueString,
- kLBValueInteger
+ kLBValueInteger,
+ kLBValueReal,
+ kLBValuePoint,
+ kLBValueRect,
+ kLBValueItemPtr
};
struct LBValue {
- LBValue() { type = kLBValueInteger; integer = 0; }
+ LBValue() {
+ type = kLBValueInteger;
+ integer = 0;
+ }
+ LBValue(int val) {
+ type = kLBValueInteger;
+ integer = val;
+ }
+ LBValue(const Common::String &str) {
+ type = kLBValueString;
+ string = str;
+ }
+ LBValue(const Common::Point &p) {
+ type = kLBValuePoint;
+ point = p;
+ }
+ LBValue(const Common::Rect &r) {
+ type = kLBValueRect;
+ rect = r;
+ }
+ LBValue(LBItem *itm) {
+ type = kLBValueItemPtr;
+ item = itm;
+ }
+ LBValue(const LBValue &val) {
+ type = val.type;
+ switch (type) {
+ case kLBValueString:
+ string = val.string;
+ break;
+ case kLBValueInteger:
+ integer = val.integer;
+ break;
+ case kLBValueReal:
+ real = val.real;
+ break;
+ case kLBValuePoint:
+ point = val.point;
+ break;
+ case kLBValueRect:
+ rect = val.rect;
+ break;
+ case kLBValueItemPtr:
+ item = val.item;
+ break;
+ }
+ }
LBValueType type;
Common::String string;
int integer;
+ double real;
+ Common::Point point;
+ Common::Rect rect;
+ LBItem *item;
bool operator==(const LBValue &x) const;
bool operator!=(const LBValue &x) const;
+
+ bool isNumeric() const;
+ bool isZero() const;
+
+ Common::String toString() const;
+ int toInt() const;
+ double toDouble() const;
+ Common::Point toPoint() const;
+ Common::Rect toRect() const;
};
enum {
@@ -54,39 +119,119 @@ enum {
};
enum {
- kLBCodeTokenString = 0x1,
- kLBCodeTokenLiteral = 0x5,
- kLBCodeTokenChar = 0x6,
- kLBCodeTokenEndOfStatement = 0x7,
- kLBCodeTokenEndOfFile = 0x8,
- kLBCodeTokenOpenBracket = 0xf,
- kLBCodeTokenCloseBracket = 0x10,
- kLBCodeTokenLong = 0x11,
-
- kLBCodeTokenEquals = 0x22, // TODO: maybe..
- kLBCodeTokenQuote = 0x27, // "'"
- kLBCodeTokenComma = 0x2c // ","
+ kTokenIdentifier = 0x1,
+ kTokenLiteral = 0x5,
+ kTokenString = 0x6,
+ kTokenEndOfStatement = 0x7,
+ kTokenEndOfFile = 0x8,
+ kTokenConcat = 0xb,
+ kTokenSingleQuote = 0xc, // ??
+ kTokenDoubleQuote = 0xd, // ??
+ kTokenMultiply = 0xe,
+ kTokenOpenBracket = 0xf,
+ kTokenCloseBracket = 0x10,
+ kTokenMinus = 0x11,
+ kTokenMinusMinus = 0x12,
+ kTokenPlusEquals = 0x13,
+ kTokenPlus = 0x14,
+ kTokenPlusPlus = 0x15,
+ kTokenEquals = 0x16,
+ kTokenMinusEquals = 0x17,
+ kTokenMultiplyEquals = 0x18,
+ kTokenDivideEquals = 0x19,
+ kTokenListStart = 0x1a,
+ kTokenListEnd = 0x1b,
+ kTokenColon = 0x1c, // ??
+ kTokenLessThan = 0x1d,
+ kTokenGreaterThan = 0x1e,
+ kTokenAndEquals = 0x1f,
+ kTokenDotOperator = 0x20,
+ kTokenDivide = 0x21,
+ kTokenAssign = 0x22,
+ kTokenLessThanEq = 0x23,
+ kTokenGreaterThanEq = 0x24,
+ kTokenNotEq = 0x25,
+ kTokenQuote = 0x27, // ??
+ kTokenAnd = 0x2a,
+ kTokenComma = 0x2c,
+ kTokenConstMode = 0x31,
+ kTokenIntDivide = 0x32,
+ kTokenModulo = 0x34,
+ kTokenNot = 0x35,
+ kTokenOr = 0x37,
+ kTokenTrue = 0x39,
+ kTokenFalse = 0x3a,
+ kTokenConstDataType = 0x3b, // ??
+ kTokenConstItemType = 0x3c, // ??
+ kTokenConstEventId = 0x42,
+ kTokenConstScriptOpcode = 0x43, // ??
+ kTokenConstScriptParam = 0x44, // ??
+ kTokenGeneralCommand = 0x4d,
+ kTokenItemCommand = 0x4e,
+ kTokenNotifyCommand = 0x4f,
+ // 0x5e?!
+ kTokenKeycode = 0x5f,
+
+ // v5 only:
+ kTokenLocal = 0x61,
+ kTokenPropListCommand = 0x70,
+ kTokenRectCommand = 0x71
};
class LBCode {
public:
- LBCode(MohawkEngine_LivingBooks *vm);
+ LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId);
~LBCode();
- void runCode(LBItem *src, uint32 offset);
+ LBValue runCode(LBItem *src, uint32 offset);
protected:
MohawkEngine_LivingBooks *_vm;
- uint32 size;
- byte *data;
+ uint32 _size;
+ byte *_data;
+ Common::HashMap<uint16, Common::String> _strings;
+
+ uint32 _currOffset;
+ LBItem *_currSource;
+
+ Common::Stack<LBValue> _stack;
+ byte _currToken;
+ LBValue _currValue;
- Common::HashMap<uint16, Common::String> strings;
+ void nextToken();
- Common::Array<LBValue> readParams(LBItem *src, uint32 &offset);
- void runCodeCommand(LBItem *src, uint32 &offset);
- void runCodeItemCommand(LBItem *src, uint32 &offset);
- void runCodeNotifyCommand(LBItem *src, uint32 &offset);
+ LBValue runCode(byte terminator);
+ void parseStatement();
+ void parseComparisons();
+ void parseConcat();
+ void parseArithmetic1();
+ void parseArithmetic2();
+ void parseMain();
+
+ Common::Array<LBValue> readParams();
+ Common::Rect getRectFromParams(const Common::Array<LBValue> &params);
+
+ void runGeneralCommand();
+ void runItemCommand();
+ void runNotifyCommand();
+
+public:
+ void cmdUnimplemented(const Common::Array<LBValue> &params);
+ void cmdGetRect(const Common::Array<LBValue> &params);
+ void cmdTopLeft(const Common::Array<LBValue> &params);
+ void cmdBottomRight(const Common::Array<LBValue> &params);
+ void cmdTop(const Common::Array<LBValue> &params);
+ void cmdLeft(const Common::Array<LBValue> &params);
+ void cmdBottom(const Common::Array<LBValue> &params);
+ void cmdRight(const Common::Array<LBValue> &params);
+ void cmdSetPlayParams(const Common::Array<LBValue> &params);
+ void cmdSetKeyEvent(const Common::Array<LBValue> &params);
+ void cmdSetHitTest(const Common::Array<LBValue> &params);
+ void cmdKey(const Common::Array<LBValue> &params);
+
+ void itemSetParent(const Common::Array<LBValue> &params);
+ void itemIsPlaying(const Common::Array<LBValue> &params);
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index 8c4453e155..30f1d40fdb 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -3,11 +3,6 @@ MODULE := engines/mohawk
MODULE_OBJS = \
bitmap.o \
console.o \
- cstime.o \
- cstime_cases.o \
- cstime_game.o \
- cstime_ui.o \
- cstime_view.o \
cursors.o \
detection.o \
dialogs.o \
@@ -16,20 +11,27 @@ MODULE_OBJS = \
livingbooks.o \
livingbooks_code.o \
mohawk.o \
+ resource.o \
+ sound.o \
+ video.o \
+ view.o
+
+ifdef ENABLE_CSTIME
+MODULE_OBJS += \
+ cstime.o \
+ cstime_cases.o \
+ cstime_game.o \
+ cstime_ui.o \
+ cstime_view.o
+endif
+
+ifdef ENABLE_MYST
+MODULE_OBJS += \
myst.o \
myst_areas.o \
myst_scripts.o \
myst_state.o \
- resource.o \
resource_cache.o \
- riven.o \
- riven_external.o \
- riven_saveload.o \
- riven_scripts.o \
- riven_vars.o \
- sound.o \
- video.o \
- view.o \
myst_stacks/channelwood.o \
myst_stacks/credits.o \
myst_stacks/demo.o \
@@ -42,6 +44,16 @@ MODULE_OBJS = \
myst_stacks/selenitic.o \
myst_stacks/slides.o \
myst_stacks/stoneship.o
+endif
+
+ifdef ENABLE_RIVEN
+MODULE_OBJS += \
+ riven.o \
+ riven_external.o \
+ riven_saveload.o \
+ riven_scripts.o \
+ riven_vars.o
+endif
# This module can be built as a plugin
ifeq ($(ENABLE_MOHAWK), DYNAMIC_PLUGIN)
diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp
index a3db630c6a..015cbffb26 100644
--- a/engines/mohawk/mohawk.cpp
+++ b/engines/mohawk/mohawk.cpp
@@ -46,8 +46,8 @@ MohawkEngine::MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc)
if (!_mixer->isReady())
error ("Sound initialization failed");
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ // Setup mixer
+ syncSoundSettings();
_sound = 0;
_video = 0;
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index d8c9786fcf..1aba820fed 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -417,45 +417,45 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
switch (_curStack) {
case kChannelwoodStack:
_gameState->_globals.currentAge = 4;
- _scriptParser = new MystScriptParser_Channelwood(this);
+ _scriptParser = new MystStacks::Channelwood(this);
break;
case kCreditsStack:
- _scriptParser = new MystScriptParser_Credits(this);
+ _scriptParser = new MystStacks::Credits(this);
break;
case kDemoStack:
- _scriptParser = new MystScriptParser_Demo(this);
+ _scriptParser = new MystStacks::Demo(this);
break;
case kDniStack:
_gameState->_globals.currentAge = 6;
- _scriptParser = new MystScriptParser_Dni(this);
+ _scriptParser = new MystStacks::Dni(this);
break;
case kIntroStack:
- _scriptParser = new MystScriptParser_Intro(this);
+ _scriptParser = new MystStacks::Intro(this);
break;
case kMakingOfStack:
- _scriptParser = new MystScriptParser_MakingOf(this);
+ _scriptParser = new MystStacks::MakingOf(this);
break;
case kMechanicalStack:
_gameState->_globals.currentAge = 3;
- _scriptParser = new MystScriptParser_Mechanical(this);
+ _scriptParser = new MystStacks::Mechanical(this);
break;
case kMystStack:
_gameState->_globals.currentAge = 2;
- _scriptParser = new MystScriptParser_Myst(this);
+ _scriptParser = new MystStacks::Myst(this);
break;
case kDemoPreviewStack:
- _scriptParser = new MystScriptParser_Preview(this);
+ _scriptParser = new MystStacks::Preview(this);
break;
case kSeleniticStack:
_gameState->_globals.currentAge = 0;
- _scriptParser = new MystScriptParser_Selenitic(this);
+ _scriptParser = new MystStacks::Selenitic(this);
break;
case kDemoSlidesStack:
- _scriptParser = new MystScriptParser_Slides(this);
+ _scriptParser = new MystStacks::Slides(this);
break;
case kStoneshipStack:
_gameState->_globals.currentAge = 1;
- _scriptParser = new MystScriptParser_Stoneship(this);
+ _scriptParser = new MystStacks::Stoneship(this);
break;
default:
error("Unknown Myst stack");
@@ -1143,20 +1143,6 @@ void MohawkEngine_Myst::loadResources() {
delete rlstStream;
}
-void MohawkEngine_Myst::runLoadDialog() {
- const Common::String gameId = ConfMan.get("gameid");
-
- const EnginePlugin *plugin = 0;
- EngineMan.findGame(gameId, &plugin);
-
- pauseEngine(true);
- int slot = _loadDialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
- if (slot >= 0) {
- // TODO
- }
- pauseEngine(false);
-}
-
Common::Error MohawkEngine_Myst::loadGameState(int slot) {
if (_gameState->load(_gameState->generateSaveGameList()[slot]))
return Common::kNoError;
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 919509384b..47e8a6562c 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -155,8 +155,6 @@ public:
Common::String wrapMovieFilename(const Common::String &movieName, uint16 stack);
void reloadSaveList();
- void runLoadDialog();
- void runSaveDialog();
void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound);
void changeToCard(uint16 card, bool updateScreen);
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index 66430f2068..aa06d1a5b4 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -233,6 +233,7 @@ public:
void drawFrame(uint16 frame);
bool pullLeverV();
void releaseLeverV();
+ uint16 getNumFrames() { return _numFrames; }
protected:
uint16 _numFrames;
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index 25eeac0a6c..17a2c66091 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -599,6 +599,10 @@ void MystScriptParser::o_copyBackBufferToScreen(uint16 op, uint16 var, uint16 ar
void MystScriptParser::o_copyImageToBackBuffer(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
uint16 imageId = argv[0];
+ // WORKAROUND wrong image id in mechanical staircase
+ if (imageId == 7158)
+ imageId = 7178;
+
Common::Rect srcRect = Common::Rect(argv[1], argv[2], argv[3], argv[4]);
Common::Rect dstRect = Common::Rect(argv[5], argv[6], 544, 333);
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index 6e367d0167..26267cfbda 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -35,18 +35,19 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Channelwood::MystScriptParser_Channelwood(MohawkEngine_Myst *vm) :
+Channelwood::Channelwood(MohawkEngine_Myst *vm) :
MystScriptParser(vm), _state(vm->_gameState->_channelwood) {
setupOpcodes();
}
-MystScriptParser_Channelwood::~MystScriptParser_Channelwood() {
+Channelwood::~Channelwood() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Channelwood::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Channelwood::x, #x))
-void MystScriptParser_Channelwood::setupOpcodes() {
+void Channelwood::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_bridgeToggle);
OPCODE(101, o_pipeExtend);
@@ -89,15 +90,15 @@ void MystScriptParser_Channelwood::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Channelwood::disablePersistentScripts() {
+void Channelwood::disablePersistentScripts() {
}
-void MystScriptParser_Channelwood::runPersistentScripts() {
+void Channelwood::runPersistentScripts() {
}
-uint16 MystScriptParser_Channelwood::getVar(uint16 var) {
+uint16 Channelwood::getVar(uint16 var) {
switch(var) {
case 1: // Water Pump Bridge Raised
return _state.waterPumpBridgeState;
@@ -186,7 +187,7 @@ uint16 MystScriptParser_Channelwood::getVar(uint16 var) {
}
}
-void MystScriptParser_Channelwood::toggleVar(uint16 var) {
+void Channelwood::toggleVar(uint16 var) {
switch(var) {
case 1: // Water Pump Bridge Raised
_state.waterPumpBridgeState ^= 1;
@@ -219,7 +220,7 @@ void MystScriptParser_Channelwood::toggleVar(uint16 var) {
}
}
-bool MystScriptParser_Channelwood::setVarValue(uint16 var, uint16 value) {
+bool Channelwood::setVarValue(uint16 var, uint16 value) {
bool refresh = false;
switch (var) {
@@ -270,7 +271,7 @@ bool MystScriptParser_Channelwood::setVarValue(uint16 var, uint16 value) {
return refresh;
}
-bool MystScriptParser_Channelwood::pipeChangeValve(bool open, uint16 mask) {
+bool Channelwood::pipeChangeValve(bool open, uint16 mask) {
if (open) {
if (!(_state.waterValveStates & mask)) {
_state.waterValveStates |= mask;
@@ -286,7 +287,7 @@ bool MystScriptParser_Channelwood::pipeChangeValve(bool open, uint16 mask) {
return false;
}
-void MystScriptParser_Channelwood::o_bridgeToggle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_bridgeToggle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Bridge rise / skink video", op);
VideoHandle bridge = _vm->_video->playMovie(_vm->wrapMovieFilename("bridge", kChannelwoodStack), 292, 203);
@@ -300,7 +301,7 @@ void MystScriptParser_Channelwood::o_bridgeToggle(uint16 op, uint16 var, uint16
_vm->_video->waitUntilMovieEnds(bridge);
}
-void MystScriptParser_Channelwood::o_pipeExtend(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_pipeExtend(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Play Pipe Movie and Sound", op);
uint16 soundId = argv[0];
@@ -319,7 +320,7 @@ void MystScriptParser_Channelwood::o_pipeExtend(uint16 op, uint16 var, uint16 ar
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Channelwood::o_drawImageChangeCardAndVolume(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_drawImageChangeCardAndVolume(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Draw Full Screen Image, Change Card, and change volume", op);
uint16 imageId = argv[0];
@@ -340,7 +341,7 @@ void MystScriptParser_Channelwood::o_drawImageChangeCardAndVolume(uint16 op, uin
}
-void MystScriptParser_Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Do Water Tank Valve Open Animation", op);
Common::Rect rect = _invokingResource->getRect();
@@ -354,7 +355,7 @@ void MystScriptParser_Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, u
pipeChangeValve(true, 0x80);
}
-void MystScriptParser_Channelwood::o_leverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever start move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -363,7 +364,7 @@ void MystScriptParser_Channelwood::o_leverStartMove(uint16 op, uint16 var, uint1
_leverPulled = false;
}
-void MystScriptParser_Channelwood::o_leverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -378,7 +379,7 @@ void MystScriptParser_Channelwood::o_leverMove(uint16 op, uint16 var, uint16 arg
}
}
-void MystScriptParser_Channelwood::o_leverMoveFail(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverMoveFail(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -395,7 +396,7 @@ void MystScriptParser_Channelwood::o_leverMoveFail(uint16 op, uint16 var, uint16
}
}
-void MystScriptParser_Channelwood::o_leverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever end move", op);
// Get current lever frame
@@ -411,12 +412,12 @@ void MystScriptParser_Channelwood::o_leverEndMove(uint16 op, uint16 var, uint16
_vm->checkCursorHints();
}
-void MystScriptParser_Channelwood::o_leverEndMoveResumeBackground(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverEndMoveResumeBackground(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_vm->_sound->resumeBackgroundMyst();
o_leverEndMove(op, var, argc, argv);
}
-void MystScriptParser_Channelwood::o_leverEndMoveWithSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverEndMoveWithSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
o_leverEndMove(op, var, argc, argv);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -425,20 +426,20 @@ void MystScriptParser_Channelwood::o_leverEndMoveWithSound(uint16 op, uint16 var
_vm->_sound->replaceSoundMyst(soundId);
}
-void MystScriptParser_Channelwood::o_leverElev3StartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverElev3StartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_vm->_gfx->copyImageToScreen(3970, Common::Rect(544, 333));
_vm->_system->updateScreen();
o_leverStartMove(op, var, argc, argv);
}
-void MystScriptParser_Channelwood::o_leverElev3EndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_leverElev3EndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
o_leverEndMove(op, var, argc, argv);
_vm->_gfx->copyImageToScreen(3265, Common::Rect(544, 333));
_vm->_system->updateScreen();
_vm->_sound->replaceSoundMyst(5265);
}
-void MystScriptParser_Channelwood::o_pumpLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_pumpLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Pump lever move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -452,7 +453,7 @@ void MystScriptParser_Channelwood::o_pumpLeverMove(uint16 op, uint16 var, uint16
}
}
-void MystScriptParser_Channelwood::o_pumpLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_pumpLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
o_leverEndMove(op, var, argc, argv);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -461,7 +462,7 @@ void MystScriptParser_Channelwood::o_pumpLeverEndMove(uint16 op, uint16 var, uin
_vm->_sound->replaceBackgroundMyst(soundId, 36864);
}
-void MystScriptParser_Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Play stairs door video", op);
MystResourceType6 *movie = static_cast<MystResourceType6 *>(_invokingResource);
@@ -474,7 +475,7 @@ void MystScriptParser_Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uin
}
}
-void MystScriptParser_Channelwood::o_valveHandleMove1(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMove1(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -490,7 +491,7 @@ void MystScriptParser_Channelwood::o_valveHandleMove1(uint16 op, uint16 var, uin
}
}
-void MystScriptParser_Channelwood::o_valveHandleMoveStart1(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMoveStart1(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move start", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -502,7 +503,7 @@ void MystScriptParser_Channelwood::o_valveHandleMoveStart1(uint16 op, uint16 var
o_valveHandleMove1(op, var, argc, argv);
}
-void MystScriptParser_Channelwood::o_valveHandleMoveStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMoveStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move stop", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -525,7 +526,7 @@ void MystScriptParser_Channelwood::o_valveHandleMoveStop(uint16 op, uint16 var,
_vm->checkCursorHints();
}
-void MystScriptParser_Channelwood::o_valveHandleMove2(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMove2(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -541,7 +542,7 @@ void MystScriptParser_Channelwood::o_valveHandleMove2(uint16 op, uint16 var, uin
}
}
-void MystScriptParser_Channelwood::o_valveHandleMoveStart2(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMoveStart2(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move start", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -553,7 +554,7 @@ void MystScriptParser_Channelwood::o_valveHandleMoveStart2(uint16 op, uint16 var
o_valveHandleMove2(op, var, argc, argv);
}
-void MystScriptParser_Channelwood::o_valveHandleMove3(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMove3(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -569,7 +570,7 @@ void MystScriptParser_Channelwood::o_valveHandleMove3(uint16 op, uint16 var, uin
}
}
-void MystScriptParser_Channelwood::o_valveHandleMoveStart3(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_valveHandleMoveStart3(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move start", op);
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
@@ -581,7 +582,7 @@ void MystScriptParser_Channelwood::o_valveHandleMoveStart3(uint16 op, uint16 var
o_valveHandleMove3(op, var, argc, argv);
}
-void MystScriptParser_Channelwood::o_hologramMonitor(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_hologramMonitor(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram monitor", op);
// Used on Card 3012 (Temple Hologram Monitor)
@@ -613,7 +614,7 @@ void MystScriptParser_Channelwood::o_hologramMonitor(uint16 op, uint16 var, uint
}
}
-void MystScriptParser_Channelwood::o_drawerOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_drawerOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Open Sirius drawer", op);
_siriusDrawerState = 1;
@@ -621,7 +622,7 @@ void MystScriptParser_Channelwood::o_drawerOpen(uint16 op, uint16 var, uint16 ar
_vm->redrawArea(102, false);
}
-void MystScriptParser_Channelwood::o_hologramTemple(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_hologramTemple(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Temple hologram", op);
_vm->_sound->pauseBackgroundMyst();
@@ -648,14 +649,14 @@ void MystScriptParser_Channelwood::o_hologramTemple(uint16 op, uint16 var, uint1
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Channelwood::o_executeMouseUp(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_executeMouseUp(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Execute mouse up", op);
MystResourceType5 *resource = static_cast<MystResourceType5 *>(_vm->_resources[argv[0]]);
resource->handleMouseUp();
}
-void MystScriptParser_Channelwood::o_waterTankValveClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_waterTankValveClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Do Water Tank Valve Close Animation", op);
Common::Rect rect = _invokingResource->getRect();
@@ -669,7 +670,7 @@ void MystScriptParser_Channelwood::o_waterTankValveClose(uint16 op, uint16 var,
pipeChangeValve(false, 0x80);
}
-void MystScriptParser_Channelwood::o_elevatorMovies(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_elevatorMovies(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used by Card 3262 (Elevator)
debugC(kDebugScript, "Opcode %d: Elevator movie", op);
@@ -714,7 +715,7 @@ void MystScriptParser_Channelwood::o_elevatorMovies(uint16 op, uint16 var, uint1
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Channelwood::o_soundReplace(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_soundReplace(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Play sound if not already playing", op);
uint16 soundId = argv[0];
@@ -723,19 +724,20 @@ void MystScriptParser_Channelwood::o_soundReplace(uint16 op, uint16 var, uint16
_vm->_sound->replaceSoundMyst(soundId);
}
-void MystScriptParser_Channelwood::o_lever_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_lever_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever init", op);
_leverAction = static_cast<MystResourceType5 *>(_invokingResource);
}
-void MystScriptParser_Channelwood::o_pipeValve_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_pipeValve_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Water valve init", op);
_valveVar = var;
}
-void MystScriptParser_Channelwood::o_drawer_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Channelwood::o_drawer_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sirius's drawer init", op);
_siriusDrawerState = 0;
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/channelwood.h b/engines/mohawk/myst_stacks/channelwood.h
index 8c52f864cd..5eeaa63e23 100644
--- a/engines/mohawk/myst_stacks/channelwood.h
+++ b/engines/mohawk/myst_stacks/channelwood.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Channelwood : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Channelwood : public MystScriptParser {
public:
- MystScriptParser_Channelwood(MohawkEngine_Myst *vm);
- ~MystScriptParser_Channelwood();
+ Channelwood(MohawkEngine_Myst *vm);
+ ~Channelwood();
void disablePersistentScripts();
void runPersistentScripts();
@@ -99,6 +100,7 @@ private:
bool pipeChangeValve(bool open, uint16 mask);
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index 6c0b2c2951..61772eda4d 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -33,19 +33,20 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
// NOTE: Credits Start Card is 10000
-MystScriptParser_Credits::MystScriptParser_Credits(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+Credits::Credits(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
setupOpcodes();
}
-MystScriptParser_Credits::~MystScriptParser_Credits() {
+Credits::~Credits() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Credits::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Credits::x, #x))
-void MystScriptParser_Credits::setupOpcodes() {
+void Credits::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_quit);
@@ -55,11 +56,11 @@ void MystScriptParser_Credits::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Credits::disablePersistentScripts() {
+void Credits::disablePersistentScripts() {
_creditsRunning = false;
}
-void MystScriptParser_Credits::runPersistentScripts() {
+void Credits::runPersistentScripts() {
if (!_creditsRunning)
return;
@@ -79,7 +80,7 @@ void MystScriptParser_Credits::runPersistentScripts() {
}
}
-uint16 MystScriptParser_Credits::getVar(uint16 var) {
+uint16 Credits::getVar(uint16 var) {
switch(var) {
case 0: // Credits Image Control
return _curImage;
@@ -90,11 +91,12 @@ uint16 MystScriptParser_Credits::getVar(uint16 var) {
}
}
-void MystScriptParser_Credits::o_runCredits(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Credits::o_runCredits(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Activate the credits
_creditsRunning = true;
_curImage = 0;
_startTime = _vm->_system->getMillis();
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/credits.h b/engines/mohawk/myst_stacks/credits.h
index 46d23c67ca..4f9eaa2944 100644
--- a/engines/mohawk/myst_stacks/credits.h
+++ b/engines/mohawk/myst_stacks/credits.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Credits : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Credits : public MystScriptParser {
public:
- MystScriptParser_Credits(MohawkEngine_Myst *vm);
- ~MystScriptParser_Credits();
+ Credits(MohawkEngine_Myst *vm);
+ ~Credits();
void disablePersistentScripts();
void runPersistentScripts();
@@ -55,6 +56,7 @@ private:
uint16 _curImage; // 56
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp
index 548a2d5390..a2dd148b22 100644
--- a/engines/mohawk/myst_stacks/demo.cpp
+++ b/engines/mohawk/myst_stacks/demo.cpp
@@ -29,25 +29,26 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Demo::MystScriptParser_Demo(MohawkEngine_Myst *vm) : MystScriptParser_Intro(vm) {
+Demo::Demo(MohawkEngine_Myst *vm) : Intro(vm) {
setupOpcodes();
}
-MystScriptParser_Demo::~MystScriptParser_Demo() {
+Demo::~Demo() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Demo::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Demo::x, #x))
#define OVERRIDE_OPCODE(opcode, x) \
for (uint32 i = 0; i < _opcodes.size(); i++) \
if (_opcodes[i]->op == opcode) { \
- _opcodes[i]->proc = (OpcodeProcMyst) &MystScriptParser_Demo::x; \
+ _opcodes[i]->proc = (OpcodeProcMyst) &Demo::x; \
_opcodes[i]->desc = #x; \
break; \
}
-void MystScriptParser_Demo::setupOpcodes() {
+void Demo::setupOpcodes() {
// "Stack-Specific" Opcodes
OVERRIDE_OPCODE(100, opcode_100);
OPCODE(101, opcode_101);
@@ -63,14 +64,14 @@ void MystScriptParser_Demo::setupOpcodes() {
#undef OPCODE
#undef OVERRIDE_OPCODE
-void MystScriptParser_Demo::disablePersistentScripts() {
- MystScriptParser_Intro::disablePersistentScripts();
+void Demo::disablePersistentScripts() {
+ Intro::disablePersistentScripts();
_enabled201 = false;
}
-void MystScriptParser_Demo::runPersistentScripts() {
- MystScriptParser_Intro::runPersistentScripts();
+void Demo::runPersistentScripts() {
+ Intro::runPersistentScripts();
if (_enabled201) {
// Used on Card 2001, 2002 and 2003
@@ -79,11 +80,11 @@ void MystScriptParser_Demo::runPersistentScripts() {
}
}
-void MystScriptParser_Demo::opcode_100(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Demo::opcode_100(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// TODO: Fill in Function...
}
-void MystScriptParser_Demo::opcode_101(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Demo::opcode_101(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used on Card 2000, 2002 and 2003
@@ -94,7 +95,7 @@ void MystScriptParser_Demo::opcode_101(uint16 op, uint16 var, uint16 argc, uint1
unknown(op, var, argc, argv);
}
-void MystScriptParser_Demo::opcode_102(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Demo::opcode_102(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used on Card 2002 and 2003
@@ -105,7 +106,7 @@ void MystScriptParser_Demo::opcode_102(uint16 op, uint16 var, uint16 argc, uint1
unknown(op, var, argc, argv);
}
-void MystScriptParser_Demo::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Demo::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used on Card 2001, 2002 and 2003
@@ -116,11 +117,12 @@ void MystScriptParser_Demo::opcode_201(uint16 op, uint16 var, uint16 argc, uint1
}
-void MystScriptParser_Demo::opcode_300(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Demo::opcode_300(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Card 2000
varUnusedCheck(op, var);
// TODO: Fill in Function...
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/demo.h b/engines/mohawk/myst_stacks/demo.h
index f693ea4c35..054dc7befe 100644
--- a/engines/mohawk/myst_stacks/demo.h
+++ b/engines/mohawk/myst_stacks/demo.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Demo : public MystScriptParser_Intro {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Demo : public Intro {
public:
- MystScriptParser_Demo(MohawkEngine_Myst *vm);
- ~MystScriptParser_Demo();
+ Demo(MohawkEngine_Myst *vm);
+ ~Demo();
void disablePersistentScripts();
void runPersistentScripts();
@@ -59,6 +60,7 @@ private:
bool _enabled201;
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp
index 47382b7b81..ffbf9c991f 100644
--- a/engines/mohawk/myst_stacks/dni.cpp
+++ b/engines/mohawk/myst_stacks/dni.cpp
@@ -32,19 +32,20 @@
#include "mohawk/myst_stacks/dni.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Dni::MystScriptParser_Dni(MohawkEngine_Myst *vm) :
+Dni::Dni(MohawkEngine_Myst *vm) :
MystScriptParser(vm) {
setupOpcodes();
_notSeenAtrus = true;
}
-MystScriptParser_Dni::~MystScriptParser_Dni() {
+Dni::~Dni() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Dni::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Dni::x, #x))
-void MystScriptParser_Dni::setupOpcodes() {
+void Dni::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, NOP);
OPCODE(101, o_handPage);
@@ -58,13 +59,13 @@ void MystScriptParser_Dni::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Dni::disablePersistentScripts() {
+void Dni::disablePersistentScripts() {
_atrusRunning = false;
_waitForLoop = false;
_atrusLeft = false;
}
-void MystScriptParser_Dni::runPersistentScripts() {
+void Dni::runPersistentScripts() {
if (_atrusRunning)
atrus_run();
@@ -75,7 +76,7 @@ void MystScriptParser_Dni::runPersistentScripts() {
atrusLeft_run();
}
-uint16 MystScriptParser_Dni::getVar(uint16 var) {
+uint16 Dni::getVar(uint16 var) {
switch(var) {
case 0: // Atrus Gone (from across room)
return _globals.ending == 2;
@@ -95,7 +96,7 @@ uint16 MystScriptParser_Dni::getVar(uint16 var) {
}
}
-void MystScriptParser_Dni::o_handPage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Dni::o_handPage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hand page to Atrus", op);
// Used in Card 5014 (Atrus)
@@ -118,7 +119,7 @@ void MystScriptParser_Dni::o_handPage(uint16 op, uint16 var, uint16 argc, uint16
}
}
-void MystScriptParser_Dni::atrusLeft_run() {
+void Dni::atrusLeft_run() {
if (_vm->_system->getMillis() > _atrusLeftTime + 63333) {
_video = _vm->wrapMovieFilename("atrus2", kDniStack);
VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77);
@@ -137,7 +138,7 @@ void MystScriptParser_Dni::atrusLeft_run() {
}
}
-void MystScriptParser_Dni::loopVideo_run() {
+void Dni::loopVideo_run() {
if (!_vm->_video->isVideoPlaying()) {
VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77);
_vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, _loopStart, 600), Audio::Timestamp(0, _loopEnd, 600));
@@ -147,7 +148,7 @@ void MystScriptParser_Dni::loopVideo_run() {
}
}
-void MystScriptParser_Dni::atrus_run() {
+void Dni::atrus_run() {
if (_globals.ending == 2) {
// Wait for atrus to come back
_atrusLeft = true;
@@ -188,10 +189,11 @@ void MystScriptParser_Dni::atrus_run() {
}
}
-void MystScriptParser_Dni::o_atrus_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Dni::o_atrus_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Atrus init", op);
_atrusRunning = true;
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/dni.h b/engines/mohawk/myst_stacks/dni.h
index 85900ad562..b50f018d3e 100644
--- a/engines/mohawk/myst_stacks/dni.h
+++ b/engines/mohawk/myst_stacks/dni.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Dni : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Dni : public MystScriptParser {
public:
- MystScriptParser_Dni(MohawkEngine_Myst *vm);
- ~MystScriptParser_Dni();
+ Dni(MohawkEngine_Myst *vm);
+ ~Dni();
void disablePersistentScripts();
void runPersistentScripts();
@@ -67,6 +68,7 @@ private:
bool _atrusLeft; // 80
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp
index a4a8cf2a89..0d8f67a85b 100644
--- a/engines/mohawk/myst_stacks/intro.cpp
+++ b/engines/mohawk/myst_stacks/intro.cpp
@@ -34,17 +34,18 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Intro::MystScriptParser_Intro(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+Intro::Intro(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
setupOpcodes();
}
-MystScriptParser_Intro::~MystScriptParser_Intro() {
+Intro::~Intro() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Intro::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Intro::x, #x))
-void MystScriptParser_Intro::setupOpcodes() {
+void Intro::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_useLinkBook);
@@ -58,12 +59,12 @@ void MystScriptParser_Intro::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Intro::disablePersistentScripts() {
+void Intro::disablePersistentScripts() {
_introMoviesRunning = false;
_linkBookRunning = false;
}
-void MystScriptParser_Intro::runPersistentScripts() {
+void Intro::runPersistentScripts() {
if (_introMoviesRunning)
introMovies_run();
@@ -71,7 +72,7 @@ void MystScriptParser_Intro::runPersistentScripts() {
mystLinkBook_run();
}
-uint16 MystScriptParser_Intro::getVar(uint16 var) {
+uint16 Intro::getVar(uint16 var) {
switch(var) {
case 0:
if (_globals.currentAge == 9 || _globals.currentAge == 10)
@@ -83,7 +84,7 @@ uint16 MystScriptParser_Intro::getVar(uint16 var) {
}
}
-void MystScriptParser_Intro::o_useLinkBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Intro::o_useLinkBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Hard coded SoundId valid only for Intro Stack.
// Other stacks use Opcode 40, which takes SoundId values as arguments.
const uint16 soundIdLinkSrc = 5;
@@ -96,7 +97,7 @@ void MystScriptParser_Intro::o_useLinkBook(uint16 op, uint16 var, uint16 argc, u
_vm->changeToStack(_stackMap[_globals.currentAge], _startCard[_globals.currentAge], soundIdLinkSrc, soundIdLinkDst[_globals.currentAge]);
}
-void MystScriptParser_Intro::introMovies_run() {
+void Intro::introMovies_run() {
// Play Intro Movies
// This is all quite messy...
@@ -156,12 +157,12 @@ void MystScriptParser_Intro::introMovies_run() {
}
}
-void MystScriptParser_Intro::o_playIntroMovies(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Intro::o_playIntroMovies(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_introMoviesRunning = true;
_introStep = 0;
}
-void MystScriptParser_Intro::mystLinkBook_run() {
+void Intro::mystLinkBook_run() {
if (_startTime == 1) {
_startTime = 0;
@@ -175,7 +176,7 @@ void MystScriptParser_Intro::mystLinkBook_run() {
}
}
-void MystScriptParser_Intro::o_mystLinkBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Intro::o_mystLinkBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Myst link book init", op);
_linkBookMovie = static_cast<MystResourceType6 *>(_invokingResource);
@@ -183,4 +184,5 @@ void MystScriptParser_Intro::o_mystLinkBook_init(uint16 op, uint16 var, uint16 a
_linkBookRunning = true;
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/intro.h b/engines/mohawk/myst_stacks/intro.h
index a40d268d7d..0ecd9e6883 100644
--- a/engines/mohawk/myst_stacks/intro.h
+++ b/engines/mohawk/myst_stacks/intro.h
@@ -32,16 +32,17 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
class MystResourceType6;
struct MystScriptEntry;
-class MystScriptParser_Intro : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Intro : public MystScriptParser {
public:
- MystScriptParser_Intro(MohawkEngine_Myst *vm);
- ~MystScriptParser_Intro();
+ Intro(MohawkEngine_Myst *vm);
+ ~Intro();
void disablePersistentScripts();
void runPersistentScripts();
@@ -65,6 +66,7 @@ private:
MystResourceType6 *_linkBookMovie;
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/makingof.cpp b/engines/mohawk/myst_stacks/makingof.cpp
index 28b8665f52..e639092ed4 100644
--- a/engines/mohawk/myst_stacks/makingof.cpp
+++ b/engines/mohawk/myst_stacks/makingof.cpp
@@ -33,27 +33,29 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_MakingOf::MystScriptParser_MakingOf(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+MakingOf::MakingOf(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
setupOpcodes();
}
-MystScriptParser_MakingOf::~MystScriptParser_MakingOf() {
+MakingOf::~MakingOf() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_MakingOf::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MakingOf::x, #x))
-void MystScriptParser_MakingOf::setupOpcodes() {
+void MakingOf::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_quit);
}
#undef OPCODE
-void MystScriptParser_MakingOf::disablePersistentScripts() {
+void MakingOf::disablePersistentScripts() {
}
-void MystScriptParser_MakingOf::runPersistentScripts() {
+void MakingOf::runPersistentScripts() {
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/makingof.h b/engines/mohawk/myst_stacks/makingof.h
index ab919fd174..3033bb851e 100644
--- a/engines/mohawk/myst_stacks/makingof.h
+++ b/engines/mohawk/myst_stacks/makingof.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_MakingOf : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class MakingOf : public MystScriptParser {
public:
- MystScriptParser_MakingOf(MohawkEngine_Myst *vm);
- ~MystScriptParser_MakingOf();
+ MakingOf(MohawkEngine_Myst *vm);
+ ~MakingOf();
void disablePersistentScripts();
void runPersistentScripts();
@@ -49,6 +50,7 @@ private:
void setupOpcodes();
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index add87694a8..3dab2f7939 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "mohawk/cursors.h"
#include "mohawk/myst.h"
#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
@@ -34,8 +35,9 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Mechanical::MystScriptParser_Mechanical(MohawkEngine_Myst *vm) :
+Mechanical::Mechanical(MohawkEngine_Myst *vm) :
MystScriptParser(vm), _state(vm->_gameState->_mechanical) {
setupOpcodes();
@@ -43,18 +45,22 @@ MystScriptParser_Mechanical::MystScriptParser_Mechanical(MohawkEngine_Myst *vm)
_fortressPosition = 0;
}
-MystScriptParser_Mechanical::~MystScriptParser_Mechanical() {
+Mechanical::~Mechanical() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Mechanical::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Mechanical::x, #x))
-void MystScriptParser_Mechanical::setupOpcodes() {
+void Mechanical::setupOpcodes() {
// "Stack-Specific" Opcodes
- OPCODE(104, opcode_104);
+ OPCODE(100, o_throneEnablePassage);
+ OPCODE(104, o_snakeBoxTrigger);
OPCODE(105, o_fortressStaircaseMovie);
- OPCODE(121, opcode_121);
- OPCODE(122, opcode_122);
- OPCODE(123, opcode_123);
+ OPCODE(106, o_elevatorRotationStart);
+ OPCODE(107, o_elevatorRotationMove);
+ OPCODE(108, o_elevatorRotationStop);
+ OPCODE(121, o_elevatorWindowMovie);
+ OPCODE(122, o_elevatorGoMiddle);
+ OPCODE(123, o_elevatorTopMovie);
OPCODE(124, opcode_124);
OPCODE(125, o_mystStaircaseMovie);
OPCODE(126, opcode_126);
@@ -66,44 +72,44 @@ void MystScriptParser_Mechanical::setupOpcodes() {
OPCODE(132, o_crystalLeaveRed);
// "Init" Opcodes
- OPCODE(200, opcode_200);
- OPCODE(201, opcode_201);
+ OPCODE(200, o_throne_init);
+ OPCODE(201, o_fortressStaircase_init);
OPCODE(202, opcode_202);
- OPCODE(203, opcode_203);
- OPCODE(204, opcode_204);
+ OPCODE(203, o_snakeBox_init);
+ OPCODE(204, o_elevatorRotation_init);
OPCODE(205, opcode_205);
OPCODE(206, opcode_206);
OPCODE(209, opcode_209);
// "Exit" Opcodes
- OPCODE(300, opcode_300);
+ OPCODE(300, NOP);
}
#undef OPCODE
-void MystScriptParser_Mechanical::disablePersistentScripts() {
- opcode_200_disable();
- opcode_201_disable();
+void Mechanical::disablePersistentScripts() {
opcode_202_disable();
- opcode_203_disable();
- opcode_204_disable();
opcode_205_disable();
opcode_206_disable();
opcode_209_disable();
+ _elevatorGoingMiddle = false;
}
-void MystScriptParser_Mechanical::runPersistentScripts() {
- opcode_200_run();
- opcode_201_run();
+void Mechanical::runPersistentScripts() {
opcode_202_run();
- opcode_203_run();
- opcode_204_run();
+
+ if (_elevatorRotationLeverMoving)
+ elevatorRotation_run();
+
+ if (_elevatorGoingMiddle)
+ elevatorGoMiddle_run();
+
opcode_205_run();
opcode_206_run();
opcode_209_run();
}
-uint16 MystScriptParser_Mechanical::getVar(uint16 var) {
+uint16 Mechanical::getVar(uint16 var) {
switch(var) {
case 0: // Sirrus's Secret Panel State
return _state.sirrusPanelState;
@@ -135,13 +141,15 @@ uint16 MystScriptParser_Mechanical::getVar(uint16 var) {
return _state.staircaseState;
case 11: // Fortress Elevator Rotation Position
return _state.elevatorRotation;
-// case 12: // Fortress Elevator Rotation Cog Position
-// return 0;
-// return 1;
-// return 2;
-// return 3;
-// return 4;
-// return 5;
+ case 12: // Fortress Elevator Rotation Cog Position
+ return 5 - (uint16)(_elevatorRotationGearPosition + 0.5) % 6;
+ case 13: // Elevator position
+ return _elevatorPosition;
+ case 14: // Elevator going down when at top
+ if (_elevatorGoingDown && _elevatorTooLate)
+ return 2;
+ else
+ return _elevatorGoingDown;
case 15: // Code Lock Execute Button Script
if (_mystStaircaseState)
return 0;
@@ -170,8 +178,12 @@ uint16 MystScriptParser_Mechanical::getVar(uint16 var) {
}
}
-void MystScriptParser_Mechanical::toggleVar(uint16 var) {
+void Mechanical::toggleVar(uint16 var) {
switch(var) {
+ case 0: // Sirrus's Secret Panel State
+ _state.sirrusPanelState ^= 1;
+ case 1: // Achenar's Secret Panel State
+ _state.achenarPanelState ^= 1;
case 3: // Achenar's Secret Room Crate State
_state.achenarCrateOpened ^= 1;
case 4: // Myst Book Room Staircase State
@@ -184,6 +196,9 @@ void MystScriptParser_Mechanical::toggleVar(uint16 var) {
case 19: // Code Lock Shape #4 - Right
_state.codeShape[var - 16] = (_state.codeShape[var - 16] + 1) % 10;
break;
+ case 23: // Elevator player is in cabin
+ _elevatorInCabin = false;
+ break;
case 102: // Red page
if (!(_globals.redPagesInBook & 4)) {
if (_globals.heldPage == 9)
@@ -206,10 +221,15 @@ void MystScriptParser_Mechanical::toggleVar(uint16 var) {
}
}
-bool MystScriptParser_Mechanical::setVarValue(uint16 var, uint16 value) {
+bool Mechanical::setVarValue(uint16 var, uint16 value) {
bool refresh = false;
switch (var) {
+ case 13:
+ _elevatorPosition = value;
+ case 14: // Elevator going down when at top
+ _elevatorGoingDown = value;
+ break;
default:
refresh = MystScriptParser::setVarValue(var, value);
break;
@@ -218,20 +238,20 @@ bool MystScriptParser_Mechanical::setVarValue(uint16 var, uint16 value) {
return refresh;
}
-void MystScriptParser_Mechanical::opcode_104(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Mechanical::o_throneEnablePassage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Enable throne passage", op);
- // Used on Mechanical Card 6043 (Weapons Rack with Snake Box)
- if (argc == 0) {
- debugC(kDebugScript, "Opcode %d: Trigger Playing Of Snake Movie", op);
+ _vm->_resources[argv[0]]->setEnabled(getVar(var));
+}
- // TODO: Trigger Type 6 To Play Snake Movie.. Resource #3 on card.
- } else
- unknown(op, var, argc, argv);
+void Mechanical::o_snakeBoxTrigger(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Trigger Playing Of Snake Movie", op);
+ // Used on Mechanical Card 6043 (Weapons Rack with Snake Box)
+ _snakeBox->playMovie();
}
-void MystScriptParser_Mechanical::o_fortressStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_fortressStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Play Stairs Movement Movie", op);
VideoHandle staircase = _vm->_video->playMovie(_vm->wrapMovieFilename("hhstairs", kMechanicalStack), 174, 222);
@@ -245,50 +265,168 @@ void MystScriptParser_Mechanical::o_fortressStaircaseMovie(uint16 op, uint16 var
_vm->_video->waitUntilMovieEnds(staircase);
}
+void Mechanical::o_elevatorRotationStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation lever start", op);
-void MystScriptParser_Mechanical::opcode_121(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ lever->drawFrame(0);
- if (argc == 2) {
- uint16 startTime = argv[0];
- uint16 endTime = argv[1];
+ _elevatorRotationLeverMoving = true;
+ _elevatorRotationSpeed = 0;
- warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, startTime, endTime);
- // TODO: Need version of playMovie blocking which allows selection
- // of start and finish points.
- _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0);
- } else
- unknown(op, var, argc, argv);
+ _vm->_sound->stopBackgroundMyst();
+
+ _vm->_cursor->setCursor(700);
}
-void MystScriptParser_Mechanical::opcode_122(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- if (argc == 0) {
- // Used on Card 6120 (Elevator)
- // Called when Exit Midde Button Pressed
+void Mechanical::o_elevatorRotationMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation lever move", op);
- // TODO: hcelev? Movie of Elevator?
- } else
- unknown(op, var, argc, argv);
+ const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+
+ // Make the handle follow the mouse
+ int16 maxStep = lever->getNumFrames() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((rect.bottom - mouse.y) * lever->getNumFrames()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ _elevatorRotationSpeed = step * 0.1;
+
+ // Draw current frame
+ lever->drawFrame(step);
}
-void MystScriptParser_Mechanical::opcode_123(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Mechanical::o_elevatorRotationStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation lever stop", op);
- if (argc == 2) {
- // Used on Card 6154
- uint16 start_time = argv[0];
- uint16 end_time = argv[1];
+ const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
- warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, start_time, end_time);
- // TODO: Need version of playMovie blocking which allows selection
- // of start and finish points.
- // TODO: Not 100% sure about movie position
- _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("hcelev", kMechanicalStack), 205, 40);
- } else
- unknown(op, var, argc, argv);
+ // Get current lever frame
+ int16 maxStep = lever->getNumFrames() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((rect.bottom - mouse.y) * lever->getNumFrames()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ // Release lever
+ for (int i = step; i >= 0; i--) {
+ lever->drawFrame(i);
+ _vm->_system->delayMillis(10);
+ }
+
+ // Stop persistent script
+ _elevatorRotationLeverMoving = false;
+
+ float speed = _elevatorRotationSpeed * 10;
+
+ if (speed > 0) {
+
+ // Decrease speed
+ while (speed > 2) {
+ speed -= 0.5;
+
+ _elevatorRotationGearPosition += speed * 0.1;
+
+ if (_elevatorRotationGearPosition > 12)
+ break;
+
+ _vm->redrawArea(12);
+ _vm->_system->delayMillis(100);
+ }
+
+ // Increment position
+ _state.elevatorRotation = (_state.elevatorRotation + 1) % 10;
+
+ _vm->_sound->replaceSoundMyst(_elevatorRotationSoundId);
+ _vm->redrawArea(11);
+ }
+
+ _vm->checkCursorHints();
+}
+
+void Mechanical::o_elevatorWindowMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 startTime = argv[0];
+ uint16 endTime = argv[1];
+
+ debugC(kDebugScript, "Opcode %d Movie Time Index %d to %d", op, startTime, endTime);
+
+ VideoHandle window = _vm->_video->playMovie(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0);
+ _vm->_video->setVideoBounds(window, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600));
+ _vm->_video->waitUntilMovieEnds(window);
+}
+
+void Mechanical::o_elevatorGoMiddle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator go middle from top", op);
+
+ _elevatorTooLate = false;
+ _elevatorTopCounter = 5;
+ _elevatorGoingMiddle = true;
+ _elevatorInCabin = true;
+ _elevatorNextTime = _vm->_system->getMillis() + 1000;
+}
+
+void Mechanical::elevatorGoMiddle_run() {
+ uint32 time = _vm->_system->getMillis();
+ if (_elevatorNextTime < time) {
+ _elevatorNextTime = time + 1000;
+ _elevatorTopCounter--;
+
+ if (_elevatorTopCounter > 0) {
+ // Draw button pressed
+ if (_elevatorInCabin) {
+ _vm->_gfx->copyImageSectionToScreen(6332, Common::Rect(0, 35, 51, 63), Common::Rect(10, 137, 61, 165));
+ _vm->_system->updateScreen();
+ }
+
+ // Blip
+ _vm->_sound->playSoundBlocking(14120);
+
+ // Restore button
+ if (_elevatorInCabin) {
+ _vm->_gfx->copyBackBufferToScreen(Common::Rect(10, 137, 61, 165));
+ _vm->_system->updateScreen();
+ }
+ } else if (_elevatorInCabin) {
+ _elevatorTooLate = true;
+
+ // Elevator going to middle animation
+ _vm->_cursor->hideCursor();
+ _vm->_sound->playSoundBlocking(11120);
+ _vm->_gfx->copyImageToBackBuffer(6118, Common::Rect(544, 333));
+ _vm->_sound->replaceSoundMyst(12120);
+ _vm->_gfx->runTransition(2, Common::Rect(177, 0, 370, 333), 25, 0);
+ _vm->_sound->playSoundBlocking(13120);
+ _vm->_sound->replaceSoundMyst(8120);
+ _vm->_gfx->copyImageToBackBuffer(6327, Common::Rect(544, 333));
+ _vm->_system->delayMillis(500);
+ _vm->_sound->replaceSoundMyst(9120);
+ static uint16 moviePos[2] = { 3540, 5380 };
+ o_elevatorWindowMovie(121, 0, 2, moviePos);
+ _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333));
+ _vm->_sound->replaceSoundMyst(10120);
+ _vm->_cursor->showCursor();
+
+ _elevatorGoingMiddle = false;
+ _elevatorPosition = 1;
+
+ _vm->changeToCard(6327, true);
+ }
+ }
+}
+
+void Mechanical::o_elevatorTopMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 startTime = argv[0];
+ uint16 endTime = argv[1];
+
+ debugC(kDebugScript, "Opcode %d Movie Time Index %d to %d", op, startTime, endTime);
+
+ VideoHandle window = _vm->_video->playMovie(_vm->wrapMovieFilename("hcelev", kMechanicalStack), 206, 38);
+ _vm->_video->setVideoBounds(window, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600));
+ _vm->_video->waitUntilMovieEnds(window);
}
-void MystScriptParser_Mechanical::opcode_124(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::opcode_124(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
if (argc == 0) {
@@ -300,13 +438,13 @@ void MystScriptParser_Mechanical::opcode_124(uint16 op, uint16 var, uint16 argc,
unknown(op, var, argc, argv);
}
-void MystScriptParser_Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Myst book staircase video", op);
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("sstairs", kMechanicalStack), 199, 108);
}
-void MystScriptParser_Mechanical::opcode_126(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::opcode_126(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
if (argc == 0) {
@@ -319,129 +457,77 @@ void MystScriptParser_Mechanical::opcode_126(uint16 op, uint16 var, uint16 argc,
unknown(op, var, argc, argv);
}
-void MystScriptParser_Mechanical::o_crystalEnterYellow(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_crystalEnterYellow(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Crystal enter", op);
_crystalLit = 3;
_vm->redrawArea(20);
}
-void MystScriptParser_Mechanical::o_crystalEnterGreen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_crystalEnterGreen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Crystal enter", op);
_crystalLit = 1;
_vm->redrawArea(21);
}
-void MystScriptParser_Mechanical::o_crystalEnterRed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_crystalEnterRed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Crystal enter", op);
_crystalLit = 2;
_vm->redrawArea(22);
}
-void MystScriptParser_Mechanical::o_crystalLeaveYellow(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_crystalLeaveYellow(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Crystal leave", op);
_crystalLit = 0;
_vm->redrawArea(20);
}
-void MystScriptParser_Mechanical::o_crystalLeaveGreen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_crystalLeaveGreen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Crystal leave", op);
_crystalLit = 0;
_vm->redrawArea(21);
}
-void MystScriptParser_Mechanical::o_crystalLeaveRed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::o_crystalLeaveRed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Crystal leave", op);
_crystalLit = 0;
_vm->redrawArea(22);
}
-static struct {
- bool enabled;
- uint16 var;
-} g_opcode200Parameters;
-
-void MystScriptParser_Mechanical::opcode_200_run() {
+void Mechanical::o_throne_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Card 6238 (Sirrus' Throne) and Card 6027 (Achenar's Throne)
- // g_opcode200Parameters.var == 0 for Achenar
- // g_opcode200Parameters.var == 1 for Sirrus
+ debugC(kDebugScript, "Opcode %d: Brother throne init", op);
- // TODO: Fill in Function...
- // Variable indicates that this is related to Secret Panel State
+ _invokingResource->setEnabled(getVar(var));
}
-void MystScriptParser_Mechanical::opcode_200_disable() {
- g_opcode200Parameters.enabled = false;
- g_opcode200Parameters.var = 0;
-}
+void Mechanical::o_fortressStaircase_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Staircase init", op);
-void MystScriptParser_Mechanical::opcode_200(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // Used on Card 6238 (Sirrus' Throne) and Card 6027 (Achenar's Throne)
- if (argc == 0) {
- g_opcode200Parameters.var = var;
- g_opcode200Parameters.enabled = true;
- } else
- unknown(op, var, argc, argv);
-}
-
-static struct {
- uint16 u0;
- uint16 u1;
- uint16 u2;
-
- bool enabled;
-} g_opcode201Parameters;
-
-void MystScriptParser_Mechanical::opcode_201_run() {
- // Used for Card 6159 (Facing Corridor to Fortress Elevator)
-
- // g_opcode201Parameters.u0
- // g_opcode201Parameters.u1
- // g_opcode201Parameters.u2
-
- // TODO: Fill in Function...
-}
-
-void MystScriptParser_Mechanical::opcode_201_disable() {
- g_opcode201Parameters.enabled = false;
- g_opcode201Parameters.u0 = 0;
- g_opcode201Parameters.u1 = 0;
- g_opcode201Parameters.u2 = 0;
-}
-
-void MystScriptParser_Mechanical::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
-
- // Used for Card 6159 (Facing Corridor to Fortress Elevator)
- if (argc == 3) {
- g_opcode201Parameters.u0 = argv[0];
- g_opcode201Parameters.u1 = argv[1];
- g_opcode201Parameters.u2 = argv[2];
-
- g_opcode201Parameters.enabled = true;
- } else
- unknown(op, var, argc, argv);
+ _vm->_resources[argv[0]]->setEnabled(!_state.staircaseState);
+ _vm->_resources[argv[1]]->setEnabled(!_state.staircaseState);
+ _vm->_resources[argv[2]]->setEnabled(_state.staircaseState);
}
static struct {
bool enabled;
} g_opcode202Parameters;
-void MystScriptParser_Mechanical::opcode_202_run() {
+void Mechanical::opcode_202_run() {
// Used for Card 6220 (Sirrus' Mechanical Bird)
// TODO: Fill in Function
}
-void MystScriptParser_Mechanical::opcode_202_disable() {
+void Mechanical::opcode_202_disable() {
g_opcode202Parameters.enabled = false;
}
-void MystScriptParser_Mechanical::opcode_202(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::opcode_202(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 6220 (Sirrus' Mechanical Bird)
if (argc == 0)
g_opcode202Parameters.enabled = true;
@@ -449,61 +535,35 @@ void MystScriptParser_Mechanical::opcode_202(uint16 op, uint16 var, uint16 argc,
unknown(op, var, argc, argv);
}
-static struct {
- bool enabled;
-} g_opcode203Parameters;
+void Mechanical::o_snakeBox_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Snake box init", op);
-void MystScriptParser_Mechanical::opcode_203_run() {
- if (g_opcode203Parameters.enabled) {
- // Used for Card 6043 (Weapons Rack with Snake Box)
- // TODO: Fill in Logic for Snake Box...
- }
+ _snakeBox = static_cast<MystResourceType6 *>(_invokingResource);
}
-void MystScriptParser_Mechanical::opcode_203_disable() {
- g_opcode203Parameters.enabled = false;
-}
+void Mechanical::elevatorRotation_run() {
+ _vm->redrawArea(12);
-void MystScriptParser_Mechanical::opcode_203(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+ _elevatorRotationGearPosition += _elevatorRotationSpeed;
- // Used for Card 6043 (Weapons Rack with Snake Box)
- if (argc == 0)
- g_opcode203Parameters.enabled = true;
- else
- unknown(op, var, argc, argv);
-}
+ if (_elevatorRotationGearPosition > 12) {
+ uint16 position = (uint16)_elevatorRotationGearPosition;
+ _elevatorRotationGearPosition = _elevatorRotationGearPosition - position + position % 6;
-static struct {
- bool enabled;
- uint16 soundId;
-} g_opcode204Parameters;
-
-void MystScriptParser_Mechanical::opcode_204_run() {
- if (g_opcode204Parameters.enabled) {
- // TODO: Fill in Logic.
- // Var 12 holds Large Cog Position in range 0 to 5
- // - For animation
- // Var 11 holds C position in range 0 to 9
- // - 4 for Correct Answer
- // C Movement Sound
- //_vm->_sound->playSound(g_opcode204Parameters.soundId);
- }
-}
+ _state.elevatorRotation = (_state.elevatorRotation + 1) % 10;
-void MystScriptParser_Mechanical::opcode_204_disable() {
- g_opcode204Parameters.enabled = false;
+ _vm->_sound->replaceSoundMyst(_elevatorRotationSoundId);
+ _vm->redrawArea(11);
+ _vm->_system->delayMillis(100);
+ }
}
-void MystScriptParser_Mechanical::opcode_204(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation init", op);
- // Used for Card 6180 (Lower Elevator Puzzle)
- if (argc == 1) {
- g_opcode204Parameters.soundId = argv[0];
- g_opcode204Parameters.enabled = true;
- } else
- unknown(op, var, argc, argv);
+ _elevatorRotationSoundId = argv[0];
+ _elevatorRotationGearPosition = 0;
+ _elevatorRotationLeverMoving = false;
}
static struct {
@@ -512,17 +572,17 @@ static struct {
bool enabled;
} g_opcode205Parameters;
-void MystScriptParser_Mechanical::opcode_205_run() {
+void Mechanical::opcode_205_run() {
// Used for Card 6156 (Fortress Rotation Controls)
// TODO: Fill in function...
// g_opcode205Parameters.soundIdPosition[4]
}
-void MystScriptParser_Mechanical::opcode_205_disable() {
+void Mechanical::opcode_205_disable() {
g_opcode205Parameters.enabled = false;
}
-void MystScriptParser_Mechanical::opcode_205(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::opcode_205(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used for Card 6156 (Fortress Rotation Controls)
@@ -545,7 +605,7 @@ static struct {
bool enabled;
} g_opcode206Parameters;
-void MystScriptParser_Mechanical::opcode_206_run() {
+void Mechanical::opcode_206_run() {
if (g_opcode206Parameters.enabled) {
// Used for Card 6044 (Fortress Rotation Simulator)
@@ -556,11 +616,11 @@ void MystScriptParser_Mechanical::opcode_206_run() {
}
}
-void MystScriptParser_Mechanical::opcode_206_disable() {
+void Mechanical::opcode_206_disable() {
g_opcode206Parameters.enabled = false;
}
-void MystScriptParser_Mechanical::opcode_206(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::opcode_206(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used for Card 6044 (Fortress Rotation Simulator)
@@ -582,18 +642,18 @@ static struct {
bool enabled;
} g_opcode209Parameters;
-void MystScriptParser_Mechanical::opcode_209_run() {
+void Mechanical::opcode_209_run() {
// Used for Card 6044 (Fortress Rotation Simulator)
// TODO: Implement Function For Secret Panel State as
// per Opcode 200 function (Mechanical)
}
-void MystScriptParser_Mechanical::opcode_209_disable() {
+void Mechanical::opcode_209_disable() {
g_opcode209Parameters.enabled = false;
}
-void MystScriptParser_Mechanical::opcode_209(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Mechanical::opcode_209(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used for Card 6044 (Fortress Rotation Simulator)
@@ -603,10 +663,5 @@ void MystScriptParser_Mechanical::opcode_209(uint16 op, uint16 var, uint16 argc,
unknown(op, var, argc, argv);
}
-void MystScriptParser_Mechanical::opcode_300(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // Used in Card 6156 (Fortress Elevator View)
- varUnusedCheck(op, var);
- // TODO: Fill in Logic. Clearing Variable for View?
-}
-
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/mechanical.h b/engines/mohawk/myst_stacks/mechanical.h
index 3c7701c12d..6a0aa30f5c 100644
--- a/engines/mohawk/myst_stacks/mechanical.h
+++ b/engines/mohawk/myst_stacks/mechanical.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Mechanical : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Mechanical : public MystScriptParser {
public:
- MystScriptParser_Mechanical(MohawkEngine_Myst *vm);
- ~MystScriptParser_Mechanical();
+ Mechanical(MohawkEngine_Myst *vm);
+ ~Mechanical();
void disablePersistentScripts();
void runPersistentScripts();
@@ -51,16 +52,10 @@ private:
void toggleVar(uint16 var);
bool setVarValue(uint16 var, uint16 value);
- void opcode_200_run();
- void opcode_200_disable();
- void opcode_201_run();
- void opcode_201_disable();
void opcode_202_run();
void opcode_202_disable();
- void opcode_203_run();
- void opcode_203_disable();
- void opcode_204_run();
- void opcode_204_disable();
+ void elevatorRotation_run();
+ void elevatorGoMiddle_run();
void opcode_205_run();
void opcode_205_disable();
void opcode_206_run();
@@ -68,11 +63,15 @@ private:
void opcode_209_run();
void opcode_209_disable();
- DECLARE_OPCODE(opcode_104);
+ DECLARE_OPCODE(o_throneEnablePassage);
+ DECLARE_OPCODE(o_snakeBoxTrigger);
DECLARE_OPCODE(o_fortressStaircaseMovie);
- DECLARE_OPCODE(opcode_121);
- DECLARE_OPCODE(opcode_122);
- DECLARE_OPCODE(opcode_123);
+ DECLARE_OPCODE(o_elevatorRotationStart);
+ DECLARE_OPCODE(o_elevatorRotationMove);
+ DECLARE_OPCODE(o_elevatorRotationStop);
+ DECLARE_OPCODE(o_elevatorWindowMovie);
+ DECLARE_OPCODE(o_elevatorGoMiddle);
+ DECLARE_OPCODE(o_elevatorTopMovie);
DECLARE_OPCODE(opcode_124);
DECLARE_OPCODE(o_mystStaircaseMovie);
DECLARE_OPCODE(opcode_126);
@@ -83,26 +82,41 @@ private:
DECLARE_OPCODE(o_crystalLeaveGreen);
DECLARE_OPCODE(o_crystalLeaveRed);
- DECLARE_OPCODE(opcode_200);
- DECLARE_OPCODE(opcode_201);
+ DECLARE_OPCODE(o_throne_init);
+ DECLARE_OPCODE(o_fortressStaircase_init);
DECLARE_OPCODE(opcode_202);
- DECLARE_OPCODE(opcode_203);
- DECLARE_OPCODE(opcode_204);
+ DECLARE_OPCODE(o_snakeBox_init);
+ DECLARE_OPCODE(o_elevatorRotation_init);
DECLARE_OPCODE(opcode_205);
DECLARE_OPCODE(opcode_206);
DECLARE_OPCODE(opcode_209);
- DECLARE_OPCODE(opcode_300);
-
MystGameState::Mechanical &_state;
bool _mystStaircaseState; // 76
uint16 _fortressPosition; // 82
+ uint16 _elevatorGoingDown; // 112
+
+ float _elevatorRotationSpeed; // 120
+ float _elevatorRotationGearPosition; // 124
+ uint16 _elevatorRotationSoundId; // 128
+ bool _elevatorRotationLeverMoving; // 184
+
+ bool _elevatorGoingMiddle; // 148
+ bool _elevatorTooLate;
+ uint16 _elevatorPosition; // 104
+ bool _elevatorInCabin; // 108
+ uint16 _elevatorTopCounter;
+ uint32 _elevatorNextTime;
+
uint16 _crystalLit; // 130
+
+ MystResourceType6 *_snakeBox; // 156
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index 3bcc83527b..5d070322ca 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -37,10 +37,9 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-// NOTE: Credits Start Card is 10000
-
-MystScriptParser_Myst::MystScriptParser_Myst(MohawkEngine_Myst *vm) :
+Myst::Myst(MohawkEngine_Myst *vm) :
MystScriptParser(vm), _state(_vm->_gameState->_myst) {
setupOpcodes();
@@ -48,8 +47,10 @@ MystScriptParser_Myst::MystScriptParser_Myst(MohawkEngine_Myst *vm) :
// when linking back to Myst in the library
_savedCardId = 4329;
+ _towerRotationBlinkLabel = false;
_libraryBookcaseChanged = false;
_dockVaultState = 0;
+ _cabinDoorOpened = 0;
_cabinMatchState = 2;
_matchBurning = false;
_tree = 0;
@@ -62,12 +63,12 @@ MystScriptParser_Myst::MystScriptParser_Myst(MohawkEngine_Myst *vm) :
_state.treeLastMoveTime = _vm->_system->getMillis();
}
-MystScriptParser_Myst::~MystScriptParser_Myst() {
+Myst::~Myst() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Myst::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Myst::x, #x))
-void MystScriptParser_Myst::setupOpcodes() {
+void Myst::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, NOP);
OPCODE(101, o_libraryBookPageTurnLeft);
@@ -211,7 +212,7 @@ void MystScriptParser_Myst::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Myst::disablePersistentScripts() {
+void Myst::disablePersistentScripts() {
_libraryBookcaseMoving = false;
_generatorControlRoomRunning = false;
_libraryCombinationBookPagesTurning = false;
@@ -235,7 +236,7 @@ void MystScriptParser_Myst::disablePersistentScripts() {
_gullsFlying3 = false;
}
-void MystScriptParser_Myst::runPersistentScripts() {
+void Myst::runPersistentScripts() {
if (_towerRotationMapRunning)
towerRotationMap_run();
@@ -306,7 +307,7 @@ void MystScriptParser_Myst::runPersistentScripts() {
gullsFly3_run();
}
-uint16 MystScriptParser_Myst::getVar(uint16 var) {
+uint16 Myst::getVar(uint16 var) {
switch(var) {
case 0: // Myst Library Bookcase Closed
return _state.libraryBookcaseDoor;
@@ -630,7 +631,7 @@ uint16 MystScriptParser_Myst::getVar(uint16 var) {
}
}
-void MystScriptParser_Myst::toggleVar(uint16 var) {
+void Myst::toggleVar(uint16 var) {
switch(var) {
case 2: // Marker Switch Near Cabin
_state.cabinMarkerSwitch = (_state.cabinMarkerSwitch + 1) % 2;
@@ -720,7 +721,7 @@ void MystScriptParser_Myst::toggleVar(uint16 var) {
}
}
-bool MystScriptParser_Myst::setVarValue(uint16 var, uint16 value) {
+bool Myst::setVarValue(uint16 var, uint16 value) {
bool refresh = false;
switch (var) {
@@ -775,7 +776,7 @@ bool MystScriptParser_Myst::setVarValue(uint16 var, uint16 value) {
return refresh;
}
-uint16 MystScriptParser_Myst::bookCountPages(uint16 var) {
+uint16 Myst::bookCountPages(uint16 var) {
uint16 pages = 0;
uint16 cnt = 0;
@@ -808,7 +809,7 @@ uint16 MystScriptParser_Myst::bookCountPages(uint16 var) {
return cnt;
}
-void MystScriptParser_Myst::o_libraryBookPageTurnLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryBookPageTurnLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Turn book page left", op);
if (_libraryBookPage - 1 >= 0) {
@@ -826,7 +827,7 @@ void MystScriptParser_Myst::o_libraryBookPageTurnLeft(uint16 op, uint16 var, uin
}
}
-void MystScriptParser_Myst::o_libraryBookPageTurnRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryBookPageTurnRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Turn book page right", op);
if (_libraryBookPage + 1 < _libraryBookNumPages) {
@@ -844,7 +845,7 @@ void MystScriptParser_Myst::o_libraryBookPageTurnRight(uint16 op, uint16 var, ui
}
}
-void MystScriptParser_Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Myst Card 4162 (Fireplace Grid)
debugC(kDebugScript, "Opcode %d: Fireplace grid toggle button", op);
@@ -873,7 +874,7 @@ void MystScriptParser_Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint1
}
}
-void MystScriptParser_Myst::o_fireplaceRotation(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_fireplaceRotation(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Myst Card 4162 and 4166 (Fireplace Puzzle Rotation Movies)
uint16 movieNum = argv[0];
debugC(kDebugScript, "Opcode %d: Play Fireplace Puzzle Rotation Movies", op);
@@ -885,7 +886,7 @@ void MystScriptParser_Myst::o_fireplaceRotation(uint16 op, uint16 var, uint16 ar
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("fpin", kMystStack), 167, 4);
}
-void MystScriptParser_Myst::o_courtyardBoxesCheckSolution(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_courtyardBoxesCheckSolution(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
uint16 soundId = argv[0];
debugC(kDebugScript, "Opcode %d: Ship Puzzle Logic", op);
@@ -905,7 +906,7 @@ void MystScriptParser_Myst::o_courtyardBoxesCheckSolution(uint16 op, uint16 var,
}
}
-void MystScriptParser_Myst::o_towerRotationStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_towerRotationStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_towerRotationBlinkLabel = false;
_towerRotationMapClicked = true;
_towerRotationSpeed = 0;
@@ -920,7 +921,7 @@ void MystScriptParser_Myst::o_towerRotationStart(uint16 op, uint16 var, uint16 a
_vm->_sound->replaceSoundMyst(5378, Audio::Mixer::kMaxChannelVolume, true);
}
-void MystScriptParser_Myst::o_towerRotationEnd(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_towerRotationEnd(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_towerRotationMapClicked = false;
// Set angle value to expected value
@@ -948,7 +949,7 @@ void MystScriptParser_Myst::o_towerRotationEnd(uint16 op, uint16 var, uint16 arg
_towerRotationBlinkLabelCount = 0;
}
-void MystScriptParser_Myst::o_imagerChangeSelection(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_imagerChangeSelection(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Dock imager change selection", op);
if (_imagerValidationStep != 10) {
@@ -974,7 +975,7 @@ void MystScriptParser_Myst::o_imagerChangeSelection(uint16 op, uint16 var, uint1
}
}
-void MystScriptParser_Myst::o_dockVaultOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_dockVaultOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Myst 4143 (Dock near Marker Switch)
uint16 soundId = argv[0];
uint16 delay = argv[1];
@@ -1003,7 +1004,7 @@ void MystScriptParser_Myst::o_dockVaultOpen(uint16 op, uint16 var, uint16 argc,
}
}
-void MystScriptParser_Myst::o_dockVaultClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_dockVaultClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Myst 4143 (Dock near Marker Switch)
uint16 soundId = argv[0];
uint16 delay = argv[1];
@@ -1030,7 +1031,7 @@ void MystScriptParser_Myst::o_dockVaultClose(uint16 op, uint16 var, uint16 argc,
}
}
-void MystScriptParser_Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
uint16 cardIdLose = argv[0];
uint16 cardIdBookCover = argv[1];
uint16 soundIdAddPage = argv[2];
@@ -1117,7 +1118,7 @@ void MystScriptParser_Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, u
}
}
-void MystScriptParser_Myst::o_clockWheelsExecute(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockWheelsExecute(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Card 4006 (Clock Tower Time Controls)
uint16 soundId = argv[0];
@@ -1153,7 +1154,7 @@ void MystScriptParser_Myst::o_clockWheelsExecute(uint16 op, uint16 var, uint16 a
}
}
-void MystScriptParser_Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Imager play button", op);
uint16 video = getVar(51);
@@ -1232,7 +1233,7 @@ void MystScriptParser_Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 arg
_vm->_cursor->showCursor();
}
-void MystScriptParser_Myst::o_imagerEraseButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_imagerEraseButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Imager erase button", op);
_imagerRedButton = static_cast<MystResourceType8 *>(_invokingResource->_parent);
@@ -1279,7 +1280,7 @@ void MystScriptParser_Myst::o_imagerEraseButton(uint16 op, uint16 var, uint16 ar
}
}
-void MystScriptParser_Myst::imagerValidation_run() {
+void Myst::imagerValidation_run() {
uint32 time = _vm->_system->getMillis();
if (time > _startTime) {
@@ -1307,7 +1308,7 @@ void MystScriptParser_Myst::imagerValidation_run() {
}
}
-void MystScriptParser_Myst::o_towerElevatorAnimation(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_towerElevatorAnimation(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Tower elevator animation", op);
_treeStopped = true;
@@ -1332,7 +1333,7 @@ void MystScriptParser_Myst::o_towerElevatorAnimation(uint16 op, uint16 var, uint
_treeStopped = false;
}
-void MystScriptParser_Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator button pressed", op);
MystResource *button = _invokingResource->_parent;
@@ -1374,13 +1375,13 @@ void MystScriptParser_Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint
_state.generatorBreakers = _vm->_rnd->getRandomNumberRng(1, 2);
}
-void MystScriptParser_Myst::generatorRedrawRocket() {
+void Myst::generatorRedrawRocket() {
_vm->redrawArea(64);
_vm->redrawArea(65);
_vm->redrawArea(97);
}
-void MystScriptParser_Myst::generatorButtonValue(MystResource *button, uint16 &mask, uint16 &value) {
+void Myst::generatorButtonValue(MystResource *button, uint16 &mask, uint16 &value) {
switch (button->getType8Var()) {
case 52: // Generator Switch #1
mask = 1;
@@ -1425,7 +1426,7 @@ void MystScriptParser_Myst::generatorButtonValue(MystResource *button, uint16 &m
}
}
-void MystScriptParser_Myst::o_cabinSafeChangeDigit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_cabinSafeChangeDigit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cabin safe change digit", op);
uint16 d1 = _state.cabinSafeCombination / 100;
@@ -1444,7 +1445,7 @@ void MystScriptParser_Myst::o_cabinSafeChangeDigit(uint16 op, uint16 var, uint16
_vm->redrawArea(var);
}
-void MystScriptParser_Myst::o_cabinSafeHandleStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_cabinSafeHandleStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cabin safe handle start move", op);
// Used on Card 4100
@@ -1454,7 +1455,7 @@ void MystScriptParser_Myst::o_cabinSafeHandleStartMove(uint16 op, uint16 var, ui
_tempVar = 0;
}
-void MystScriptParser_Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cabin safe handle move", op);
// Used on Card 4100
@@ -1484,7 +1485,7 @@ void MystScriptParser_Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16
}
}
-void MystScriptParser_Myst::o_cabinSafeHandleEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_cabinSafeHandleEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cabin safe handle end move", op);
// Used on Card 4100
@@ -1493,7 +1494,7 @@ void MystScriptParser_Myst::o_cabinSafeHandleEndMove(uint16 op, uint16 var, uint
_vm->checkCursorHints();
}
-void MystScriptParser_Myst::o_observatoryMonthChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryMonthChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Observatory month change start", op);
_vm->_sound->pauseBackgroundMyst();
@@ -1528,7 +1529,7 @@ void MystScriptParser_Myst::o_observatoryMonthChangeStart(uint16 op, uint16 var,
_observatoryMonthChanging = true;
}
-void MystScriptParser_Myst::observatoryIncrementMonth(int16 increment) {
+void Myst::observatoryIncrementMonth(int16 increment) {
int16 newMonth = _state.observatoryMonthSetting + increment;
if (newMonth >= 0 && newMonth <= 11) {
@@ -1547,12 +1548,12 @@ void MystScriptParser_Myst::observatoryIncrementMonth(int16 increment) {
_vm->_sound->replaceSoundMyst(8500);
}
-void MystScriptParser_Myst::observatoryMonthChange_run() {
+void Myst::observatoryMonthChange_run() {
if (_startTime + 500 < _vm->_system->getMillis())
observatoryIncrementMonth(_observatoryIncrement);
}
-void MystScriptParser_Myst::o_observatoryDayChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryDayChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Observatory day change start", op);
_vm->_sound->pauseBackgroundMyst();
@@ -1587,7 +1588,7 @@ void MystScriptParser_Myst::o_observatoryDayChangeStart(uint16 op, uint16 var, u
_observatoryDayChanging = true;
}
-void MystScriptParser_Myst::observatoryIncrementDay(int16 increment) {
+void Myst::observatoryIncrementDay(int16 increment) {
int16 newDay = _state.observatoryDaySetting + increment;
if (newDay >= 1 && newDay <= 31) {
@@ -1607,12 +1608,12 @@ void MystScriptParser_Myst::observatoryIncrementDay(int16 increment) {
_vm->_sound->replaceSoundMyst(8500);
}
-void MystScriptParser_Myst::observatoryDayChange_run() {
+void Myst::observatoryDayChange_run() {
if (_startTime + 500 < _vm->_system->getMillis())
observatoryIncrementDay(_observatoryIncrement);
}
-void MystScriptParser_Myst::o_observatoryYearChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryYearChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Observatory year change start", op);
_vm->_sound->pauseBackgroundMyst();
@@ -1639,7 +1640,7 @@ void MystScriptParser_Myst::o_observatoryYearChangeStart(uint16 op, uint16 var,
_observatoryYearChanging = true;
}
-void MystScriptParser_Myst::observatoryIncrementYear(int16 increment) {
+void Myst::observatoryIncrementYear(int16 increment) {
int16 newYear = _state.observatoryYearSetting + increment;
if (newYear >= 0 && newYear <= 9999) {
@@ -1661,12 +1662,12 @@ void MystScriptParser_Myst::observatoryIncrementYear(int16 increment) {
_vm->_sound->replaceSoundMyst(8500);
}
-void MystScriptParser_Myst::observatoryYearChange_run() {
+void Myst::observatoryYearChange_run() {
if (_startTime + 500 < _vm->_system->getMillis())
observatoryIncrementYear(_observatoryIncrement);
}
-void MystScriptParser_Myst::o_observatoryTimeChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryTimeChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Observatory time change start", op);
_vm->_sound->pauseBackgroundMyst();
@@ -1693,7 +1694,7 @@ void MystScriptParser_Myst::o_observatoryTimeChangeStart(uint16 op, uint16 var,
_observatoryTimeChanging = true;
}
-void MystScriptParser_Myst::observatoryIncrementTime(int16 increment) {
+void Myst::observatoryIncrementTime(int16 increment) {
int16 newTime = _state.observatoryTimeSetting + increment;
if (newTime >= 0 && newTime <= 1439) {
@@ -1720,12 +1721,12 @@ void MystScriptParser_Myst::observatoryIncrementTime(int16 increment) {
_vm->_sound->replaceSoundMyst(8500);
}
-void MystScriptParser_Myst::observatoryTimeChange_run() {
+void Myst::observatoryTimeChange_run() {
if (_startTime + 500 < _vm->_system->getMillis())
observatoryIncrementTime(_observatoryIncrement);
}
-void MystScriptParser_Myst::o_observatoryGoButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryGoButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Observatory go button", op);
// Setting not at target
@@ -1759,31 +1760,31 @@ void MystScriptParser_Myst::o_observatoryGoButton(uint16 op, uint16 var, uint16
}
}
-void MystScriptParser_Myst::o_observatoryMonthSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryMonthSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Month slider move", op);
observatoryUpdateMonth();
}
-void MystScriptParser_Myst::o_observatoryDaySliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryDaySliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Day slider move", op);
observatoryUpdateDay();
}
-void MystScriptParser_Myst::o_observatoryYearSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryYearSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Year slider move", op);
observatoryUpdateYear();
}
-void MystScriptParser_Myst::o_observatoryTimeSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryTimeSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Time slider move", op);
observatoryUpdateTime();
}
-void MystScriptParser_Myst::o_circuitBreakerStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_circuitBreakerStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Circuit breaker start move", op);
MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
@@ -1792,7 +1793,7 @@ void MystScriptParser_Myst::o_circuitBreakerStartMove(uint16 op, uint16 var, uin
_tempVar = 0;
}
-void MystScriptParser_Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Circuit breaker move", op);
MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
@@ -1843,7 +1844,7 @@ void MystScriptParser_Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 a
}
}
-void MystScriptParser_Myst::o_circuitBreakerEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_circuitBreakerEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Circuit breaker end move", op);
MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
@@ -1851,7 +1852,7 @@ void MystScriptParser_Myst::o_circuitBreakerEndMove(uint16 op, uint16 var, uint1
_vm->checkCursorHints();
}
-void MystScriptParser_Myst::o_boilerIncreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_boilerIncreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Boiler increase pressure start", op);
_treeStopped = true;
@@ -1861,7 +1862,7 @@ void MystScriptParser_Myst::o_boilerIncreasePressureStart(uint16 op, uint16 var,
_boilerPressureIncreasing = true;
}
-void MystScriptParser_Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Boiler light pilot", op);
// Match is lit
@@ -1882,7 +1883,7 @@ void MystScriptParser_Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 arg
}
}
-void MystScriptParser_Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Boiler increase pressure stop", op);
_treeStopped = false;
@@ -1898,7 +1899,7 @@ void MystScriptParser_Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var,
_vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10);
}
-void MystScriptParser_Myst::boilerPressureIncrease_run() {
+void Myst::boilerPressureIncrease_run() {
// Allow increasing pressure if sound has stopped
if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition < 25) {
_state.cabinValvePosition++;
@@ -1922,7 +1923,7 @@ void MystScriptParser_Myst::boilerPressureIncrease_run() {
}
}
-void MystScriptParser_Myst::boilerPressureDecrease_run() {
+void Myst::boilerPressureDecrease_run() {
// Allow decreasing pressure if sound has stopped
if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition > 0) {
_state.cabinValvePosition--;
@@ -1941,7 +1942,7 @@ void MystScriptParser_Myst::boilerPressureDecrease_run() {
}
}
-void MystScriptParser_Myst::o_boilerDecreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_boilerDecreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Boiler decrease pressure start", op);
_treeStopped = true;
@@ -1950,7 +1951,7 @@ void MystScriptParser_Myst::o_boilerDecreasePressureStart(uint16 op, uint16 var,
_boilerPressureDecreasing = true;
}
-void MystScriptParser_Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Boiler decrease pressure stop", op);
_treeStopped = false;
@@ -1968,14 +1969,14 @@ void MystScriptParser_Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var,
}
}
-void MystScriptParser_Myst::o_basementIncreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_basementIncreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Basement increase pressure start", op);
_treeStopped = true;
_basementPressureIncreasing = true;
}
-void MystScriptParser_Myst::o_basementIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_basementIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Basement increase pressure stop", op);
_treeStopped = false;
@@ -1983,7 +1984,7 @@ void MystScriptParser_Myst::o_basementIncreasePressureStop(uint16 op, uint16 var
_state.treeLastMoveTime = _vm->_system->getMillis();
}
-void MystScriptParser_Myst::basementPressureIncrease_run() {
+void Myst::basementPressureIncrease_run() {
// Allow increasing pressure if sound has stopped
if (!_vm->_sound->isPlaying(4642) && _state.cabinValvePosition < 25) {
_state.cabinValvePosition++;
@@ -1996,7 +1997,7 @@ void MystScriptParser_Myst::basementPressureIncrease_run() {
}
}
-void MystScriptParser_Myst::basementPressureDecrease_run() {
+void Myst::basementPressureDecrease_run() {
// Allow decreasing pressure if sound has stopped
if (!_vm->_sound->isPlaying(4642) && _state.cabinValvePosition > 0) {
_state.cabinValvePosition--;
@@ -2009,14 +2010,14 @@ void MystScriptParser_Myst::basementPressureDecrease_run() {
}
}
-void MystScriptParser_Myst::o_basementDecreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_basementDecreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Basement decrease pressure start", op);
_treeStopped = true;
_basementPressureDecreasing = true;
}
-void MystScriptParser_Myst::o_basementDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_basementDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Basement decrease pressure stop", op);
_treeStopped = false;
@@ -2024,7 +2025,7 @@ void MystScriptParser_Myst::o_basementDecreasePressureStop(uint16 op, uint16 var
_state.treeLastMoveTime = _vm->_system->getMillis();
}
-void MystScriptParser_Myst::tree_run() {
+void Myst::tree_run() {
uint16 pressure;
if (_state.cabinPilotLightLit)
pressure = _state.cabinValvePosition;
@@ -2073,7 +2074,7 @@ void MystScriptParser_Myst::tree_run() {
}
}
-void MystScriptParser_Myst::treeSetAlcoveAccessible() {
+void Myst::treeSetAlcoveAccessible() {
if (_treeAlcove) {
// Make alcove accessible if the tree is in the correct position
_treeAlcove->setEnabled(_state.treePosition >= _treeMinAccessiblePosition
@@ -2081,14 +2082,14 @@ void MystScriptParser_Myst::treeSetAlcoveAccessible() {
}
}
-uint32 MystScriptParser_Myst::treeNextMoveDelay(uint16 pressure) {
+uint32 Myst::treeNextMoveDelay(uint16 pressure) {
if (pressure >= 12)
return 25000 * (13 - (pressure - 12)) / 12 + 3000;
else
return 25000 * pressure / 13 + 3000;
}
-void MystScriptParser_Myst::o_rocketSoundSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketSoundSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket slider start move", op);
_rocketSliderSound = 0;
@@ -2097,13 +2098,13 @@ void MystScriptParser_Myst::o_rocketSoundSliderStartMove(uint16 op, uint16 var,
rocketSliderMove();
}
-void MystScriptParser_Myst::o_rocketSoundSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketSoundSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket slider move", op);
rocketSliderMove();
}
-void MystScriptParser_Myst::o_rocketSoundSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketSoundSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket slider end move", op);
_vm->checkCursorHints();
@@ -2125,7 +2126,7 @@ void MystScriptParser_Myst::o_rocketSoundSliderEndMove(uint16 op, uint16 var, ui
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Myst::rocketSliderMove() {
+void Myst::rocketSliderMove() {
MystResourceType10 *slider = static_cast<MystResourceType10 *>(_invokingResource);
if (_state.generatorVoltage == 59 && !_state.generatorBreakers) {
@@ -2137,11 +2138,11 @@ void MystScriptParser_Myst::rocketSliderMove() {
}
}
-uint16 MystScriptParser_Myst::rocketSliderGetSound(uint16 pos) {
+uint16 Myst::rocketSliderGetSound(uint16 pos) {
return (uint16)(9530 + (pos - 216) * 35.0 * 0.01639344262295082);
}
-void MystScriptParser_Myst::rocketCheckSolution() {
+void Myst::rocketCheckSolution() {
_vm->_cursor->hideCursor();
uint16 soundId;
@@ -2211,7 +2212,7 @@ void MystScriptParser_Myst::rocketCheckSolution() {
_vm->_cursor->showCursor();
}
-void MystScriptParser_Myst::o_rocketPianoStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketPianoStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket piano start move", op);
MystResourceType11 *key = static_cast<MystResourceType11 *>(_invokingResource);
@@ -2234,7 +2235,7 @@ void MystScriptParser_Myst::o_rocketPianoStart(uint16 op, uint16 var, uint16 arg
}
}
-void MystScriptParser_Myst::o_rocketPianoMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketPianoMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket piano move", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
@@ -2280,7 +2281,7 @@ void MystScriptParser_Myst::o_rocketPianoMove(uint16 op, uint16 var, uint16 argc
_vm->_system->updateScreen();
}
-void MystScriptParser_Myst::o_rocketPianoStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketPianoStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket piano end move", op);
MystResourceType8 *key = static_cast<MystResourceType8 *>(_invokingResource);
@@ -2298,7 +2299,7 @@ void MystScriptParser_Myst::o_rocketPianoStop(uint16 op, uint16 var, uint16 argc
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Myst::o_rocketLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket lever start move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -2308,7 +2309,7 @@ void MystScriptParser_Myst::o_rocketLeverStartMove(uint16 op, uint16 var, uint16
lever->drawFrame(0);
}
-void MystScriptParser_Myst::o_rocketOpenBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketOpenBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket open link book", op);
// Flyby movie
@@ -2318,7 +2319,7 @@ void MystScriptParser_Myst::o_rocketOpenBook(uint16 op, uint16 var, uint16 argc,
_tempVar = 2;
}
-void MystScriptParser_Myst::o_rocketLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket lever move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -2347,7 +2348,7 @@ void MystScriptParser_Myst::o_rocketLeverMove(uint16 op, uint16 var, uint16 argc
_rocketLeverPosition = step;
}
-void MystScriptParser_Myst::o_rocketLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket lever end move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -2357,7 +2358,7 @@ void MystScriptParser_Myst::o_rocketLeverEndMove(uint16 op, uint16 var, uint16 a
lever->drawFrame(0);
}
-void MystScriptParser_Myst::o_cabinLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_cabinLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Leave cabin", op);
// If match is lit, put out
@@ -2369,7 +2370,7 @@ void MystScriptParser_Myst::o_cabinLeave(uint16 op, uint16 var, uint16 argc, uin
}
}
-void MystScriptParser_Myst::o_treePressureReleaseStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_treePressureReleaseStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Tree pressure release start", op);
Common::Rect src = Common::Rect(0, 0, 49, 86);
@@ -2386,7 +2387,7 @@ void MystScriptParser_Myst::o_treePressureReleaseStart(uint16 op, uint16 var, ui
}
}
-void MystScriptParser_Myst::o_treePressureReleaseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_treePressureReleaseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Tree pressure release stop", op);
Common::Rect rect = Common::Rect(78, 46, 127, 132);
@@ -2397,7 +2398,7 @@ void MystScriptParser_Myst::o_treePressureReleaseStop(uint16 op, uint16 var, uin
_treeMinPosition = 0;
}
-void MystScriptParser_Myst::o_observatoryMonthSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryMonthSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Month slider start move", op);
_vm->_cursor->setCursor(700);
@@ -2406,7 +2407,7 @@ void MystScriptParser_Myst::o_observatoryMonthSliderStartMove(uint16 op, uint16
observatoryUpdateMonth();
}
-void MystScriptParser_Myst::o_observatoryMonthSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryMonthSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Month slider end move", op);
_vm->checkCursorHints();
@@ -2415,7 +2416,7 @@ void MystScriptParser_Myst::o_observatoryMonthSliderEndMove(uint16 op, uint16 va
observatoryUpdateMonth();
}
-void MystScriptParser_Myst::observatoryUpdateMonth() {
+void Myst::observatoryUpdateMonth() {
int16 month = (_observatoryMonthSlider->_pos.y - 94) / 8;
if (month != _state.observatoryMonthSetting) {
@@ -2428,7 +2429,7 @@ void MystScriptParser_Myst::observatoryUpdateMonth() {
}
}
-void MystScriptParser_Myst::o_observatoryDaySliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryDaySliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Day slider start move", op);
_vm->_cursor->setCursor(700);
@@ -2437,7 +2438,7 @@ void MystScriptParser_Myst::o_observatoryDaySliderStartMove(uint16 op, uint16 va
observatoryUpdateDay();
}
-void MystScriptParser_Myst::o_observatoryDaySliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryDaySliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Day slider end move", op);
_vm->checkCursorHints();
@@ -2446,7 +2447,7 @@ void MystScriptParser_Myst::o_observatoryDaySliderEndMove(uint16 op, uint16 var,
observatoryUpdateDay();
}
-void MystScriptParser_Myst::observatoryUpdateDay() {
+void Myst::observatoryUpdateDay() {
int16 day = (_observatoryDaySlider->_pos.y - 94) * 30 / 94 + 1;
if (day != _state.observatoryDaySetting) {
@@ -2460,7 +2461,7 @@ void MystScriptParser_Myst::observatoryUpdateDay() {
}
}
-void MystScriptParser_Myst::o_observatoryYearSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryYearSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Year slider start move", op);
_vm->_cursor->setCursor(700);
@@ -2469,7 +2470,7 @@ void MystScriptParser_Myst::o_observatoryYearSliderStartMove(uint16 op, uint16 v
observatoryUpdateYear();
}
-void MystScriptParser_Myst::o_observatoryYearSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryYearSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Year slider end move", op);
_vm->checkCursorHints();
@@ -2478,7 +2479,7 @@ void MystScriptParser_Myst::o_observatoryYearSliderEndMove(uint16 op, uint16 var
observatoryUpdateYear();
}
-void MystScriptParser_Myst::observatoryUpdateYear() {
+void Myst::observatoryUpdateYear() {
int16 year = (_observatoryYearSlider->_pos.y - 94) * 9999 / 94;
if (year != _state.observatoryYearSetting) {
@@ -2494,7 +2495,7 @@ void MystScriptParser_Myst::observatoryUpdateYear() {
}
}
-void MystScriptParser_Myst::o_observatoryTimeSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryTimeSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Time slider start move", op);
_vm->_cursor->setCursor(700);
@@ -2503,7 +2504,7 @@ void MystScriptParser_Myst::o_observatoryTimeSliderStartMove(uint16 op, uint16 v
observatoryUpdateTime();
}
-void MystScriptParser_Myst::o_observatoryTimeSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryTimeSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Time slider end move", op);
_vm->checkCursorHints();
@@ -2512,7 +2513,7 @@ void MystScriptParser_Myst::o_observatoryTimeSliderEndMove(uint16 op, uint16 var
observatoryUpdateTime();
}
-void MystScriptParser_Myst::observatoryUpdateTime() {
+void Myst::observatoryUpdateTime() {
int16 time = (_observatoryTimeSlider->_pos.y - 94) * 1439 / 94;
if (time != _state.observatoryTimeSetting) {
@@ -2532,12 +2533,12 @@ void MystScriptParser_Myst::observatoryUpdateTime() {
}
}
-void MystScriptParser_Myst::o_libraryCombinationBookStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryCombinationBookStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Combination book stop turning pages", op);
_libraryCombinationBookPagesTurning = false;
}
-void MystScriptParser_Myst::o_cabinMatchLight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_cabinMatchLight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
if (!_cabinMatchState) {
_vm->_sound->replaceSoundMyst(4103);
@@ -2552,7 +2553,7 @@ void MystScriptParser_Myst::o_cabinMatchLight(uint16 op, uint16 var, uint16 argc
}
}
-void MystScriptParser_Myst::matchBurn_run() {
+void Myst::matchBurn_run() {
uint32 time = _vm->_system->getMillis();
if (time > _matchGoOutTime) {
@@ -2576,41 +2577,41 @@ void MystScriptParser_Myst::matchBurn_run() {
}
}
-void MystScriptParser_Myst::o_courtyardBoxEnter(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_courtyardBoxEnter(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Mouse enters courtyard box", op);
_tempVar = 1;
_vm->_sound->playSound(_courtyardBoxSound);
_vm->redrawArea(var);
}
-void MystScriptParser_Myst::o_courtyardBoxLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_courtyardBoxLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Mouse leaves courtyard box", op);
_tempVar = 0;
_vm->redrawArea(var);
}
-void MystScriptParser_Myst::o_clockMinuteWheelStartTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockMinuteWheelStartTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Card 4006
debugC(kDebugScript, "Opcode %d: Minute wheel start turn", op);
clockWheelStartTurn(2);
}
-void MystScriptParser_Myst::o_clockWheelEndTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockWheelEndTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Card 4006
debugC(kDebugScript, "Opcode %d: Wheel end turn", op);
_clockTurningWheel = 0;
}
-void MystScriptParser_Myst::o_clockHourWheelStartTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockHourWheelStartTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Card 4006
debugC(kDebugScript, "Opcode %d: Hour wheel start turn", op);
clockWheelStartTurn(1);
}
-void MystScriptParser_Myst::clockWheel_run() {
+void Myst::clockWheel_run() {
// Turn wheel one step each second
uint32 time = _vm->_system->getMillis();
@@ -2626,7 +2627,7 @@ void MystScriptParser_Myst::clockWheel_run() {
}
}
-void MystScriptParser_Myst::clockWheelStartTurn(uint16 wheel) {
+void Myst::clockWheelStartTurn(uint16 wheel) {
MystResourceType11 *resource = static_cast<MystResourceType11 *>(_invokingResource);
uint16 soundId = resource->getList1(0);
@@ -2646,7 +2647,7 @@ void MystScriptParser_Myst::clockWheelStartTurn(uint16 wheel) {
_startTime = _vm->_system->getMillis();
}
-void MystScriptParser_Myst::clockWheelTurn(uint16 var) {
+void Myst::clockWheelTurn(uint16 var) {
if (var == 38) {
// Hours
_state.clockTowerHourPosition = (_state.clockTowerHourPosition + 1) % 12;
@@ -2656,7 +2657,7 @@ void MystScriptParser_Myst::clockWheelTurn(uint16 var) {
}
}
-void MystScriptParser_Myst::o_libraryCombinationBookStartRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryCombinationBookStartRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Combination book start turning pages right", op);
_tempVar = 0;
@@ -2665,7 +2666,7 @@ void MystScriptParser_Myst::o_libraryCombinationBookStartRight(uint16 op, uint16
_libraryCombinationBookPagesTurning = true;
}
-void MystScriptParser_Myst::o_libraryCombinationBookStartLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryCombinationBookStartLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Combination book start turning pages left", op);
_tempVar = 0;
@@ -2674,7 +2675,7 @@ void MystScriptParser_Myst::o_libraryCombinationBookStartLeft(uint16 op, uint16
_libraryCombinationBookPagesTurning = true;
}
-void MystScriptParser_Myst::libraryCombinationBookTurnLeft() {
+void Myst::libraryCombinationBookTurnLeft() {
// Turn page left
if (_libraryBookPage - 1 >= 0) {
_tempVar--;
@@ -2700,7 +2701,7 @@ void MystScriptParser_Myst::libraryCombinationBookTurnLeft() {
}
}
-void MystScriptParser_Myst::libraryCombinationBookTurnRight() {
+void Myst::libraryCombinationBookTurnRight() {
// Turn page right
if (_libraryBookPage + 1 < _libraryBookNumPages) {
_tempVar++;
@@ -2726,7 +2727,7 @@ void MystScriptParser_Myst::libraryCombinationBookTurnRight() {
}
}
-void MystScriptParser_Myst::libraryCombinationBook_run() {
+void Myst::libraryCombinationBook_run() {
uint32 time = _vm->_system->getMillis();
if (time >= _startTime + 500) {
if (_tempVar > 0) {
@@ -2739,7 +2740,7 @@ void MystScriptParser_Myst::libraryCombinationBook_run() {
}
}
-void MystScriptParser_Myst::o_observatoryChangeSettingStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatoryChangeSettingStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Observatory change setting stop", op);
// Stop persistent scripts
@@ -2758,7 +2759,7 @@ void MystScriptParser_Myst::o_observatoryChangeSettingStop(uint16 op, uint16 var
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Myst::o_dockVaultForceClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_dockVaultForceClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Myst 4143 (Dock near Marker Switch)
uint16 soundId = argv[0];
uint16 delay = argv[1];
@@ -2782,12 +2783,12 @@ void MystScriptParser_Myst::o_dockVaultForceClose(uint16 op, uint16 var, uint16
}
}
-void MystScriptParser_Myst::o_imagerEraseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_imagerEraseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Imager stop erase", op);
_imagerValidationRunning = false;
}
-void MystScriptParser_Myst::o_clockLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock lever start move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
lever->drawFrame(0);
@@ -2796,7 +2797,7 @@ void MystScriptParser_Myst::o_clockLeverStartMove(uint16 op, uint16 var, uint16
_clockLeverPulled = false;
}
-void MystScriptParser_Myst::o_clockLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock left lever move", op);
if (!_clockLeverPulled) {
@@ -2822,7 +2823,7 @@ void MystScriptParser_Myst::o_clockLeverMove(uint16 op, uint16 var, uint16 argc,
}
}
-void MystScriptParser_Myst::clockGearForwardOneStep(uint16 gear) {
+void Myst::clockGearForwardOneStep(uint16 gear) {
static const uint16 startTime[] = { 0, 324, 618 };
static const uint16 endTime[] = { 324, 618, 950 };
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3" };
@@ -2840,7 +2841,7 @@ void MystScriptParser_Myst::clockGearForwardOneStep(uint16 gear) {
Audio::Timestamp(0, endTime[gearPosition], 600));
}
-void MystScriptParser_Myst::clockWeightDownOneStep() {
+void Myst::clockWeightDownOneStep() {
// Set video bounds
_clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
_vm->_video->setVideoBounds(_clockWeightVideo,
@@ -2851,7 +2852,7 @@ void MystScriptParser_Myst::clockWeightDownOneStep() {
_clockWeightPosition += 246;
}
-void MystScriptParser_Myst::clockGears_run() {
+void Myst::clockGears_run() {
if (!_vm->_video->isVideoPlaying() && _clockWeightPosition < 2214) {
_clockMiddleGearMovedAlone = true;
_vm->_sound->replaceSoundMyst(5113);
@@ -2860,7 +2861,7 @@ void MystScriptParser_Myst::clockGears_run() {
}
}
-void MystScriptParser_Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock lever end move", op);
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3", "cl1wlfch" };
@@ -2887,7 +2888,7 @@ void MystScriptParser_Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 ar
_vm->_cursor->showCursor();
}
-void MystScriptParser_Myst::clockGearsCheckSolution() {
+void Myst::clockGearsCheckSolution() {
if (_clockGearsPositions[0] == 2
&& _clockGearsPositions[1] == 2
&& _clockGearsPositions[2] == 1
@@ -2915,7 +2916,7 @@ void MystScriptParser_Myst::clockGearsCheckSolution() {
}
}
-void MystScriptParser_Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock reset lever start move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -2923,7 +2924,7 @@ void MystScriptParser_Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, ui
_vm->_cursor->setCursor(700);
}
-void MystScriptParser_Myst::o_clockResetLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockResetLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock reset lever move", op);
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
@@ -2933,7 +2934,7 @@ void MystScriptParser_Myst::o_clockResetLeverMove(uint16 op, uint16 var, uint16
clockReset();
}
-void MystScriptParser_Myst::clockReset() {
+void Myst::clockReset() {
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3", "cl1wlfch" };
_vm->_cursor->hideCursor();
@@ -2971,7 +2972,7 @@ void MystScriptParser_Myst::clockReset() {
_vm->_cursor->showCursor();
}
-void MystScriptParser_Myst::clockResetWeight() {
+void Myst::clockResetWeight() {
// Set video bounds, weight going up
if (!(_vm->getFeatures() & GF_ME)) {
_clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
@@ -2987,7 +2988,7 @@ void MystScriptParser_Myst::clockResetWeight() {
_clockWeightPosition = 0;
}
-void MystScriptParser_Myst::clockResetGear(uint16 gear) {
+void Myst::clockResetGear(uint16 gear) {
static const uint16 time[] = { 324, 618, 950 };
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3" };
static const uint16 x[] = { 224, 224, 224 };
@@ -3006,7 +3007,7 @@ void MystScriptParser_Myst::clockResetGear(uint16 gear) {
_clockGearsPositions[gear] = 3;
}
-void MystScriptParser_Myst::o_clockResetLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockResetLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock reset lever end move", op);
// Get current lever frame
@@ -3017,7 +3018,7 @@ void MystScriptParser_Myst::o_clockResetLeverEndMove(uint16 op, uint16 var, uint
_vm->checkCursorHints();
}
-void MystScriptParser_Myst::o_libraryBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_libraryBookPage = 0;
_libraryBookNumPages = argv[0];
_libraryBookBaseImage = argv[1];
@@ -3025,13 +3026,13 @@ void MystScriptParser_Myst::o_libraryBook_init(uint16 op, uint16 var, uint16 arg
_libraryBookSound2 = argv[3];
}
-void MystScriptParser_Myst::o_courtyardBox_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_courtyardBox_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Courtyard box init", op);
_courtyardBoxSound = argv[0];
}
-void MystScriptParser_Myst::towerRotationMap_run() {
+void Myst::towerRotationMap_run() {
if (!_towerRotationMapInitialized) {
_towerRotationMapInitialized = true;
_vm->_sound->replaceSoundMyst(4378);
@@ -3072,7 +3073,7 @@ void MystScriptParser_Myst::towerRotationMap_run() {
}
}
-void MystScriptParser_Myst::o_towerRotationMap_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_towerRotationMap_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_towerRotationMapRunning = true;
_towerRotationMapTower = static_cast<MystResourceType11 *>(_invokingResource);
_towerRotationMapLabel = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
@@ -3081,7 +3082,7 @@ void MystScriptParser_Myst::o_towerRotationMap_init(uint16 op, uint16 var, uint1
_towerRotationMapClicked = false;
}
-void MystScriptParser_Myst::towerRotationDrawBuildings() {
+void Myst::towerRotationDrawBuildings() {
// Draw library
_vm->redrawArea(304, false);
@@ -3092,7 +3093,7 @@ void MystScriptParser_Myst::towerRotationDrawBuildings() {
}
}
-uint16 MystScriptParser_Myst::towerRotationMapComputeAngle() {
+uint16 Myst::towerRotationMapComputeAngle() {
_towerRotationSpeed++;
if (_towerRotationSpeed >= 7)
_towerRotationSpeed = 7;
@@ -3128,18 +3129,18 @@ uint16 MystScriptParser_Myst::towerRotationMapComputeAngle() {
return angle;
}
-Common::Point MystScriptParser_Myst::towerRotationMapComputeCoords(const Common::Point &center, uint16 angle) {
+Common::Point Myst::towerRotationMapComputeCoords(const Common::Point &center, uint16 angle) {
Common::Point end;
// Polar to rect coords
- double radians = angle * PI / 180.0;
+ double radians = angle * M_PI / 180.0;
end.x = (int16)(center.x + cos(radians) * 310.0);
end.y = (int16)(center.y + sin(radians) * 310.0);
return end;
}
-void MystScriptParser_Myst::towerRotationMapDrawLine(const Common::Point &center, const Common::Point &end) {
+void Myst::towerRotationMapDrawLine(const Common::Point &center, const Common::Point &end) {
Graphics::PixelFormat pf = _vm->_system->getScreenFormat();
uint32 color = 0;
@@ -3174,27 +3175,27 @@ void MystScriptParser_Myst::towerRotationMapDrawLine(const Common::Point &center
_vm->_system->updateScreen();
}
-void MystScriptParser_Myst::towerRotationMapRotate() {
+void Myst::towerRotationMapRotate() {
const Common::Point center = Common::Point(383, 124);
uint16 angle = towerRotationMapComputeAngle();
Common::Point end = towerRotationMapComputeCoords(center, angle);
towerRotationMapDrawLine(center, end);
}
-void MystScriptParser_Myst::o_forechamberDoor_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_forechamberDoor_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 4138 (Dock Forechamber Door)
// Set forechamber door to closed
_tempVar = 0;
}
-void MystScriptParser_Myst::o_shipAccess_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_shipAccess_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Enable acces to the ship
if (_state.shipFloating) {
_invokingResource->setEnabled(true);
}
}
-void MystScriptParser_Myst::o_butterflies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_butterflies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Butterflies movie init", op);
// Used for Card 4256 (Butterfly Movie Activation)
@@ -3206,7 +3207,7 @@ void MystScriptParser_Myst::o_butterflies_init(uint16 op, uint16 var, uint16 arg
}
}
-void MystScriptParser_Myst::o_imager_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_imager_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Imager init", op);
debugC(kDebugScript, "Var: %d", var);
@@ -3215,7 +3216,7 @@ void MystScriptParser_Myst::o_imager_init(uint16 op, uint16 var, uint16 argc, ui
_imagerRunning = true;
}
-void MystScriptParser_Myst::imager_run() {
+void Myst::imager_run() {
_imagerRunning = false;
if (_state.imagerActive && _state.imagerSelection == 67) {
@@ -3225,7 +3226,7 @@ void MystScriptParser_Myst::imager_run() {
}
}
-void MystScriptParser_Myst::libraryBookcaseTransform_run(void) {
+void Myst::libraryBookcaseTransform_run(void) {
if (_libraryBookcaseChanged) {
_libraryBookcaseChanged = false;
_libraryBookcaseMoving = false;
@@ -3252,7 +3253,7 @@ void MystScriptParser_Myst::libraryBookcaseTransform_run(void) {
}
}
-void MystScriptParser_Myst::o_libraryBookcaseTransform_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_libraryBookcaseTransform_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
if (_libraryBookcaseChanged) {
MystResourceType7 *resource = static_cast<MystResourceType7 *>(_invokingResource);
_libraryBookcaseMovie = static_cast<MystResourceType6 *>(resource->getSubResource(getVar(0)));
@@ -3261,7 +3262,7 @@ void MystScriptParser_Myst::o_libraryBookcaseTransform_init(uint16 op, uint16 va
}
}
-void MystScriptParser_Myst::generatorControlRoom_run(void) {
+void Myst::generatorControlRoom_run(void) {
if (_generatorVoltage == _state.generatorVoltage) {
generatorRedrawRocket();
} else {
@@ -3278,14 +3279,14 @@ void MystScriptParser_Myst::generatorControlRoom_run(void) {
}
}
-void MystScriptParser_Myst::o_generatorControlRoom_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_generatorControlRoom_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator control room init", op);
_generatorVoltage = _state.generatorVoltage;
_generatorControlRoomRunning = true;
}
-void MystScriptParser_Myst::o_fireplace_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_fireplace_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Fireplace grid init", op);
// Clear fireplace grid
@@ -3293,7 +3294,7 @@ void MystScriptParser_Myst::o_fireplace_init(uint16 op, uint16 var, uint16 argc,
_fireplaceLines[i] = 0;
}
-void MystScriptParser_Myst::o_clockGears_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_clockGears_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 4113 (Clock Tower Cog Puzzle)
debugC(kDebugScript, "Opcode %d: Gears puzzle init", op);
@@ -3311,7 +3312,7 @@ void MystScriptParser_Myst::o_clockGears_init(uint16 op, uint16 var, uint16 argc
}
}
-void MystScriptParser_Myst::o_gulls1_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_gulls1_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Gulls init", op);
if (!_state.shipFloating) {
@@ -3320,7 +3321,7 @@ void MystScriptParser_Myst::o_gulls1_init(uint16 op, uint16 var, uint16 argc, ui
}
}
-void MystScriptParser_Myst::gullsFly1_run() {
+void Myst::gullsFly1_run() {
static const char* gulls[] = { "birds1", "birds2", "birds3" };
uint32 time = _vm->_system->getMillis();
@@ -3340,7 +3341,7 @@ void MystScriptParser_Myst::gullsFly1_run() {
}
}
-void MystScriptParser_Myst::o_observatory_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_observatory_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Stellar observatory init", op);
_tempVar = 0;
@@ -3370,13 +3371,13 @@ void MystScriptParser_Myst::o_observatory_init(uint16 op, uint16 var, uint16 arg
_observatoryRunning = true;
}
-bool MystScriptParser_Myst::observatoryIsDDMMYYYY2400() {
+bool Myst::observatoryIsDDMMYYYY2400() {
// TODO: Auto-detect based on the month rect position
return !(_vm->getFeatures() & GF_ME) && (_vm->getLanguage() == Common::FR_FRA
|| _vm->getLanguage() == Common::DE_DEU);
}
-void MystScriptParser_Myst::observatoryUpdateVisualizer(uint16 x, uint16 y) {
+void Myst::observatoryUpdateVisualizer(uint16 x, uint16 y) {
Common::Rect &visu0 = _observatoryVisualizer->_subImages[0].rect;
Common::Rect &visu1 = _observatoryVisualizer->_subImages[1].rect;
@@ -3391,7 +3392,7 @@ void MystScriptParser_Myst::observatoryUpdateVisualizer(uint16 x, uint16 y) {
visu1.bottom = visu0.bottom;
}
-void MystScriptParser_Myst::observatorySetTargetToSetting() {
+void Myst::observatorySetTargetToSetting() {
uint32 visuX = _state.observatoryTimeSetting * 7 / 25;
uint32 visuY = 250 * _state.observatoryYearSetting
+ 65 * (_state.observatoryMonthSetting + 1)
@@ -3405,7 +3406,7 @@ void MystScriptParser_Myst::observatorySetTargetToSetting() {
_state.observatoryTimeTarget = _state.observatoryTimeSetting;
}
-void MystScriptParser_Myst::observatory_run() {
+void Myst::observatory_run() {
if (_observatoryNotInitialized) {
_observatoryNotInitialized = false;
@@ -3463,7 +3464,7 @@ void MystScriptParser_Myst::observatory_run() {
}
}
-void MystScriptParser_Myst::o_gulls2_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_gulls2_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Gulls init", op);
if (!_state.shipFloating) {
@@ -3472,7 +3473,7 @@ void MystScriptParser_Myst::o_gulls2_init(uint16 op, uint16 var, uint16 argc, ui
}
}
-void MystScriptParser_Myst::gullsFly2_run() {
+void Myst::gullsFly2_run() {
static const char* gulls[] = { "birds1", "birds2", "birds3" };
uint32 time = _vm->_system->getMillis();
@@ -3486,13 +3487,13 @@ void MystScriptParser_Myst::gullsFly2_run() {
}
}
-void MystScriptParser_Myst::o_treeCard_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_treeCard_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Enter tree card", op);
_tree = static_cast<MystResourceType8 *>(_invokingResource);
}
-void MystScriptParser_Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Enter tree card with entry", op);
_treeAlcove = static_cast<MystResourceType5 *>(_invokingResource);
@@ -3502,7 +3503,7 @@ void MystScriptParser_Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc,
treeSetAlcoveAccessible();
}
-void MystScriptParser_Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used for Card 4097 (Cabin Boiler)
@@ -3520,7 +3521,7 @@ void MystScriptParser_Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint1
}
}
-void MystScriptParser_Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket sliders init", op);
_rocketSlider1 = static_cast<MystResourceType10 *>(_vm->_resources[argv[0]]);
@@ -3541,12 +3542,12 @@ void MystScriptParser_Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 a
_rocketSlider5->setPosition(_state.rocketSliderPosition[4]);
}
-void MystScriptParser_Myst::o_rocketLinkVideo_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_rocketLinkVideo_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket link video init", op);
_tempVar = 0;
}
-void MystScriptParser_Myst::o_greenBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_greenBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 4168 (Green Book Movies)
debugC(kDebugScript, "Opcode %d: Green book init", op);
@@ -3554,7 +3555,7 @@ void MystScriptParser_Myst::o_greenBook_init(uint16 op, uint16 var, uint16 argc,
_tempVar = 1;
}
-void MystScriptParser_Myst::greenBook_run() {
+void Myst::greenBook_run() {
uint loopStart = 0;
uint loopEnd = 0;
Common::String file;
@@ -3589,7 +3590,7 @@ void MystScriptParser_Myst::greenBook_run() {
}
}
-void MystScriptParser_Myst::o_gulls3_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_gulls3_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Gulls init", op);
if (!_state.shipFloating) {
@@ -3598,7 +3599,7 @@ void MystScriptParser_Myst::o_gulls3_init(uint16 op, uint16 var, uint16 argc, ui
}
}
-void MystScriptParser_Myst::gullsFly3_run() {
+void Myst::gullsFly3_run() {
static const char* gulls[] = { "birds1", "birds2", "birds3" };
uint32 time = _vm->_system->getMillis();
@@ -3614,7 +3615,7 @@ void MystScriptParser_Myst::gullsFly3_run() {
}
}
-void MystScriptParser_Myst::o_bookAddSpecialPage_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_bookAddSpecialPage_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Book Exit Function", op);
uint16 numPages = bookCountPages(var);
@@ -3628,22 +3629,23 @@ void MystScriptParser_Myst::o_bookAddSpecialPage_exit(uint16 op, uint16 var, uin
}
}
-void MystScriptParser_Myst::o_treeCard_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_treeCard_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Exit tree card", op);
_tree = 0;
}
-void MystScriptParser_Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Exit tree card with entry", op);
_treeAlcove = 0;
}
-void MystScriptParser_Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator room exit", op);
_generatorVoltage = _state.generatorVoltage;
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
index e41527a5b8..51dffd0abe 100644
--- a/engines/mohawk/myst_stacks/myst.h
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Myst : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Myst : public MystScriptParser {
public:
- MystScriptParser_Myst(MohawkEngine_Myst *vm);
- ~MystScriptParser_Myst();
+ Myst(MohawkEngine_Myst *vm);
+ ~Myst();
void disablePersistentScripts();
void runPersistentScripts();
@@ -333,6 +334,7 @@ private:
void observatoryUpdateTime();
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index bbf324714b..dc491c7573 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -33,25 +33,26 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Preview::MystScriptParser_Preview(MohawkEngine_Myst *vm) : MystScriptParser_Myst(vm) {
+Preview::Preview(MohawkEngine_Myst *vm) : Myst(vm) {
setupOpcodes();
}
-MystScriptParser_Preview::~MystScriptParser_Preview() {
+Preview::~Preview() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Preview::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Preview::x, #x))
#define OVERRIDE_OPCODE(opcode, x) \
for (uint32 i = 0; i < _opcodes.size(); i++) \
if (_opcodes[i]->op == opcode) { \
- _opcodes[i]->proc = (OpcodeProcMyst) &MystScriptParser_Preview::x; \
+ _opcodes[i]->proc = (OpcodeProcMyst) &Preview::x; \
_opcodes[i]->desc = #x; \
break; \
}
-void MystScriptParser_Preview::setupOpcodes() {
+void Preview::setupOpcodes() {
// "Stack-Specific" Opcodes
OVERRIDE_OPCODE(196, opcode_196);
OVERRIDE_OPCODE(197, opcode_197);
@@ -66,7 +67,7 @@ void MystScriptParser_Preview::setupOpcodes() {
#undef OPCODE
#undef OVERRIDE_OPCODE
-void MystScriptParser_Preview::opcode_196(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Preview::opcode_196(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used on Card ...
@@ -74,7 +75,7 @@ void MystScriptParser_Preview::opcode_196(uint16 op, uint16 var, uint16 argc, ui
// Voice Over and Card Advance?
}
-void MystScriptParser_Preview::opcode_197(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Preview::opcode_197(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used on Card ...
@@ -83,7 +84,7 @@ void MystScriptParser_Preview::opcode_197(uint16 op, uint16 var, uint16 argc, ui
}
// TODO: Merge with Opcode 42?
-void MystScriptParser_Preview::opcode_198(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Preview::opcode_198(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
if (argc == 0) {
@@ -94,7 +95,7 @@ void MystScriptParser_Preview::opcode_198(uint16 op, uint16 var, uint16 argc, ui
unknown(op, var, argc, argv);
}
-void MystScriptParser_Preview::opcode_199(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Preview::opcode_199(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used on Card ...
@@ -102,7 +103,7 @@ void MystScriptParser_Preview::opcode_199(uint16 op, uint16 var, uint16 argc, ui
// Voice Over and Card Advance?
}
-void MystScriptParser_Preview::opcode_298(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Preview::opcode_298(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used for Card 3000 (Closed Myst Book)
@@ -125,7 +126,7 @@ void MystScriptParser_Preview::opcode_298(uint16 op, uint16 var, uint16 argc, ui
}
}
-void MystScriptParser_Preview::opcode_299(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Preview::opcode_299(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
varUnusedCheck(op, var);
// Used for Card 3002 (Myst Island Overview)
@@ -135,4 +136,5 @@ void MystScriptParser_Preview::opcode_299(uint16 op, uint16 var, uint16 argc, ui
// can change the Myst Library to Red..
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/preview.h b/engines/mohawk/myst_stacks/preview.h
index 25f0ab514f..870e4b9272 100644
--- a/engines/mohawk/myst_stacks/preview.h
+++ b/engines/mohawk/myst_stacks/preview.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Preview : public MystScriptParser_Myst {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Preview : public Myst {
public:
- MystScriptParser_Preview(MohawkEngine_Myst *vm);
- ~MystScriptParser_Preview();
+ Preview(MohawkEngine_Myst *vm);
+ ~Preview();
private:
void setupOpcodes();
@@ -54,6 +55,7 @@ private:
DECLARE_OPCODE(opcode_299);
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index 3e00d242be..f485bab2f9 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -35,8 +35,9 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Selenitic::MystScriptParser_Selenitic(MohawkEngine_Myst *vm) :
+Selenitic::Selenitic(MohawkEngine_Myst *vm) :
MystScriptParser(vm), _state(vm->_gameState->_selenitic) {
setupOpcodes();
_invokingResource = NULL;
@@ -44,12 +45,12 @@ MystScriptParser_Selenitic::MystScriptParser_Selenitic(MohawkEngine_Myst *vm) :
_mazeRunnerDirection = 8;
}
-MystScriptParser_Selenitic::~MystScriptParser_Selenitic() {
+Selenitic::~Selenitic() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Selenitic::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Selenitic::x, #x))
-void MystScriptParser_Selenitic::setupOpcodes() {
+void Selenitic::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_mazeRunnerMove);
OPCODE(101, o_mazeRunnerSoundRepeat);
@@ -82,16 +83,16 @@ void MystScriptParser_Selenitic::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Selenitic::disablePersistentScripts() {
+void Selenitic::disablePersistentScripts() {
_soundReceiverRunning = false;
}
-void MystScriptParser_Selenitic::runPersistentScripts() {
+void Selenitic::runPersistentScripts() {
if (_soundReceiverRunning)
soundReceiver_run();
}
-uint16 MystScriptParser_Selenitic::getVar(uint16 var) {
+uint16 Selenitic::getVar(uint16 var) {
switch(var) {
case 0: // Sound receiver emitters enabled
return _state.emitterEnabledWind;
@@ -166,7 +167,7 @@ uint16 MystScriptParser_Selenitic::getVar(uint16 var) {
}
}
-void MystScriptParser_Selenitic::toggleVar(uint16 var) {
+void Selenitic::toggleVar(uint16 var) {
switch(var) {
case 0: // Sound receiver emitters enabled
_state.emitterEnabledWind = (_state.emitterEnabledWind + 1) % 2;
@@ -211,7 +212,7 @@ void MystScriptParser_Selenitic::toggleVar(uint16 var) {
}
}
-bool MystScriptParser_Selenitic::setVarValue(uint16 var, uint16 value) {
+bool Selenitic::setVarValue(uint16 var, uint16 value) {
bool refresh = false;
switch (var) {
@@ -283,7 +284,7 @@ bool MystScriptParser_Selenitic::setVarValue(uint16 var, uint16 value) {
return refresh;
}
-void MystScriptParser_Selenitic::o_mazeRunnerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
uint16 oldPosition = _mazeRunnerPosition;
uint16 move = var;
@@ -304,7 +305,7 @@ void MystScriptParser_Selenitic::o_mazeRunnerMove(uint16 op, uint16 var, uint16
}
}
-void MystScriptParser_Selenitic::mazeRunnerBacktrack(uint16 &oldPosition) {
+void Selenitic::mazeRunnerBacktrack(uint16 &oldPosition) {
if (oldPosition == 289)
_mazeRunnerDirection = 3;
@@ -365,7 +366,7 @@ void MystScriptParser_Selenitic::mazeRunnerBacktrack(uint16 &oldPosition) {
}
}
-void MystScriptParser_Selenitic::mazeRunnerPlayVideo(uint16 video, uint16 pos) {
+void Selenitic::mazeRunnerPlayVideo(uint16 video, uint16 pos) {
Common::String file;
switch (video) {
@@ -486,7 +487,7 @@ void MystScriptParser_Selenitic::mazeRunnerPlayVideo(uint16 video, uint16 pos) {
}
}
-void MystScriptParser_Selenitic::mazeRunnerUpdateCompass() {
+void Selenitic::mazeRunnerUpdateCompass() {
if (_mazeRunnerPosition == 288 || _mazeRunnerPosition == 289)
_mazeRunnerDirection = 8;
else
@@ -495,12 +496,12 @@ void MystScriptParser_Selenitic::mazeRunnerUpdateCompass() {
_mazeRunnerCompass->drawConditionalDataToScreen(_mazeRunnerDirection);
}
-bool MystScriptParser_Selenitic::mazeRunnerForwardAllowed(uint16 position) {
+bool Selenitic::mazeRunnerForwardAllowed(uint16 position) {
uint16 move = _mazeRunnerVideos[position][1];
return move == 6 || move == 7;
}
-void MystScriptParser_Selenitic::mazeRunnerPlaySoundHelp() {
+void Selenitic::mazeRunnerPlaySoundHelp() {
uint16 soundId = 0;
_mazeRunnerLight->drawConditionalDataToScreen(1);
@@ -564,14 +565,14 @@ void MystScriptParser_Selenitic::mazeRunnerPlaySoundHelp() {
_mazeRunnerLight->drawConditionalDataToScreen(0);
}
-void MystScriptParser_Selenitic::o_mazeRunnerSoundRepeat(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerSoundRepeat(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
mazeRunnerPlaySoundHelp();
}
/**
* Sound receiver sigma button
*/
-void MystScriptParser_Selenitic::o_soundReceiverSigma(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiverSigma(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver sigma button", op);
_vm->_cursor->hideCursor();
@@ -623,7 +624,7 @@ void MystScriptParser_Selenitic::o_soundReceiverSigma(uint16 op, uint16 var, uin
/**
* Sound receiver right button
*/
-void MystScriptParser_Selenitic::o_soundReceiverRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiverRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver right", op);
soundReceiverLeftRight(1);
@@ -632,13 +633,13 @@ void MystScriptParser_Selenitic::o_soundReceiverRight(uint16 op, uint16 var, uin
/**
* Sound receiver left button
*/
-void MystScriptParser_Selenitic::o_soundReceiverLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiverLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver left", op);
soundReceiverLeftRight(2);
}
-void MystScriptParser_Selenitic::soundReceiverLeftRight(uint direction) {
+void Selenitic::soundReceiverLeftRight(uint direction) {
if (_soundReceiverSigmaPressed) {
_soundReceiverSigmaButton->drawConditionalDataToScreen(0);
@@ -659,7 +660,7 @@ void MystScriptParser_Selenitic::soundReceiverLeftRight(uint direction) {
soundReceiverUpdate();
}
-void MystScriptParser_Selenitic::soundReceiverUpdate() {
+void Selenitic::soundReceiverUpdate() {
if (_soundReceiverDirection == 1)
*_soundReceiverPosition = ((*_soundReceiverPosition) + _soundReceiverSpeed) % 3600;
else if (_soundReceiverDirection == 2)
@@ -668,7 +669,7 @@ void MystScriptParser_Selenitic::soundReceiverUpdate() {
soundReceiverDrawView();
}
-void MystScriptParser_Selenitic::soundReceiverDrawView() {
+void Selenitic::soundReceiverDrawView() {
uint32 left = ((*_soundReceiverPosition) * 1800) / 3600;
_soundReceiverViewer->_subImages->rect.left = left;
@@ -679,7 +680,7 @@ void MystScriptParser_Selenitic::soundReceiverDrawView() {
soundReceiverDrawAngle();
}
-void MystScriptParser_Selenitic::soundReceiverDrawAngle() {
+void Selenitic::soundReceiverDrawAngle() {
_vm->redrawResource(_soundReceiverAngle1);
_vm->redrawResource(_soundReceiverAngle2);
_vm->redrawResource(_soundReceiverAngle3);
@@ -689,7 +690,7 @@ void MystScriptParser_Selenitic::soundReceiverDrawAngle() {
/**
* Sound receiver source selection buttons
*/
-void MystScriptParser_Selenitic::o_soundReceiverSource(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiverSource(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver source", op);
if (_soundReceiverSigmaPressed) {
@@ -723,7 +724,7 @@ void MystScriptParser_Selenitic::o_soundReceiverSource(uint16 op, uint16 var, ui
_vm->_cursor->showCursor();
}
-void MystScriptParser_Selenitic::o_mazeRunnerDoorButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerDoorButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Selenitic Maze Runner Exit Logic
uint16 cardIdExit = argv[0];
uint16 cardIdEntry = argv[1];
@@ -739,13 +740,13 @@ void MystScriptParser_Selenitic::o_mazeRunnerDoorButton(uint16 op, uint16 var, u
}
}
-void MystScriptParser_Selenitic::o_soundReceiverUpdateSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiverUpdateSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver update sound", op);
soundReceiverUpdateSound();
}
-uint16 MystScriptParser_Selenitic::soundLockCurrentSound(uint16 position, bool pixels) {
+uint16 Selenitic::soundLockCurrentSound(uint16 position, bool pixels) {
if ((pixels && position < 96) || (!pixels && position == 0))
return 289;
else if ((pixels && position < 108) || (!pixels && position == 1))
@@ -770,7 +771,7 @@ uint16 MystScriptParser_Selenitic::soundLockCurrentSound(uint16 position, bool p
return 0;
}
-MystResourceType10 *MystScriptParser_Selenitic::soundLockSliderFromVar(uint16 var) {
+MystResourceType10 *Selenitic::soundLockSliderFromVar(uint16 var) {
switch (var) {
case 20:
return _soundLockSlider1;
@@ -787,7 +788,7 @@ MystResourceType10 *MystScriptParser_Selenitic::soundLockSliderFromVar(uint16 va
return 0;
}
-void MystScriptParser_Selenitic::o_soundLockMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundLockMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock move", op);
MystResourceType10 *slider = soundLockSliderFromVar(var);
@@ -799,7 +800,7 @@ void MystScriptParser_Selenitic::o_soundLockMove(uint16 op, uint16 var, uint16 a
}
}
-void MystScriptParser_Selenitic::o_soundLockStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundLockStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock start move", op);
MystResourceType10 *slider = soundLockSliderFromVar(var);
@@ -811,7 +812,7 @@ void MystScriptParser_Selenitic::o_soundLockStartMove(uint16 op, uint16 var, uin
_vm->_sound->replaceSoundMyst(_soundLockSoundId, Audio::Mixer::kMaxChannelVolume, true);
}
-void MystScriptParser_Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock end move", op);
MystResourceType10 *slider = soundLockSliderFromVar(var);
@@ -855,7 +856,7 @@ void MystScriptParser_Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint1
_vm->_sound->resumeBackgroundMyst();
}
-void MystScriptParser_Selenitic::soundLockCheckSolution(MystResourceType10 *slider, uint16 value, uint16 solution, bool &solved) {
+void Selenitic::soundLockCheckSolution(MystResourceType10 *slider, uint16 value, uint16 solution, bool &solved) {
slider->drawConditionalDataToScreen(2);
_vm->_sound->replaceSoundMyst(soundLockCurrentSound(value / 12, false));
_vm->_system->delayMillis(1500);
@@ -867,7 +868,7 @@ void MystScriptParser_Selenitic::soundLockCheckSolution(MystResourceType10 *slid
_vm->_sound->stopSound();
}
-void MystScriptParser_Selenitic::o_soundLockButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundLockButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock button", op);
bool solved = true;
@@ -905,7 +906,7 @@ void MystScriptParser_Selenitic::o_soundLockButton(uint16 op, uint16 var, uint16
_vm->_cursor->showCursor();
}
-void MystScriptParser_Selenitic::o_soundReceiverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver end move", op);
uint16 oldDirection = _soundReceiverDirection;
@@ -922,19 +923,19 @@ void MystScriptParser_Selenitic::o_soundReceiverEndMove(uint16 op, uint16 var, u
}
}
-void MystScriptParser_Selenitic::o_mazeRunnerCompass_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerCompass_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_mazeRunnerCompass = static_cast<MystResourceType8 *>(_invokingResource);
}
-void MystScriptParser_Selenitic::o_mazeRunnerWindow_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerWindow_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_mazeRunnerWindow = static_cast<MystResourceType8 *>(_invokingResource);
}
-void MystScriptParser_Selenitic::o_mazeRunnerLight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerLight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_mazeRunnerLight = static_cast<MystResourceType8 *>(_invokingResource);
}
-void MystScriptParser_Selenitic::soundReceiver_run() {
+void Selenitic::soundReceiver_run() {
if (_soundReceiverStartTime) {
if (_soundReceiverDirection) {
uint32 currentTime = _vm->_system->getMillis();
@@ -952,7 +953,7 @@ void MystScriptParser_Selenitic::soundReceiver_run() {
}
}
-void MystScriptParser_Selenitic::soundReceiverIncreaseSpeed() {
+void Selenitic::soundReceiverIncreaseSpeed() {
switch (_soundReceiverSpeed) {
case 1:
_soundReceiverSpeed = 10;
@@ -966,12 +967,12 @@ void MystScriptParser_Selenitic::soundReceiverIncreaseSpeed() {
}
}
-void MystScriptParser_Selenitic::soundReceiverUpdateSound() {
+void Selenitic::soundReceiverUpdateSound() {
uint16 soundId = soundReceiverCurrentSound(_state.soundReceiverCurrentSource, *_soundReceiverPosition);
_vm->_sound->replaceSoundMyst(soundId);
}
-uint16 MystScriptParser_Selenitic::soundReceiverCurrentSound(uint16 source, uint16 position) {
+uint16 Selenitic::soundReceiverCurrentSound(uint16 source, uint16 position) {
uint16 solution = 0;
bool sourceEnabled = false;
soundReceiverSolution(source, solution, sourceEnabled);
@@ -1022,7 +1023,7 @@ uint16 MystScriptParser_Selenitic::soundReceiverCurrentSound(uint16 source, uint
return soundId;
}
-void MystScriptParser_Selenitic::soundReceiverSolution(uint16 source, uint16 &solution, bool &enabled) {
+void Selenitic::soundReceiverSolution(uint16 source, uint16 &solution, bool &enabled) {
switch (source) {
case 0:
enabled = _state.emitterEnabledWater;
@@ -1047,7 +1048,7 @@ void MystScriptParser_Selenitic::soundReceiverSolution(uint16 source, uint16 &so
}
}
-void MystScriptParser_Selenitic::o_soundReceiver_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundReceiver_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound receiver init", op);
// Used for Card 1245 (Sound Receiver)
@@ -1074,7 +1075,7 @@ void MystScriptParser_Selenitic::o_soundReceiver_init(uint16 op, uint16 var, uin
_soundReceiverSigmaPressed = false;
}
-void MystScriptParser_Selenitic::o_soundLock_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_soundLock_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock init", op);
for (uint i = 0; i < _vm->_resources.size(); i++) {
@@ -1109,15 +1110,15 @@ void MystScriptParser_Selenitic::o_soundLock_init(uint16 op, uint16 var, uint16
_soundLockSoundId = 0;
}
-void MystScriptParser_Selenitic::o_mazeRunnerRight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerRight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_mazeRunnerRightButton = static_cast<MystResourceType8 *>(_invokingResource);
}
-void MystScriptParser_Selenitic::o_mazeRunnerLeft_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Selenitic::o_mazeRunnerLeft_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_mazeRunnerLeftButton = static_cast<MystResourceType8 *>(_invokingResource);
}
-const uint16 MystScriptParser_Selenitic::_mazeRunnerMap[300][4] = {
+const uint16 Selenitic::_mazeRunnerMap[300][4] = {
{8, 7, 1, 288},
{1, 0, 2, 288},
{2, 1, 3, 288},
@@ -1420,7 +1421,7 @@ const uint16 MystScriptParser_Selenitic::_mazeRunnerMap[300][4] = {
{ 0, 0, 0, 0}
};
-const uint8 MystScriptParser_Selenitic::_mazeRunnerVideos[300][4] = {
+const uint8 Selenitic::_mazeRunnerVideos[300][4] = {
{3, 6, 10, 17},
{0, 5, 8, 17},
{0, 4, 8, 17},
@@ -1723,4 +1724,5 @@ const uint8 MystScriptParser_Selenitic::_mazeRunnerVideos[300][4] = {
{0, 0, 0, 0}
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/selenitic.h b/engines/mohawk/myst_stacks/selenitic.h
index 54e9db4d66..4ec92b9869 100644
--- a/engines/mohawk/myst_stacks/selenitic.h
+++ b/engines/mohawk/myst_stacks/selenitic.h
@@ -32,16 +32,17 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
class MystResourceType8;
struct MystScriptEntry;
-class MystScriptParser_Selenitic : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Selenitic : public MystScriptParser {
public:
- MystScriptParser_Selenitic(MohawkEngine_Myst *vm);
- ~MystScriptParser_Selenitic();
+ Selenitic(MohawkEngine_Myst *vm);
+ ~Selenitic();
void disablePersistentScripts();
void runPersistentScripts();
@@ -135,6 +136,7 @@ private:
void mazeRunnerBacktrack(uint16 &oldPosition);
};
+} // End of namespace MystStacks
}
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index 128505d266..e664081c96 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -33,19 +33,18 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-// NOTE: Credits Start Card is 10000
-
-MystScriptParser_Slides::MystScriptParser_Slides(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+Slides::Slides(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
setupOpcodes();
}
-MystScriptParser_Slides::~MystScriptParser_Slides() {
+Slides::~Slides() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Slides::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Slides::x, #x))
-void MystScriptParser_Slides::setupOpcodes() {
+void Slides::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_returnToMenu);
@@ -55,11 +54,11 @@ void MystScriptParser_Slides::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Slides::disablePersistentScripts() {
+void Slides::disablePersistentScripts() {
_cardSwapEnabled = false;
}
-void MystScriptParser_Slides::runPersistentScripts() {
+void Slides::runPersistentScripts() {
if (_cardSwapEnabled) {
// Used on Cards...
if (_vm->_system->getMillis() - _lastCardTime >= 2 * 1000)
@@ -67,11 +66,11 @@ void MystScriptParser_Slides::runPersistentScripts() {
}
}
-void MystScriptParser_Slides::o_returnToMenu(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Slides::o_returnToMenu(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_vm->changeToStack(kDemoStack, 2001, 0, 0);
}
-void MystScriptParser_Slides::o_setCardSwap(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Slides::o_setCardSwap(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used on Cards...
if (argc == 1) {
_nextCardID = argv[0];
@@ -81,4 +80,5 @@ void MystScriptParser_Slides::o_setCardSwap(uint16 op, uint16 var, uint16 argc,
unknown(op, var, argc, argv);
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/slides.h b/engines/mohawk/myst_stacks/slides.h
index 7230eead25..1e0504a665 100644
--- a/engines/mohawk/myst_stacks/slides.h
+++ b/engines/mohawk/myst_stacks/slides.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Slides : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Slides : public MystScriptParser {
public:
- MystScriptParser_Slides(MohawkEngine_Myst *vm);
- ~MystScriptParser_Slides();
+ Slides(MohawkEngine_Myst *vm);
+ ~Slides();
void disablePersistentScripts();
void runPersistentScripts();
@@ -57,6 +58,7 @@ private:
uint32 _lastCardTime;
};
+} // End of namespace MystStacks
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index ebf7f75d88..b5b403dad8 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -35,8 +35,9 @@
#include "gui/message.h"
namespace Mohawk {
+namespace MystStacks {
-MystScriptParser_Stoneship::MystScriptParser_Stoneship(MohawkEngine_Myst *vm) :
+Stoneship::Stoneship(MohawkEngine_Myst *vm) :
MystScriptParser(vm), _state(vm->_gameState->_stoneship) {
setupOpcodes();
@@ -60,12 +61,12 @@ MystScriptParser_Stoneship::MystScriptParser_Stoneship(MohawkEngine_Myst *vm) :
_state.generatorPowerAvailable = 0;
}
-MystScriptParser_Stoneship::~MystScriptParser_Stoneship() {
+Stoneship::~Stoneship() {
}
-#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &MystScriptParser_Stoneship::x, #x))
+#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Stoneship::x, #x))
-void MystScriptParser_Stoneship::setupOpcodes() {
+void Stoneship::setupOpcodes() {
// "Stack-Specific" Opcodes
OPCODE(100, o_pumpTurnOff);
OPCODE(101, o_brotherDoorOpen);
@@ -111,14 +112,14 @@ void MystScriptParser_Stoneship::setupOpcodes() {
#undef OPCODE
-void MystScriptParser_Stoneship::disablePersistentScripts() {
+void Stoneship::disablePersistentScripts() {
_batteryCharging = false;
_batteryDepleting = false;
_batteryGaugeRunning = false;
_telescopeRunning = false;
}
-void MystScriptParser_Stoneship::runPersistentScripts() {
+void Stoneship::runPersistentScripts() {
if (_batteryCharging)
chargeBattery_run();
@@ -135,7 +136,7 @@ void MystScriptParser_Stoneship::runPersistentScripts() {
tunnel_run();
}
-uint16 MystScriptParser_Stoneship::getVar(uint16 var) {
+uint16 Stoneship::getVar(uint16 var) {
switch(var) {
case 0: // Water Drained From Lighthouse / Right Button Of Pump
return _state.pumpState == 4;
@@ -260,7 +261,7 @@ uint16 MystScriptParser_Stoneship::getVar(uint16 var) {
}
}
-void MystScriptParser_Stoneship::toggleVar(uint16 var) {
+void Stoneship::toggleVar(uint16 var) {
switch(var) {
case 0: // Water Drained From Lighthouse / Right Button Of Pump
if (_state.pumpState == 4)
@@ -326,7 +327,7 @@ void MystScriptParser_Stoneship::toggleVar(uint16 var) {
}
}
-bool MystScriptParser_Stoneship::setVarValue(uint16 var, uint16 value) {
+bool Stoneship::setVarValue(uint16 var, uint16 value) {
bool refresh = false;
switch (var) {
@@ -380,7 +381,7 @@ bool MystScriptParser_Stoneship::setVarValue(uint16 var, uint16 value) {
return refresh;
}
-void MystScriptParser_Stoneship::o_pumpTurnOff(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_pumpTurnOff(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Turn off previous pump selection", op);
if (_state.pumpState) {
@@ -410,7 +411,7 @@ void MystScriptParser_Stoneship::o_pumpTurnOff(uint16 op, uint16 var, uint16 arg
}
}
-void MystScriptParser_Stoneship::o_brotherDoorOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_brotherDoorOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Open brother door", op);
_brotherDoorOpen = 1;
@@ -418,7 +419,7 @@ void MystScriptParser_Stoneship::o_brotherDoorOpen(uint16 op, uint16 var, uint16
animatedUpdate(argc, argv, 5);
}
-void MystScriptParser_Stoneship::o_cabinBookMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_cabinBookMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Play Book Room Movie", op);
uint16 startTime = argv[0];
@@ -429,7 +430,7 @@ void MystScriptParser_Stoneship::o_cabinBookMovie(uint16 op, uint16 var, uint16
_vm->_video->waitUntilMovieEnds(book);
}
-void MystScriptParser_Stoneship::o_drawerOpenSirius(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_drawerOpenSirius(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Open drawer", op);
MystResourceType8 *drawer = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
@@ -447,18 +448,18 @@ void MystScriptParser_Stoneship::o_drawerOpenSirius(uint16 op, uint16 var, uint1
_vm->_gfx->runTransition(transition, drawer->getRect(), 25, 5);
}
-void MystScriptParser_Stoneship::o_drawerClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_drawerClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Close drawer", op);
drawerClose(argv[0]);
}
-void MystScriptParser_Stoneship::o_telescopeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_telescopeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
_telescopeOldMouse = mouse.x;
_vm->_cursor->setCursor(700);
}
-void MystScriptParser_Stoneship::o_telescopeMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_telescopeMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Telescope move", op);
MystResourceType11 *display = static_cast<MystResourceType11 *>(_invokingResource);
@@ -477,11 +478,11 @@ void MystScriptParser_Stoneship::o_telescopeMove(uint16 op, uint16 var, uint16 a
_vm->_system->updateScreen();
}
-void MystScriptParser_Stoneship::o_telescopeStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_telescopeStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_vm->checkCursorHints();
}
-void MystScriptParser_Stoneship::o_generatorStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_generatorStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator start", op);
MystResourceType11 *handle = static_cast<MystResourceType11 *>(_invokingResource);
@@ -507,7 +508,7 @@ void MystScriptParser_Stoneship::o_generatorStart(uint16 op, uint16 var, uint16
_vm->_sound->replaceSoundMyst(soundId, Audio::Mixer::kMaxChannelVolume, true);
}
-void MystScriptParser_Stoneship::o_generatorStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_generatorStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator stop", op);
_batteryCharging = false;
@@ -534,7 +535,7 @@ void MystScriptParser_Stoneship::o_generatorStop(uint16 op, uint16 var, uint16 a
_vm->_sound->replaceSoundMyst(soundId);
}
-void MystScriptParser_Stoneship::chargeBattery_run() {
+void Stoneship::chargeBattery_run() {
uint32 time = _vm->_system->getMillis();
if (time > _batteryNextTime) {
@@ -543,7 +544,7 @@ void MystScriptParser_Stoneship::chargeBattery_run() {
}
}
-uint16 MystScriptParser_Stoneship::batteryRemainingCharge() {
+uint16 Stoneship::batteryRemainingCharge() {
uint32 time = _vm->_system->getMillis();
if (_state.generatorDepletionTime > time) {
@@ -553,7 +554,7 @@ uint16 MystScriptParser_Stoneship::batteryRemainingCharge() {
}
}
-void MystScriptParser_Stoneship::batteryDeplete_run() {
+void Stoneship::batteryDeplete_run() {
uint32 time = _vm->_system->getMillis();
if (time > _batteryNextTime) {
@@ -574,7 +575,7 @@ void MystScriptParser_Stoneship::batteryDeplete_run() {
}
}
-void MystScriptParser_Stoneship::o_drawerOpenAchenar(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_drawerOpenAchenar(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Open drawer", op);
MystResourceType8 *drawer = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
@@ -582,7 +583,7 @@ void MystScriptParser_Stoneship::o_drawerOpenAchenar(uint16 op, uint16 var, uint
_vm->_gfx->runTransition(5, drawer->getRect(), 25, 5);
}
-void MystScriptParser_Stoneship::o_hologramPlayback(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_hologramPlayback(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 2013 (Achenar's Rose-Skull Hologram)
debugC(kDebugScript, "Opcode %d: Rose-Skull Hologram Playback", op);
@@ -604,12 +605,12 @@ void MystScriptParser_Stoneship::o_hologramPlayback(uint16 op, uint16 var, uint1
_vm->_video->delayUntilMovieEnds(displayMovie);
}
-void MystScriptParser_Stoneship::o_hologramSelectionStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_hologramSelectionStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram start move", op);
//_vm->_cursor->setCursor(0);
}
-void MystScriptParser_Stoneship::o_hologramSelectionMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_hologramSelectionMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram move", op);
MystResourceType11 *handle = static_cast<MystResourceType11 *>(_invokingResource);
@@ -636,12 +637,12 @@ void MystScriptParser_Stoneship::o_hologramSelectionMove(uint16 op, uint16 var,
}
}
-void MystScriptParser_Stoneship::o_hologramSelectionStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_hologramSelectionStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram stop move", op);
_vm->checkCursorHints();
}
-void MystScriptParser_Stoneship::o_compassButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_compassButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Compass rose button pressed", op);
// Used on Card 2111 (Compass Rose)
// Called when Button Clicked.
@@ -663,7 +664,7 @@ void MystScriptParser_Stoneship::o_compassButton(uint16 op, uint16 var, uint16 a
o_redrawCard(op, var, argc, argv);
}
-void MystScriptParser_Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Chest valve videos", op);
Common::String movie = _vm->wrapMovieFilename("ligspig", kStoneshipStack);
@@ -699,7 +700,7 @@ void MystScriptParser_Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint1
}
}
-void MystScriptParser_Stoneship::o_chestDropKey(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_chestDropKey(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: drop chest key", op);
// If holding Key to Lamp Room Trapdoor, drop to bottom of
@@ -710,7 +711,7 @@ void MystScriptParser_Stoneship::o_chestDropKey(uint16 op, uint16 var, uint16 ar
}
}
-void MystScriptParser_Stoneship::o_trapLockOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_trapLockOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Trap lock open video", op);
Common::String movie = _vm->wrapMovieFilename("openloc", kStoneshipStack);
@@ -729,7 +730,7 @@ void MystScriptParser_Stoneship::o_trapLockOpen(uint16 op, uint16 var, uint16 ar
_vm->_sound->playSound(4143);
}
-void MystScriptParser_Stoneship::o_sideDoorsMovies(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_sideDoorsMovies(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Cards 2285, 2289, 2247, 2251 (Side Doors in Tunnels Down To Brothers Rooms)
uint16 movieId = argv[0];
@@ -765,14 +766,14 @@ void MystScriptParser_Stoneship::o_sideDoorsMovies(uint16 op, uint16 var, uint16
_vm->_cursor->showCursor();
}
-void MystScriptParser_Stoneship::o_cloudOrbEnter(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_cloudOrbEnter(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cloud orb enter", op);
_vm->_sound->replaceSoundMyst(_cloudOrbSound, Audio::Mixer::kMaxChannelVolume, true);
_cloudOrbMovie->playMovie();
}
-void MystScriptParser_Stoneship::o_cloudOrbLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_cloudOrbLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cloud orb leave", op);
_cloudOrbMovie->pauseMovie(true);
@@ -780,7 +781,7 @@ void MystScriptParser_Stoneship::o_cloudOrbLeave(uint16 op, uint16 var, uint16 a
_vm->_gfx->runTransition(5, _invokingResource->getRect(), 4, 0);
}
-void MystScriptParser_Stoneship::o_drawerCloseOpened(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_drawerCloseOpened(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Close open drawer", op);
uint16 drawerOpen = getVar(var);
@@ -788,7 +789,7 @@ void MystScriptParser_Stoneship::o_drawerCloseOpened(uint16 op, uint16 var, uint
drawerClose(argv[0] + drawerOpen - 1);
}
-void MystScriptParser_Stoneship::drawerClose(uint16 drawer) {
+void Stoneship::drawerClose(uint16 drawer) {
_chestDrawersOpen = 0;
_vm->drawCardBackground();
_vm->drawResourceImages();
@@ -797,19 +798,19 @@ void MystScriptParser_Stoneship::drawerClose(uint16 drawer) {
_vm->_gfx->runTransition(6, res->getRect(), 25, 5);
}
-void MystScriptParser_Stoneship::o_hologramDisplay_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_hologramDisplay_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram display init", op);
_hologramDisplay = static_cast<MystResourceType6 *>(_invokingResource);
_hologramDisplayPos = 0;
}
-void MystScriptParser_Stoneship::o_hologramSelection_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_hologramSelection_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram selection init", op);
_hologramSelection = static_cast<MystResourceType6 *>(_invokingResource);
}
-void MystScriptParser_Stoneship::batteryGaugeUpdate() {
+void Stoneship::batteryGaugeUpdate() {
uint16 charge = 0;
if (_state.generatorDepletionTime) {
@@ -823,7 +824,7 @@ void MystScriptParser_Stoneship::batteryGaugeUpdate() {
_batteryGauge->setRect(rect);
}
-void MystScriptParser_Stoneship::o_battery_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_battery_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 2160 (Lighthouse Battery Pack Closeup)
debugC(kDebugScript, "Opcode %d: Battery init", op);
@@ -832,7 +833,7 @@ void MystScriptParser_Stoneship::o_battery_init(uint16 op, uint16 var, uint16 ar
batteryGaugeUpdate();
}
-void MystScriptParser_Stoneship::o_tunnelEnter_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_tunnelEnter_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Tunnel enter", op);
o_tunnel_init(op, var, argc, argv);
@@ -841,13 +842,13 @@ void MystScriptParser_Stoneship::o_tunnelEnter_init(uint16 op, uint16 var, uint1
_tunnelNextTime = _vm->_system->getMillis() + 1500;
}
-void MystScriptParser_Stoneship::o_batteryGauge_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_batteryGauge_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Battery gauge init", op);
_batteryLastCharge = batteryRemainingCharge();
_batteryGaugeRunning = true;
}
-void MystScriptParser_Stoneship::batteryGauge_run() {
+void Stoneship::batteryGauge_run() {
uint16 batteryCharge = batteryRemainingCharge();
if (batteryCharge != _batteryLastCharge) {
@@ -863,7 +864,7 @@ void MystScriptParser_Stoneship::batteryGauge_run() {
}
}
-void MystScriptParser_Stoneship::o_tunnel_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_tunnel_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Tunnel card init", op);
_tunnelImagesCount = argv[0];
@@ -880,7 +881,7 @@ void MystScriptParser_Stoneship::o_tunnel_init(uint16 op, uint16 var, uint16 arg
debugC(kDebugScript, "\tsoundIdAlarm: %d", _tunnelAlarmSound);
}
-void MystScriptParser_Stoneship::tunnel_run() {
+void Stoneship::tunnel_run() {
uint32 time = _vm->_system->getMillis();
if (time > _tunnelNextTime) {
@@ -903,19 +904,19 @@ void MystScriptParser_Stoneship::tunnel_run() {
}
}
-void MystScriptParser_Stoneship::o_tunnelLeave_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_tunnelLeave_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Tunnel leave", op);
_tunnelRunning = false;
}
-void MystScriptParser_Stoneship::o_chest_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_chest_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Chest init", op);
_state.chestOpenState = 0;
}
-void MystScriptParser_Stoneship::o_telescope_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_telescope_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Telescope init", op);
// Used in Card 2218 (Telescope view)
@@ -929,7 +930,7 @@ void MystScriptParser_Stoneship::o_telescope_init(uint16 op, uint16 var, uint16
_telescopeNexTime = _vm->_system->getMillis() + 1000;
}
-void MystScriptParser_Stoneship::telescope_run() {
+void Stoneship::telescope_run() {
uint32 time = _vm->_system->getMillis();
if (time > _telescopeNexTime) {
@@ -942,7 +943,7 @@ void MystScriptParser_Stoneship::telescope_run() {
}
}
-void MystScriptParser_Stoneship::telescopeLighthouseDraw() {
+void Stoneship::telescopeLighthouseDraw() {
if (_telescopePosition > 1137 && _telescopePosition < 1294) {
uint16 imageId = _telescopeLighthouseOff;
@@ -964,7 +965,7 @@ void MystScriptParser_Stoneship::telescopeLighthouseDraw() {
}
}
-void MystScriptParser_Stoneship::o_achenarDrawers_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_achenarDrawers_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Achenar's Room Drawers Init", op);
// Used for Card 2004 (Achenar's Room Drawers)
@@ -982,7 +983,7 @@ void MystScriptParser_Stoneship::o_achenarDrawers_init(uint16 op, uint16 var, ui
}
}
-void MystScriptParser_Stoneship::o_cloudOrb_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void Stoneship::o_cloudOrb_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cloud orb init", op);
_cloudOrbMovie = static_cast<MystResourceType6 *>(_invokingResource);
@@ -990,4 +991,5 @@ void MystScriptParser_Stoneship::o_cloudOrb_init(uint16 op, uint16 var, uint16 a
_cloudOrbStopSound = argv[1];
}
+} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/stoneship.h b/engines/mohawk/myst_stacks/stoneship.h
index eb58bd6543..091fdcd169 100644
--- a/engines/mohawk/myst_stacks/stoneship.h
+++ b/engines/mohawk/myst_stacks/stoneship.h
@@ -32,15 +32,16 @@
namespace Mohawk {
-#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
-
-class MohawkEngine_Myst;
struct MystScriptEntry;
-class MystScriptParser_Stoneship : public MystScriptParser {
+namespace MystStacks {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class Stoneship : public MystScriptParser {
public:
- MystScriptParser_Stoneship(MohawkEngine_Myst *vm);
- ~MystScriptParser_Stoneship();
+ Stoneship(MohawkEngine_Myst *vm);
+ ~Stoneship();
void disablePersistentScripts();
void runPersistentScripts();
@@ -142,6 +143,7 @@ private:
uint16 batteryRemainingCharge();
};
+} // End of namespace MystStacks
}
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_vars.cpp b/engines/mohawk/myst_vars.cpp
deleted file mode 100644
index f8ea11a1e2..0000000000
--- a/engines/mohawk/myst_vars.cpp
+++ /dev/null
@@ -1,578 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "mohawk/myst.h"
-#include "mohawk/myst_vars.h"
-
-namespace Mohawk {
-
-// The Myst variable system is complex, and the structure is fairly
-// unknown. The idea of this class is to abstract the variable references
-// from the storage structure until the structure is clear enough that
-// the complexity of this abstraction can be removed.
-
-// The exact organization of local/global, persistent/non-persistent
-// age-specific mapping etc. is currently unknown.
-
-MystVarEntry introVars[] = {
- { 0, 7, "Age To Link To" } // 0 to 7
- // 0 = Selenitic
- // 1 = Stoneship
- // 2 = Myst (Library Ceiling)
- // 3 = Mechanical
- // 4 = Channelwood
- // 5 = Myst (Start of Movie - Over Sea)
- // 6 = D'ni
- // 7 = Myst (End of Movie - On Dock)
-};
-
-MystVarEntry seleniticVars[] = {
- { 0, 0, "Sound Pickup At Windy Tunnel" }, // 0 to 1 // TODO: Multiple Uses of Var 0?
- { 1, 0, "Sound Pickup At Volcanic Crack" }, // 0 to 1
- { 2, 0, "Sound Pickup At Clock" }, // 0 to 1
- { 3, 0, "Sound Pickup At Water Pool" }, // 0 to 1
- { 4, 0, "Sound Pickup At Crystal Rocks" }, // 0 to 1
- { 5, 0, "Sound Receiver Doors" }, // 0 to 1
- { 6, 0, "Windy Tunnel Lights" }, // 0 to 1
- { 7, 0, "Maze Runner Porthole View" }, // 0 to 3
- { 8, 0, "Sound Receiver Screen (Control Variable?)" },
- { 9, 0, "Sound Receiver Water Pool Button Selected" },
- { 10, 0, "Sound Receiver Volcanic Crack Button Selected" },
- { 11, 0, "Sound Receiver Clock Button Selected" },
- { 12, 0, "Sound Receiver Crystal Rocks Button Selected" },
- { 13, 0, "Sound Receiver Windy Tunnel Button Selected" },
- { 14, 0, "Sound Receiver LED Digit #0 (Left)" },
- { 15, 0, "Sound Receiver LED Digit #1" },
- { 16, 0, "Sound Receiver LED Digit #2" },
- { 17, 0, "Sound Receiver LED Digit #3 (Right)" },
- { 18, 0, "Sound Receiver Green Arrow - Right" },
- { 19, 0, "Sound Receiver Green Arrow - Left" },
- { 20, 0, "Sound Lock Slider #1 (Left) (Position?)" },
- { 21, 0, "Sound Lock Slider #2 (Position?)" },
- { 22, 0, "Sound Lock Slider #3 (Position?)" },
- { 23, 0, "Sound Lock Slider #4 (Position?)" },
- { 24, 0, "Sound Lock Slider #5 (Right) (Position?)" },
- { 25, 0, "Maze Runner Compass Heading" }, // 0 to 8
- { 26, 0, "Sound Receiver Sum Button Selected" },
- { 27, 0, "Maze Runner Red Warning Light" },
- { 28, 0, "Sound Lock Button State" },
- { 29, 0, "Maze Runner Door Button State" },
- { 30, 0, "Maze Runner Door State" },
- { 31, 0, "Maze Runner Forward Button Lit" }, // 0 to 2
- { 32, 0, "Maze Runner Left & Right Button Lit" }, // 0 to 2
- { 33, 0, "Maze Runner Backtrack Button Lit" }, // 0 to 2
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" } // 0 to 1
-};
-
-MystVarEntry stoneshipVars[] = {
- { 0, 0, "Water Pump Button #3 (Right) / Lighthouse Water Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit
- { 1, 0, "Water Pump Button #2 / Tunnels To Brothers Rooms Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit
- { 2, 0, "Water Pump Button #1 (Left) / Ship Cabin Water Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit
- { 3, 0, "Lighthouse (Water or Chest Floating?)" }, // 0 to 1, Used by Far View
- { 4, 0, "Lighthouse Water/Chest State" }, // 0 to 2 = Water, No Water, Water & Chest Floating
- { 5, 2, "Lighthouse Trapdoor State" }, // 0 to 2 = Closed & Unlocked, Open, Closed & Locked
- { 6, 0, "Lighthouse Chest Valve Position" }, // 0 to 1
- { 7, 0, "Lighthouse Chest Unlocked" }, // 0 to 1
- { 8, 0, "Lighthouse Chest Key Position?" }, // 0 to 2, 2 = Bottom of Lighthouse
-// Var 9 Unused
- { 10, 1, "Lighthouse Chest Full Of Water" }, // 0 to 1
- { 11, 3, "Lighthouse Key State" }, // 0 to 3 = Closed?, Open & No Key, Open & No Key, Open & Key
- { 12, 0, "Lighthouse Trapdoor - Holding Key" }, // 0 to 1
- { 13, 0, "State of Water in Tunnels to Brothers' Rooms" }, // 0 to 2 = Dark & Water, Dark & Drained, Lit & Water
- { 14, 0, "Tunnels to Brothers' Rooms Lit" }, // 0 to 1
- { 15, 0, "Side Door in Tunnels To Brother's Rooms Open" }, // 0 to 1
- { 16, 0, "Underwater Light Lit" }, // 0 to 1
- { 17, 0, "Sirrus' Room Drawer with Drugs Open" }, // 0 to 1
- { 18, 0, "Brother Room Door Open" }, // 0 to 1, Used for Door Slam
- { 19, 0, "Brother Room Door State" }, // 0 to 2 = Closed, Open & Dark, Open & Lit
- { 20, 0, "Ship Cabin Myst Book Present" }, // 0 to 1
- { 21, 0, "Brothers Rooms' Chest Of Drawers Drawer State" }, // 0 to 6 (Card 2197) or 0 to 7 (Card 2004)
- { 22, 0, "Sirrus' Chest of Drawers Drawer #1 (Top) Open" }, // 0 to 1
- { 23, 0, "Sirrus' Chest of Drawers Drawer #2 Open" }, // 0 to 1
- { 24, 0, "Sirrus' Chest of Drawers Drawer #3 Open" }, // 0 to 1
-// Var 25 Unused - Replaced by Var 35.
- { 26, 0, "Sirrus' Chest of Drawers Left Small Drawer Open" }, // 0 to 1
- { 27, 0, "Sirrus' Chest of Drawers Right Small Drawer Open" }, // 0 to 1
- { 28, 0, "Telescope View Position" }, // Range Unknown.. 0 to 360?
- { 29, 0, "Achenar's Room Rose/Skull Hologram Button Lit" }, // 0 to 1
- { 30, 2, "Light State in Tunnel to Compass Rose Room" }, // 0 to 2 = Lit & Underwater Light Lit, Lit, Dark
- { 31, 0, "Lighthouse Lamp Room Battery Pack Indicator Light" }, // 0 to 1
- { 32, 0, "Lighthouse Lamp Room Battery Pack Meter Level" }, // Range Unknown.. // Must be 1 to vertical size of image...
- { 33, 0, "State of Side Door in Tunnels to Compass Rose Room (Power?)" }, // 0 to 2 = Closed (No Power), Closed (Power), Open
- { 34, 1, "Achenar's Room Drawer with Torn Note Closed" }, // 0 to 1
- { 35, 2, "Sirrus' Room Drawer #4 (Bottom) Open and Red Page State" }, // 0 to 2 = Open, Open with Page, Closed
- { 36, 0, "Ship Cabin Door State" }, // 0 to 2 = Closed, Open & Dark, Open & Lit
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" }, // 0 to 1
- { 105, 0, "Ship Cabin Door State" }
-};
-
-MystVarEntry mystVars[] = {
- { 0, 1, "Myst Library Bookcase Closed / Library Exit Open" }, // 0 to 1 // TODO: Multiple Uses of Var 0?
- { 1, 0, "Myst Library Bookcase Open / Library Exit Blocked" }, // 0 to 1
- { 2, 0, "Marker Switch Near Cabin" }, // 0 to 1
- { 3, 0, "Marker Switch Near Clock Tower" }, // 0 to 1
- { 4, 0, "Marker Switch on Dock" }, // 0 to 1
- { 5, 0, "Marker Switch Near Ship Pool" }, // 0 to 1
- { 6, 0, "Marker Switch Near Cogs" }, // 0 to 1
- { 7, 0, "Marker Switch Near Generator Room" }, // 0 to 1
- { 8, 0, "Marker Switch Near Stellar Observatory" }, // 0 to 1
- { 9, 0, "Marker Switch Near Rocket Ship" }, // 0 to 1
- { 10, 0, "Ship Floating State" }, // 0 to 1
- { 11, 0, "Cabin Door Open State" },
- { 12, 0, "Clock Tower Gear Bridge" }, // 0 to 1
- { 13, 0, "Tower Elevator Sound Control" }, // 0 to 1
- { 14, 0, "Tower Solution (Key) Plaque" }, // 0 to 4
- // 0 = None
- // 1 = 59 V
- // 2 = 2:40 2-2-1
- // 3 = October 11, 1984 10:04 AM
- // January 17, 1207 5:46 AM
- // November 23, 9791 6:57 PM
- // 4 = 7, 2, 4
- { 15, 0, "Tower Window (Book) View" }, // 0 to 6
- // 0 = Wall
- // 1 = Rocketship
- // 2 = Cogs Closed
- // 3 = Ship Sunk
- // 4 = Channelwood Tree
- // 5 = Ship Floating
- // 6 = Cogs Open
- { 16, 0, "Tower Window (Book) View From Ladder Top" }, // 0 to 2
- // 0 = Wall
- // 1 = Sky
- // 2 = Sky with Channelwood Tree
- { 17, 0, "Fireplace Grid Row #1 (Top)" }, // Bitfield 0x00 to 0xFF
- { 18, 0, "Fireplace Grid Row #2" }, // Bitfield 0x00 to 0xFF
- { 19, 0, "Fireplace Grid Row #3" }, // Bitfield 0x00 to 0xFF
- { 20, 0, "Fireplace Grid Row #4" }, // Bitfield 0x00 to 0xFF
- { 21, 0, "Fireplace Grid Row #5" }, // Bitfield 0x00 to 0xFF
- { 22, 0, "Fireplace Grid Row #6 (Bottom)" }, // Bitfield 0x00 to 0xFF
- { 23, 0, "Fireplace Pattern Correct" }, // 0 to 1
- { 24, 1, "Fireplace Blue Page Present" }, // 0 to 1
- { 25, 1, "Fireplace Red Page Present" }, // 0 to 1
- { 26, 0, "Ship Puzzle Box Image (Cross)" }, // 0 to 2
- { 27, 0, "Ship Puzzle Box Image (Leaf)" }, // 0 to 2
- { 28, 0, "Ship Puzzle Box Image (Arrow)" }, // 0 to 2
- { 29, 0, "Ship Puzzle Box Image (Eye)" }, // 0 to 2
- { 30, 0, "Ship Puzzle Box Image (Snake)" }, // 0 to 2
- { 31, 0, "Ship Puzzle Box Image (Spider)" }, // 0 to 2
- { 32, 0, "Ship Puzzle Box Image (Anchor)" }, // 0 to 2
- { 33, 0, "Ship Puzzle Box Image (Ostrich)" }, // 0 to 2
- { 34, 2, "Dock Forechamber Imager State" }, // 0 to 2 = Off, Mountain, Water
- { 35, 5, "Dock Forechamber Imager Control Left Digit" }, // 0 to 9
- { 36, 6, "Dock Forechamber Imager Control Right Digit" }, // 0 to 9
- { 37, 0, "Clock Tower Control Wheels Position" }, // 0 to 8
-// Var 38 Unused
-// 39 = TODO: ?
- { 40, 0, "Cog Close/Open State" },
- { 41, 0, "Dock Marker Switch Vault State" }, // 0 to 2 = Closed, Open & Page Taken, Open & Page Present
-// Var 42 Unused
- { 43, 0, "Clock Tower Time" }, // 0 to 143
- { 44, 0, "Rocket Ship Power State" }, // 0 to 2 = None, Insufficient, Correct
- { 45, 1, "Dock Forechamber Imager Water Effect Enabled" }, // 0 to 1
- { 46, 0, "Number Of Pages in Red Book" }, // 0 to 6 = 0-5, Extra
- { 47, 0, "Number Of Pages in Blue Book" }, // 0 to 6 = 0-5, Extra
- { 48, 0, "Marker Switch on Dock - Duplicate of Var #4?" }, // 0 to 2
- { 49, 0, "Generator Running" }, // Boolean used for Sound..
-// 50 = TODO: ?
- { 51, 2, "Forechamber Imager Movie Control Variable" }, // 0 to 4 = Blank, Mountain, Water, Atrus, Marker Switch
- { 52, 0, "Generator Switch #1" },
- { 53, 0, "Generator Switch #2" },
- { 54, 0, "Generator Switch #3" },
- { 55, 0, "Generator Switch #4" },
- { 56, 0, "Generator Switch #5" },
- { 57, 0, "Generator Switch #6" },
- { 58, 0, "Generator Switch #7" },
- { 59, 0, "Generator Switch #8" },
- { 60, 0, "Generator Switch #9" },
- { 61, 0, "Generator Switch #10" },
- { 62, 0, "Generator Power Dial Left LED Digit" }, // 0 to 9
- { 63, 0, "Generator Power Dial Right LED Digit" }, // 0 to 9
- { 64, 0, "Generator Power To Spaceship Dial Left LED Digit" }, // 0 to 9
- { 65, 0, "Generator Power To Spaceship Dial Right LED Digit" }, // 0 to 9
- { 66, 0, "Generator Room Lights On" }, // Boolean
- { 67, 9, "Cabin Safe Lock Number #1 - Left" },
- { 68, 9, "Cabin Safe Lock Number #2" },
- { 69, 9, "Cabin Safe Lock Number #3 - Right" },
- { 70, 0, "Cabin Safe Matchbox State" }, // 0 to 2
- { 71, 1, "Stellar Observatory Lights" },
- { 72, 0, "Channelwood Tree Position" }, // 0 to 12, 4 for Alcove
- { 73, 9, "Stellar Observatory Telescope Control - Month" }, // 0 to 11, Not in order...
- // 0 = OCT, 1 = NOV, 2 = DEC, 3 = JUL, 4 = AUG, 5 = SEP
- // 6 = APR, 7 = MAY, 8 = JUN, 9 = JAN, 10 = FEB, 11 = MAR
- { 74, 10, "Stellar Observatory Telescope Control - Day Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 75, 1, "Stellar Observatory Telescope Control - Day Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank
- { 76, 10, "Stellar Observatory Telescope Control - Year Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 77, 10, "Stellar Observatory Telescope Control - Year Digit #2" }, // 0 to 10 = 0 to 9, Blank
- { 78, 10, "Stellar Observatory Telescope Control - Year Digit #3" }, // 0 to 10 = 0 to 9, Blank
- { 79, 0, "Stellar Observatory Telescope Control - Year Digit #4 (Right)" }, // 0 to 10 = 0 to 9, Blank
- { 80, 1, "Stellar Observatory Telescope Control - Hour Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 81, 2, "Stellar Observatory Telescope Control - Hour Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank
- { 82, 0, "Stellar Observatory Telescope Control - Minute Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 83, 0, "Stellar Observatory Telescope Control - Minute Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank
-// 84 to 87 = TODO: ?
- { 88, 0, "Stellar Observatory Telescope Control - AM/PM Indicator" }, // 0 = AM, 1 = PM
- { 89, 0, "Stellar Observatory Telescope Control - Slider #1 (Left)" }, // 0 to 2 = Not Present, Dark, Lit
- { 90, 0, "Stellar Observatory Telescope Control - Slider #2" }, // 0 to 2 = Not Present, Dark, Lit
- { 91, 0, "Stellar Observatory Telescope Control - Slider #3" }, // 0 to 2 = Not Present, Dark, Lit
- { 92, 0, "Stellar Observatory Telescope Control - Slider #4 (Right)" }, // 0 to 2 = Not Present, Dark, Lit
- { 93, 0, "Breaker nearest Generator Room Blown" },
- { 94, 0, "Breaker nearest Rocket Ship Blown" },
-// 95 = TODO: ?
- { 96, 0, "Generator Power Dial Needle Position" }, // 0 to 24
- { 97, 0, "Generator Power To Spaceship Dial Needle Position" }, // 0 to 24
- { 98, 0, "Cabin Boiler Pilot Light Lit" },
- { 99, 0, "Cabin Boiler Gas Valve Position" }, // 0 to 5
- { 100, 0, "Red Book Page State" }, // Bitfield
- { 101, 0, "Blue Book Page State" }, // Bitfield
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" }, // 0 to 1
-// 104 = TODO: ?
- { 105, 0, "Clock Tower Door / Ship Box Temp Value" },
- { 106, 0, "Red / Blue Book State" }, // 0 to 4, 0-3 = Books Present 4 = Books Burnt
- { 300, 0, "Rocket Ship Music Puzzle Slider State" }, // 0 to 2 = Not Present, Dark, Lit
- { 301, 0, "Rocket Ship Piano Key Depressed" }, // 0 to 1
- { 302, 0, "Green Book Opened Before Flag" }, // 0 to 1
- { 303, 1, "Myst Library Bookcase Closed / Library Exit Open" },
- { 304, 0, "Myst Library Image Present on Tower Rotation Map" }, // 0 to 1
- { 305, 0, "Cabin Boiler Lit" },
- { 306, 0, "Cabin Boiler Steam Sound Control" }, // 0 to 27
- { 307, 0, "Cabin Boiler Needle Position i.e. Fully Pressurised" }, // 0 to 1
- { 308, 0, "Cabin Safe Handle Position / Matchbox Temp Value" },
- { 309, 0, "Red/Blue/Green Book Open" }, // 0 to 1
- { 310, 0, "Dock Forechamber Imager Control Temp Value?" }
-};
-
-MystVarEntry mechVars[] = {
- { 0, 0, "Achenar's Room Secret Panel State" }, // TODO: Multiple Uses of Var 0?
- { 1, 0, "Sirrus's Room Secret Panel State" },
- { 2, 0, "Achenar's Secret Room Crate Lid Open and Blue Page Present" }, // 0 to 4
- // 0 = Lid Closed, Blue Page Present
- // 1 = Lid Closed, Blue Page Not Present
- // 2 = Lid Open, Blue Page Not Present
- // 3 = Lid Open, Blue Page Present
- { 3, 0, "Achenar's Secret Room Crate Lid Open" }, // 0 to 1
- { 4, 0, "Myst Book Staircase State" },
- { 5, 0, "Fortress Telescope View" },
- { 6, 0, "Large Cog Visible Through Distant Fortress Doorway" }, // 0 to 1
- { 7, 0, "Fortress Elevator Door Rotated to Open" }, // 0 to 1
-// Var 8 Not Used
-// Var 9 Not Used
- { 10, 0, "Fortress Staircase State" }, // 0 to 1
- { 11, 0, "Fortress Elevator Rotation Control - Position Indicator" }, // 0 to 9, 4 = Red Open Position
- { 12, 0, "Fortress Elevator Rotation Control - Top Cog Position" }, // 0 to 5
- { 13, 0, "Fortress Elevator Vertical Position - View" }, // 0 to 2, Used for View Logic on change from Card 6150
- { 14, 0, "Fortress Elevator Vertical Position - Button" }, // 0 to 2, Used for Button Logic on Card 6120
- { 15, 0, "Code Lock State" }, // 0 to 2
- { 16, 0, "Code Lock Shape #1 (Left)" },
- { 17, 0, "Code Lock Shape #2" },
- { 18, 0, "Code Lock Shape #3" },
- { 19, 0, "Code Lock Shape #4 (Right)" },
- { 20, 0, "Red Dodecahedron Lit" },
- { 21, 0, "Green Dodecahedron Lit" },
- { 22, 0, "Yellow Tetrahedron Lit" },
- { 23, 0, "In Elevator" }, // 0 to 1
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" } // 0 to 1
-};
-
-MystVarEntry channelwoodVars[] = {
- { 0, 0, "Multiple Uses..." }, // TODO: Multiple Uses of Var 0?
- { 1, 0, "Water Pump Bridge State" }, // 0 to 1
- { 2, 0, "Lower Walkway to Upper Walkway Elevator State" }, // 0 to 1
- { 3, 0, "Water Flowing (R) to Pump for Upper Walkway to Temple Elevator" }, // 0 to 1
- { 4, 0, "Water Flowing (L, R, R, L, Pipe Extended) to Pump for Book Room Elevator" }, // 0 to 1
- { 5, 0, "Lower Walkway to Upper Walkway Spiral Stair Lower Door Open" }, // 0 to 1
- { 6, 0, "Pipe Bridge Extended" }, // 0 to 1
- { 7, 0, "Bridge Pump Running" }, // 0 to 1
- { 8, 0, "Water Tank Valve State" }, // 0 to 1
- { 9, 0, "First Water Valve State" }, // 0 to 1
- { 10, 0, "Second (L) Water Valve State" }, // 0 to 1
- { 11, 0, "Third (L, R) Water Valve State" }, // 0 to 1
- { 12, 0, "Fourth (L, R, R) Water Valve State" }, // 0 to 1
- { 13, 0, "Fourth (L, R, L) Water Valve State" }, // 0 to 1
- { 14, 0, "Third (L, L) Water Valve State" }, // 0 to 1
- { 15, 0, "Water Flowing (L, R, R, R) to Pump for Lower Walkway to Upper Walkway Elevator" }, // 0 to 1
- { 16, 0, "Lower Walkway to Upper Walkway Spiral Stair Upper Door Open" }, // 0 to 1
- { 17, 0, "Achenar's Holoprojector Selection" }, // 0 to 3
- { 18, 0, "Drawer in Sirrus' Room with Wine Bottles and Torn Note Open" }, // 0 to 1
- { 19, 0, "Water Flowing to First Water Valve" }, // 0 to 1
- { 20, 0, "Water Flowing to Second (L) Water Valve" }, // 0 to 1
- { 21, 0, "Water Flowing to Third (L, R) Water Valve" }, // 0 to 1
- { 22, 0, "Water Flowing to Fourth (L, R, R) Water Valve" }, // 0 to 1
- { 23, 0, "Water Flowing to Fourth (L, R, L) Water Valve" }, // 0 to 1
- { 24, 0, "Water Flowing to Third (L, L) Water Valve" }, // 0 to 1
- { 25, 0, "Water Flowing to Pipe Bridge (L, R, R, L)" }, // 0 to 1
- { 26, 0, "Water Flowing to Pipe At Entry Point (L, R, L, R)" }, // 0 to 1
- { 27, 0, "Water Flowing to Join and Pump Bridge (L, R, L, L)" }, // 0 to 1
- { 28, 0, "Water Flowing to Join and Pump Bridge (L, L, R)" }, // 0 to 1
- { 29, 0, "Water Flowing to Pipe In Water (L, L, L)" }, // 0 to 1
- { 30, 0, "Lower Walkway to Upper Walkway Elevator Door Open" }, // 0 to 1
- { 31, 0, "Water Flowing to Join (L, L, R)" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow
- { 32, 0, "Water Flowing (L, R, R, L, Pipe) State" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow
- { 33, 0, "Lower Walkway to Upper Walkway Spiral Stair Upper Door State" }, // 0 to 2 = Closed, Open, Open but slams behind you.
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" }, // 0 to 1
- { 105, 0, "Upper Walkway to Temple Elevator Door Open / Temple Iron Door Open" } // 0 to 1, used for slam sound
-};
-
-MystVarEntry dniVars[] = {
- { 0, 0, "Atrus Gone" }, // 0 to 1 // TODO: Multiple Uses of Var 0?
- { 1, 0, "Myst Book State" }, // 0 to 2 = Book Inactive, Book Unlinkable, Book Linkable
- { 2, 0, "Sound Control" }, // 0 to 2 = Win Tune, Lose Tune, Stop Sound
- { 106, 0, "Atrus State Control" } // 0 to 4 = Atrus Writing, Atrus Holding Out Hand, Atrus Gone, Atrus #2, Atrus #2
-};
-
-MystVarEntry creditsVars[] = {
- { 0, 0, "Image Control" }, // 0 to 6
- { 1, 1, "Sound Control" } // 0 to 1 = Win Tune, Lose Tune
-};
-
-MystVar::MystVar(MohawkEngine_Myst *vm) {
- _vm = vm;
-}
-
-MystVar::~MystVar() {
-}
-
-// Only for use by Save/Load, all other code should use getVar()
-uint16 MystVar::saveGetVar(uint16 stack, uint16 v) {
- uint16 value = 0;
- MystVarEntry unknownVar = { v, 0, "Unknown" };
- const char *desc = NULL;
- uint16 i;
-
- switch (stack) {
- case kIntroStack:
- for (i = 0; i < ARRAYSIZE(introVars); i++) {
- if (introVars[i].refNum == v) {
- value = introVars[i].storage;
- desc = introVars[i].description;
- break;
- }
- }
- break;
- case kSeleniticStack:
- for (i = 0; i < ARRAYSIZE(seleniticVars); i++) {
- if (seleniticVars[i].refNum == v) {
- value = seleniticVars[i].storage;
- desc = seleniticVars[i].description;
- break;
- }
- }
- break;
- case kStoneshipStack:
- for (i = 0; i < ARRAYSIZE(stoneshipVars); i++) {
- if (stoneshipVars[i].refNum == v) {
- value = stoneshipVars[i].storage;
- desc = stoneshipVars[i].description;
- break;
- }
- }
- break;
- case kDemoPreviewStack:
- case kMystStack:
- for (i = 0; i < ARRAYSIZE(mystVars); i++) {
- if (mystVars[i].refNum == v) {
- value = mystVars[i].storage;
- desc = mystVars[i].description;
- break;
- }
- }
- break;
- case kMechanicalStack:
- for (i = 0; i < ARRAYSIZE(mechVars); i++) {
- if (mechVars[i].refNum == v) {
- value = mechVars[i].storage;
- desc = mechVars[i].description;
- break;
- }
- }
- break;
- case kChannelwoodStack:
- for (i = 0; i < ARRAYSIZE(channelwoodVars); i++) {
- if (channelwoodVars[i].refNum == v) {
- value = channelwoodVars[i].storage;
- desc = channelwoodVars[i].description;
- break;
- }
- }
- break;
- case kDniStack:
- for (i = 0; i < ARRAYSIZE(dniVars); i++) {
- if (dniVars[i].refNum == v) {
- value = dniVars[i].storage;
- desc = dniVars[i].description;
- break;
- }
- }
- break;
- case kCreditsStack:
- for (i = 0; i < ARRAYSIZE(creditsVars); i++) {
- if (creditsVars[i].refNum == v) {
- value = creditsVars[i].storage;
- desc = creditsVars[i].description;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- if (desc == NULL) {
- for (i = 0; i < _unknown.size(); i++) {
- if (_unknown[i].refNum == v) {
- value = _unknown[i].storage;
- desc = _unknown[i].description;
- break;
- }
- }
-
- if (desc == NULL) {
- warning("MystVar::getVar(%d): Unknown variable reference", v);
- _unknown.push_back(unknownVar);
- desc = _unknown.back().description;
- }
- }
-
- debugC(kDebugVariable, "MystVar::getVar(%d = %s): %d", v, desc, value);
- return value;
-}
-
-// Only for use by Save/Load, all other code should use setVar()
-void MystVar::loadSetVar(uint16 stack, uint16 v, uint16 value) {
- const char *desc = NULL;
- MystVarEntry unknownVar = { v, value, "Unknown" };
- uint16 i;
-
- switch (stack) {
- case kIntroStack:
- for (i = 0; i < ARRAYSIZE(introVars); i++) {
- if (introVars[i].refNum == v) {
- introVars[i].storage = value;
- desc = introVars[i].description;
- break;
- }
- }
- break;
- case kSeleniticStack:
- for (i = 0; i < ARRAYSIZE(seleniticVars); i++) {
- if (seleniticVars[i].refNum == v) {
- seleniticVars[i].storage = value;
- desc = seleniticVars[i].description;
- break;
- }
- }
- break;
- case kStoneshipStack:
- for (i = 0; i < ARRAYSIZE(stoneshipVars); i++) {
- if (stoneshipVars[i].refNum == v) {
- stoneshipVars[i].storage = value;
- desc = stoneshipVars[i].description;
- break;
- }
- }
- break;
- case kDemoPreviewStack:
- case kMystStack:
- for (i = 0; i < ARRAYSIZE(mystVars); i++) {
- if (mystVars[i].refNum == v) {
- mystVars[i].storage = value;
- desc = mystVars[i].description;
- break;
- }
- }
- break;
- case kMechanicalStack:
- for (i = 0; i < ARRAYSIZE(mechVars); i++) {
- if (mechVars[i].refNum == v) {
- mechVars[i].storage = value;
- desc = mechVars[i].description;
- break;
- }
- }
- break;
- case kChannelwoodStack:
- for (i = 0; i < ARRAYSIZE(channelwoodVars); i++) {
- if (channelwoodVars[i].refNum == v) {
- channelwoodVars[i].storage = value;
- desc = channelwoodVars[i].description;
- break;
- }
- }
- break;
- case kDniStack:
- for (i = 0; i < ARRAYSIZE(dniVars); i++) {
- if (dniVars[i].refNum == v) {
- dniVars[i].storage = value;
- desc = dniVars[i].description;
- break;
- }
- }
- break;
- case kCreditsStack:
- for (i = 0; i < ARRAYSIZE(creditsVars); i++) {
- if (creditsVars[i].refNum == v) {
- creditsVars[i].storage = value;
- desc = creditsVars[i].description;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- if (desc == NULL) {
- for (i = 0; i < _unknown.size(); i++) {
- if (_unknown[i].refNum == v) {
- _unknown[i].storage = value;
- desc = _unknown[i].description;
- break;
- }
- }
-
- if (desc == NULL) {
- warning("MystVar::setVar(%d): Unknown variable reference", v);
- _unknown.push_back(unknownVar);
- desc = _unknown.back().description;
- }
- }
-
- debugC(kDebugVariable, "MystVar::setVar(%d = %s): %d", v, desc, value);
-}
-
-uint16 MystVar::getVar(uint16 v) {
- return this->saveGetVar(_vm->getCurStack(), v);
-}
-
-void MystVar::setVar(uint16 v, uint16 value) {
- this->loadSetVar(_vm->getCurStack(), v, value);
-}
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/resource.h b/engines/mohawk/resource.h
index 18e8f80fb2..07c727951c 100644
--- a/engines/mohawk/resource.h
+++ b/engines/mohawk/resource.h
@@ -34,102 +34,102 @@
namespace Mohawk {
// Main FourCC's
-#define ID_MHWK MKID_BE('MHWK') // Main FourCC
-#define ID_RSRC MKID_BE('RSRC') // Resource Directory Tag
+#define ID_MHWK MKTAG('M','H','W','K') // Main FourCC
+#define ID_RSRC MKTAG('R','S','R','C') // Resource Directory Tag
// Myst Resource FourCC's
-#define ID_CLRC MKID_BE('CLRC') // Cursor Hotspots
-#define ID_EXIT MKID_BE('EXIT') // Card Exit Scripts
-#define ID_HINT MKID_BE('HINT') // Cursor Hints
-#define ID_INIT MKID_BE('INIT') // Card Entrance Scripts
-#define ID_MSND MKID_BE('MSND') // Standard Mohawk Sound
-#define ID_RLST MKID_BE('RLST') // Resource List, Specifies HotSpots
-#define ID_RSFL MKID_BE('RSFL') // ??? (system.dat only)
-#define ID_VIEW MKID_BE('VIEW') // Card Details
-#define ID_WDIB MKID_BE('WDIB') // LZ-Compressed Windows Bitmap
+#define ID_CLRC MKTAG('C','L','R','C') // Cursor Hotspots
+#define ID_EXIT MKTAG('E','X','I','T') // Card Exit Scripts
+#define ID_HINT MKTAG('H','I','N','T') // Cursor Hints
+#define ID_INIT MKTAG('I','N','I','T') // Card Entrance Scripts
+#define ID_MSND MKTAG('M','S','N','D') // Standard Mohawk Sound
+#define ID_RLST MKTAG('R','L','S','T') // Resource List, Specifies HotSpots
+#define ID_RSFL MKTAG('R','S','F','L') // ??? (system.dat only)
+#define ID_VIEW MKTAG('V','I','E','W') // Card Details
+#define ID_WDIB MKTAG('W','D','I','B') // LZ-Compressed Windows Bitmap
// Myst Masterpiece Edition Resource FourCC's (In addition to Myst FourCC's)
-#define ID_HELP MKID_BE('HELP') // Help Chunk
-#define ID_MJMP MKID_BE('MJMP') // MSND Jumps (To reduce MSND duplication)
-#define ID_PICT MKID_BE('PICT') // JPEG/PICT/WDIB Image
+#define ID_HELP MKTAG('H','E','L','P') // Help Chunk
+#define ID_MJMP MKTAG('M','J','M','P') // MSND Jumps (To reduce MSND duplication)
+#define ID_PICT MKTAG('P','I','C','T') // JPEG/PICT/WDIB Image
// Riven Resource FourCC's
-#define ID_BLST MKID_BE('BLST') // Card Hotspot Enabling Lists
-#define ID_CARD MKID_BE('CARD') // Card Scripts
-#define ID_FLST MKID_BE('FLST') // Card SFXE Lists
-#define ID_HSPT MKID_BE('HSPT') // Card Hotspots
-#define ID_MLST MKID_BE('MLST') // Card Movie Lists
-#define ID_NAME MKID_BE('NAME') // Object Names
-#define ID_PLST MKID_BE('PLST') // Card Picture Lists
-#define ID_RMAP MKID_BE('RMAP') // Card Codes
-#define ID_SFXE MKID_BE('SFXE') // Water Effect Animations
-#define ID_SLST MKID_BE('SLST') // Card Ambient Sound Lists
-#define ID_TMOV MKID_BE('tMOV') // QuickTime Movie
+#define ID_BLST MKTAG('B','L','S','T') // Card Hotspot Enabling Lists
+#define ID_CARD MKTAG('C','A','R','D') // Card Scripts
+#define ID_FLST MKTAG('F','L','S','T') // Card SFXE Lists
+#define ID_HSPT MKTAG('H','S','P','T') // Card Hotspots
+#define ID_MLST MKTAG('M','L','S','T') // Card Movie Lists
+#define ID_NAME MKTAG('N','A','M','E') // Object Names
+#define ID_PLST MKTAG('P','L','S','T') // Card Picture Lists
+#define ID_RMAP MKTAG('R','M','A','P') // Card Codes
+#define ID_SFXE MKTAG('S','F','X','E') // Water Effect Animations
+#define ID_SLST MKTAG('S','L','S','T') // Card Ambient Sound Lists
+#define ID_TMOV MKTAG('t','M','O','V') // QuickTime Movie
// Riven Saved Game FourCC's
-#define ID_VARS MKID_BE('VARS') // Variable Values
-#define ID_VERS MKID_BE('VERS') // Version Info
-#define ID_ZIPS MKID_BE('ZIPS') // Zip Mode Status
+#define ID_VARS MKTAG('V','A','R','S') // Variable Values
+#define ID_VERS MKTAG('V','E','R','S') // Version Info
+#define ID_ZIPS MKTAG('Z','I','P','S') // Zip Mode Status
// Zoombini Resource FourCC's
-#define ID_SND MKID_BE('\0SND') // Standard Mohawk Sound
-#define ID_CURS MKID_BE('CURS') // Cursor
-#define ID_SCRB MKID_BE('SCRB') // Feature Script
-#define ID_SCRS MKID_BE('SCRS') // Snoid Script
-#define ID_NODE MKID_BE('NODE') // Walk Node
-#define ID_PATH MKID_BE('PATH') // Walk Path
-#define ID_SHPL MKID_BE('SHPL') // Shape List
+#define ID_SND MKTAG( 0 ,'S','N','D') // Standard Mohawk Sound
+#define ID_CURS MKTAG('C','U','R','S') // Cursor
+#define ID_SCRB MKTAG('S','C','R','B') // Feature Script
+#define ID_SCRS MKTAG('S','C','R','S') // Snoid Script
+#define ID_NODE MKTAG('N','O','D','E') // Walk Node
+#define ID_PATH MKTAG('P','A','T','H') // Walk Path
+#define ID_SHPL MKTAG('S','H','P','L') // Shape List
// Living Books Resource FourCC's
-#define ID_TCUR MKID_BE('tCUR') // Cursor
-#define ID_BITL MKID_BE('BITL') // Book Item List
-#define ID_CTBL MKID_BE('CTBL') // Color Table
-#define ID_SCRP MKID_BE('SCRP') // Script
-#define ID_SPR MKID_BE('SPR#') // Sprite?
-#define ID_VRSN MKID_BE('VRSN') // Version
-#define ID_ANI MKID_BE('ANI ') // Animation
-#define ID_SHP MKID_BE('SHP#') // Shape
-#define ID_WAV MKID_BE('WAV ') // Old Sound Resource
-#define ID_BMAP MKID_BE('BMAP') // Old Mohawk Bitmap
-#define ID_BCOD MKID_BE('BCOD') // Book Code
+#define ID_TCUR MKTAG('t','C','U','R') // Cursor
+#define ID_BITL MKTAG('B','I','T','L') // Book Item List
+#define ID_CTBL MKTAG('C','T','B','L') // Color Table
+#define ID_SCRP MKTAG('S','C','R','P') // Script
+#define ID_SPR MKTAG('S','P','R','#') // Sprite?
+#define ID_VRSN MKTAG('V','R','S','N') // Version
+#define ID_ANI MKTAG('A','N','I',' ') // Animation
+#define ID_SHP MKTAG('S','H','P','#') // Shape
+#define ID_WAV MKTAG('W','A','V',' ') // Old Sound Resource
+#define ID_BMAP MKTAG('B','M','A','P') // Old Mohawk Bitmap
+#define ID_BCOD MKTAG('B','C','O','D') // Book Code
// JamesMath Resource FourCC's
-#define ID_TANM MKID_BE('tANM') // Animation?
-#define ID_TMFO MKID_BE('tMFO') // ???
+#define ID_TANM MKTAG('t','A','N','M') // Animation?
+#define ID_TMFO MKTAG('t','M','F','O') // ???
// CSTime Resource FourCC's
-#define ID_CINF MKID_BE('CINF') // Case Info
-#define ID_CONV MKID_BE('CONV') // Conversation
-#define ID_HOTS MKID_BE('HOTS') // Hotspot
-#define ID_INVO MKID_BE('INVO') // Inventory Object
-#define ID_QARS MKID_BE('QARS') // Question and Responses
-#define ID_SCEN MKID_BE('SCEN') // Scene
-#define ID_STRI MKID_BE('STRI') // String Entry?
+#define ID_CINF MKTAG('C','I','N','F') // Case Info
+#define ID_CONV MKTAG('C','O','N','V') // Conversation
+#define ID_HOTS MKTAG('H','O','T','S') // Hotspot
+#define ID_INVO MKTAG('I','N','V','O') // Inventory Object
+#define ID_QARS MKTAG('Q','A','R','S') // Question and Responses
+#define ID_SCEN MKTAG('S','C','E','N') // Scene
+#define ID_STRI MKTAG('S','T','R','I') // String Entry?
// Mohawk Wave Tags
-#define ID_WAVE MKID_BE('WAVE') // Game Sound (Third Tag)
-#define ID_ADPC MKID_BE('ADPC') // Game Sound Chunk
-#define ID_DATA MKID_BE('Data') // Game Sound Chunk
-#define ID_CUE MKID_BE('Cue#') // Game Sound Chunk
+#define ID_WAVE MKTAG('W','A','V','E') // Game Sound (Third Tag)
+#define ID_ADPC MKTAG('A','D','P','C') // Game Sound Chunk
+#define ID_DATA MKTAG('D','a','t','a') // Game Sound Chunk
+#define ID_CUE MKTAG('C','u','e','#') // Game Sound Chunk
// Mohawk MIDI Tags
-#define ID_MIDI MKID_BE('MIDI') // Game Sound (Third Tag), instead of WAVE
-#define ID_PRG MKID_BE('Prg#') // MIDI Patch
+#define ID_MIDI MKTAG('M','I','D','I') // Game Sound (Third Tag), instead of WAVE
+#define ID_PRG MKTAG('P','r','g','#') // MIDI Patch
// Common Resource FourCC's
-#define ID_TBMP MKID_BE('tBMP') // Standard Mohawk Bitmap
-#define ID_TWAV MKID_BE('tWAV') // Standard Mohawk Sound
-#define ID_TPAL MKID_BE('tPAL') // Standard Mohawk Palette
-#define ID_TCNT MKID_BE('tCNT') // Shape Count (CSWorld, CSAmtrak, JamesMath)
-#define ID_TSCR MKID_BE('tSCR') // Script (CSWorld, CSAmtrak, Treehouse)
-#define ID_STRL MKID_BE('STRL') // String List (Zoombini, CSWorld, CSAmtrak)
-#define ID_TBMH MKID_BE('tBMH') // Standard Mohawk Bitmap
-#define ID_TMID MKID_BE('tMID') // Standard Mohawk MIDI
-#define ID_REGS MKID_BE('REGS') // Registration Data - Shape Offsets (Zoombini, Treehouse)
-#define ID_BYTS MKID_BE('BYTS') // Byte Array? (Used as Database Entry in CSWorld, CSAmtrak)
-#define ID_INTS MKID_BE('INTS') // uint16 Array? (CSWorld, CSAmtrak)
-#define ID_BBOX MKID_BE('BBOX') // Boxes? (CSWorld, CSAmtrak)
-#define ID_SYSX MKID_BE('SYSX') // MIDI Sysex
+#define ID_TBMP MKTAG('t','B','M','P') // Standard Mohawk Bitmap
+#define ID_TWAV MKTAG('t','W','A','V') // Standard Mohawk Sound
+#define ID_TPAL MKTAG('t','P','A','L') // Standard Mohawk Palette
+#define ID_TCNT MKTAG('t','C','N','T') // Shape Count (CSWorld, CSAmtrak, JamesMath)
+#define ID_TSCR MKTAG('t','S','C','R') // Script (CSWorld, CSAmtrak, Treehouse)
+#define ID_STRL MKTAG('S','T','R','L') // String List (Zoombini, CSWorld, CSAmtrak)
+#define ID_TBMH MKTAG('t','B','M','H') // Standard Mohawk Bitmap
+#define ID_TMID MKTAG('t','M','I','D') // Standard Mohawk MIDI
+#define ID_REGS MKTAG('R','E','G','S') // Registration Data - Shape Offsets (Zoombini, Treehouse)
+#define ID_BYTS MKTAG('B','Y','T','S') // Byte Array? (Used as Database Entry in CSWorld, CSAmtrak)
+#define ID_INTS MKTAG('I','N','T','S') // uint16 Array? (CSWorld, CSAmtrak)
+#define ID_BBOX MKTAG('B','B','O','X') // Boxes? (CSWorld, CSAmtrak)
+#define ID_SYSX MKTAG('S','Y','S','X') // MIDI Sysex
struct FileTable {
uint32 offset;
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index abc7f5304e..3d496d0f38 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -57,9 +57,10 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_gameOver = false;
_activatedSLST = false;
_ignoreNextMouseUp = false;
- _extrasFile = NULL;
+ _extrasFile = 0;
_curStack = aspit;
- _hotspots = NULL;
+ _hotspots = 0;
+ removeTimer();
// NOTE: We can never really support CD swapping. All of the music files
// (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
@@ -89,7 +90,6 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete _extrasFile;
delete _saveLoad;
delete _scriptMan;
- delete[] _vars;
delete _optionsDialog;
delete _rnd;
delete[] _hotspots;
@@ -120,21 +120,44 @@ Common::Error MohawkEngine_Riven::run() {
_externalScriptHandler = new RivenExternal(this);
_optionsDialog = new RivenOptionsDialog(this);
_scriptMan = new RivenScriptManager(this);
- _cursor = new RivenCursorManager();
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "riven");
+ // Create the cursor manager
+ if (Common::File::exists("rivendmo.exe"))
+ _cursor = new PECursorManager("rivendmo.exe");
+ else if (Common::File::exists("riven.exe"))
+ _cursor = new PECursorManager("riven.exe");
+ else // last resort: try the Mac executable
+ _cursor = new MacCursorManager("Riven");
+
initVars();
+ // We need to have a cursor source, or the game won't work
+ if (!_cursor->hasSource()) {
+ Common::String message = "You're missing a Riven executable. The Windows executable is 'riven.exe' or 'rivendmo.exe'. ";
+ message += "Using the 'arcriven.z' installer file also works. In addition, you can use the Mac 'Riven' executable.";
+ GUIErrorMessage(message);
+ warning("%s", message.c_str());
+ return Common::kNoGameDataFoundError;
+ }
+
// Open extras.mhk for common images
_extrasFile = new MohawkArchive();
- if (!_extrasFile->open("extras.mhk"))
- error("Could not open extras.mhk");
+ // We need extras.mhk for inventory images, marble images, and credits images
+ if (!_extrasFile->open("extras.mhk")) {
+ Common::String message = "You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also works.";
+ GUIErrorMessage(message);
+ warning("%s", message.c_str());
+ return Common::kNoGameDataFoundError;
+ }
// Start at main cursor
_cursor->setCursor(kRivenMainCursor);
+ _cursor->showCursor();
+ _system->updateScreen();
// Let's begin, shall we?
if (getFeatures() & GF_DEMO) {
@@ -147,7 +170,12 @@ Common::Error MohawkEngine_Riven::run() {
Common::StringArray savedGamesList = _saveLoad->generateSaveGameList();
if (gameToLoad > savedGamesList.size())
error ("Could not find saved game");
- _saveLoad->loadGame(savedGamesList[gameToLoad]);
+
+ // Attempt to load the game. On failure, just send us to the main menu.
+ if (!_saveLoad->loadGame(savedGamesList[gameToLoad])) {
+ changeToStack(aspit);
+ changeToCard(1);
+ }
} else {
// Otherwise, start us off at aspit's card 1 (the main menu)
changeToStack(aspit);
@@ -162,12 +190,13 @@ Common::Error MohawkEngine_Riven::run() {
}
void MohawkEngine_Riven::handleEvents() {
- Common::Event event;
-
- // Update background videos and the water effect
+ // Update background running things
+ checkTimer();
bool needsUpdate = _gfx->runScheduledWaterEffects();
needsUpdate |= _video->updateMovies();
+ Common::Event event;
+
while (_eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
@@ -353,6 +382,9 @@ void MohawkEngine_Riven::changeToCard(uint16 dest) {
}
void MohawkEngine_Riven::refreshCard() {
+ // Clear any timer still floating around
+ removeTimer();
+
loadHotspots(_curCard);
_gfx->_updatesEnabled = true;
@@ -370,13 +402,15 @@ void MohawkEngine_Riven::refreshCard() {
if (!_activatedSLST)
_sound->playSLST(1, _curCard);
- if (_showHotspots) {
+ if (_showHotspots)
for (uint16 i = 0; i < _hotspotCount; i++)
_gfx->drawRect(_hotspots[i].rect, _hotspots[i].enabled);
- }
// Now we need to redraw the cursor if necessary and handle mouse over scripts
updateCurrentHotspot();
+
+ // Finally, install any hardcoded timer
+ installCardTimer();
}
void MohawkEngine_Riven::loadCard(uint16 id) {
@@ -455,7 +489,7 @@ void MohawkEngine_Riven::updateZipMode() {
for (uint32 i = 0; i < _hotspotCount; i++) {
if (_hotspots[i].zipModeHotspot) {
- if (*getVar("azip") != 0) {
+ if (_vars["azip"] != 0) {
// Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records.
Common::String hotspotName = getName(HotspotNames, _hotspots[i].name_resource);
@@ -488,10 +522,12 @@ void MohawkEngine_Riven::checkHotspotChange() {
if (_curHotspot != hotspotIndex) {
_curHotspot = hotspotIndex;
_cursor->setCursor(_hotspots[_curHotspot].mouse_cursor);
+ _system->updateScreen();
}
} else {
_curHotspot = -1;
_cursor->setCursor(kRivenMainCursor);
+ _system->updateScreen();
}
}
@@ -540,13 +576,13 @@ void MohawkEngine_Riven::checkInventoryClick() {
return;
// Set the return stack/card id's.
- *getVar("returnstackid") = _curStack;
- *getVar("returncardid") = _curCard;
+ _vars["returnstackid"] = _curStack;
+ _vars["returncardid"] = _curCard;
// See RivenGraphics::showInventory() for an explanation
// of the variables' meanings.
- bool hasCathBook = *getVar("acathbook") != 0;
- bool hasTrapBook = *getVar("atrapbook") != 0;
+ bool hasCathBook = _vars["acathbook"] != 0;
+ bool hasTrapBook = _vars["atrapbook"] != 0;
// Go to the book if a hotspot contains the mouse
if (!hasCathBook) {
@@ -719,6 +755,88 @@ Common::String MohawkEngine_Riven::getStackName(uint16 stack) const {
return rivenStackNames[stack];
}
+void MohawkEngine_Riven::installTimer(TimerProc proc, uint32 time) {
+ removeTimer();
+ _timerProc = proc;
+ _timerTime = time + getTotalPlayTime();
+}
+
+void MohawkEngine_Riven::checkTimer() {
+ if (!_timerProc)
+ return;
+
+ // NOTE: If the specified timer function is called, it is its job to remove the timer!
+ if (getTotalPlayTime() >= _timerTime) {
+ TimerProc proc = _timerProc;
+ proc(this);
+ }
+}
+
+void MohawkEngine_Riven::removeTimer() {
+ _timerProc = 0;
+ _timerTime = 0;
+}
+
+static void catherineIdleTimer(MohawkEngine_Riven *vm) {
+ uint32 &cathCheck = vm->_vars["pcathcheck"];
+ uint32 &cathState = vm->_vars["acathstate"];
+ uint16 movie;
+
+ // Choose a random movie based on where Catherine is
+ if (cathCheck == 0) {
+ static const int movieList[] = { 5, 6, 7, 8 };
+ cathCheck = 1;
+ movie = movieList[vm->_rnd->getRandomNumber(3)];
+ } else if (cathState == 1) {
+ static const int movieList[] = { 11, 14 };
+ movie = movieList[vm->_rnd->getRandomBit()];
+ } else {
+ static const int movieList[] = { 9, 10, 12, 13 };
+ movie = movieList[vm->_rnd->getRandomNumber(3)];
+ }
+
+ // Update her state if she moves from left/right or right/left, resp.
+ if (movie == 5 || movie == 7 || movie == 11 || movie == 14)
+ cathState = 2;
+ else
+ cathState = 1;
+
+ // Play the movie, blocking
+ vm->_video->activateMLST(movie, vm->getCurCard());
+ vm->_cursor->hideCursor();
+ vm->_video->playMovieBlockingRiven(movie);
+ vm->_cursor->showCursor();
+ vm->_system->updateScreen();
+
+ // Install the next timer for the next video
+ uint32 timeUntilNextMovie = vm->_rnd->getRandomNumber(120) * 1000;
+
+ vm->_vars["pcathtime"] = timeUntilNextMovie + vm->getTotalPlayTime();
+
+ vm->installTimer(&catherineIdleTimer, timeUntilNextMovie);
+}
+
+void MohawkEngine_Riven::installCardTimer() {
+ switch (getCurCardRMAP()) {
+ case 0x3a85: // Top of elevator on prison island
+ // Handle Catherine hardcoded videos
+ installTimer(&catherineIdleTimer, _rnd->getRandomNumberRng(1, 33) * 1000);
+ break;
+ case 0x77d6: // Sunners, top of stairs
+ // TODO: Background Sunner videos
+ break;
+ case 0x79bd: // Sunners, middle of stairs
+ // TODO: Background Sunner videos
+ break;
+ case 0x7beb: // Sunners, bottom of stairs
+ // TODO: Background Sunner videos
+ break;
+ case 0xb6ca: // Sunners, shoreline
+ // TODO: Background Sunner videos
+ break;
+ }
+}
+
bool ZipMode::operator== (const ZipMode &z) const {
return z.name == name && z.id == id;
}
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 60a31736d7..88927884a2 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -32,6 +32,8 @@
#include "gui/saveload.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
#include "common/random.h"
namespace Mohawk {
@@ -104,6 +106,8 @@ struct ZipMode {
bool operator== (const ZipMode& z) const;
};
+typedef Common::HashMap<Common::String, uint32, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> RivenVariableMap;
+
class MohawkEngine_Riven : public MohawkEngine {
protected:
Common::Error run();
@@ -127,6 +131,8 @@ public:
Common::Error saveGameState(int slot, const char *desc);
bool hasFeature(EngineFeature f) const;
+ typedef void (*TimerProc)(MohawkEngine_Riven *vm);
+
private:
MohawkArchive *_extrasFile; // We need a separate handle for the extra data
RivenConsole *_console;
@@ -149,8 +155,11 @@ private:
void checkHotspotChange();
// Variables
- uint32 *_vars;
- uint32 _varCount;
+ void initVars();
+
+ // Timer
+ TimerProc _timerProc;
+ uint32 _timerTime;
// Miscellaneous
bool _gameOver;
@@ -180,13 +189,9 @@ public:
Common::String getHotspotName(uint16 hotspot);
void updateCurrentHotspot();
- // Variable functions
- void initVars();
- uint32 getVarCount() const { return _varCount; }
- uint32 getGlobalVar(uint32 index);
- Common::String getGlobalVarName(uint32 index);
- uint32 *getLocalVar(uint32 index);
- uint32 *getVar(const Common::String &varName);
+ // Variables
+ RivenVariableMap _vars;
+ uint32 &getStackVar(uint32 index);
// Miscellaneous
void setGameOver() { _gameOver = true; }
@@ -195,6 +200,12 @@ public:
bool _activatedSLST;
void runLoadDialog();
void delayAndUpdate(uint32 ms);
+
+ // Timer
+ void installTimer(TimerProc proc, uint32 time);
+ void installCardTimer();
+ void checkTimer();
+ void removeTimer();
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_cursors.h b/engines/mohawk/riven_cursors.h
deleted file mode 100644
index 71cb8fd804..0000000000
--- a/engines/mohawk/riven_cursors.h
+++ /dev/null
@@ -1,670 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-namespace Mohawk {
-
-//////////////////////////////////////////////
-// Cursors and Cursor Palettes
-//////////////////////////////////////////////
-
-////////////////////////////////////////
-// Zip Mode Cursor (16x16):
-// Shown when a zip mode spot is active
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Yellow (0xDCFF00)
-////////////////////////////////////////
-static const byte s_zipModeCursor[] = {
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 2, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 1, 2, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
-};
-
-
-////////////////////////////////////////
-// Zip Mode Cursor Palette:
-// Palette For The Zip Mode Cursor
-////////////////////////////////////////
-static const byte s_zipModeCursorPalette[] = {
- 0x00, 0x00, 0x00, 0x00, // Black
- 0xDC, 0xFF, 0x00, 0x00, // Yellow
-};
-
-
-////////////////////////////////////////
-// Hand Over Object Cursor (16x16):
-// Shown when over a hotspot that's interactive
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_objectHandCursor[] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 0, 1, 2, 3, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 0, 0, 0,
- 0, 0, 1, 2, 3, 1, 1, 4, 3, 1, 2, 3, 1, 0, 1, 0,
- 0, 0, 0, 1, 2, 3, 1, 2, 3, 1, 4, 3, 1, 1, 2, 1,
- 0, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1,
- 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2, 3, 1, 2, 3, 1,
- 1, 2, 2, 1, 1, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 1,
- 1, 3, 4, 2, 1, 2, 4, 2, 2, 2, 2, 2, 4, 4, 1, 0,
- 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0,
- 0, 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 1, 0,
- 0, 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0,
- 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Grabbing Hand Cursor (13x13):
-// Shown when interacting with an object
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_grabbingHandCursor[] = {
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 2, 3, 1, 1, 1, 0, 0, 0,
- 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 0,
- 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 1,
- 0, 1, 1, 2, 2, 2, 4, 2, 4, 2, 2, 4, 1,
- 1, 2, 1, 2, 4, 2, 2, 2, 2, 2, 4, 4, 1,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1,
- 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 1,
- 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0,
- 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0,
- 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0,
- 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0,
- 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0
-};
-
-
-////////////////////////////////////////
-// Standard Hand Cursor (15x16):
-// Standard Cursor
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_standardHandCursor[] = {
- 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 3, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 1, 2, 4, 1, 1, 1, 1, 1, 0, 0,
- 1, 4, 2, 1, 0, 1, 2, 4, 1, 4, 1, 4, 1, 1, 1,
- 0, 1, 3, 2, 1, 1, 2, 4, 1, 4, 1, 4, 1, 4, 1,
- 0, 0, 1, 4, 2, 1, 2, 2, 4, 2, 4, 2, 1, 4, 1,
- 0, 0, 1, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1,
- 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Left Cursor (15x13):
-// Cursor When Over A Hotspot That Allows You To Move Left
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingLeftCursor[] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1,
- 1, 4, 2, 2, 2, 2, 1, 2, 3, 2, 2, 2, 4, 4, 4,
- 1, 4, 4, 4, 4, 4, 1, 2, 1, 3, 4, 2, 2, 2, 2,
- 0, 1, 1, 1, 1, 1, 1, 2, 1, 3, 3, 4, 2, 2, 2,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 1, 3, 4, 2, 2,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 4, 2, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 4, 2, 4,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Right Cursor (15x13):
-// Cursor When Over A Hotspot That Allows You To Move Right
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingRightCursor[] = {
- 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0,
- 1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
- 4, 4, 4, 2, 2, 2, 3, 2, 1, 4, 4, 4, 4, 4, 1,
- 2, 2, 2, 2, 4, 3, 1, 2, 1, 2, 2, 2, 2, 4, 1,
- 2, 2, 2, 4, 3, 3, 1, 2, 1, 1, 1, 1, 1, 1, 0,
- 2, 4, 4, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 2, 2, 4, 3, 1, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 2, 2, 4, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 4, 2, 4, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Down Cursor (Palm Up)(13x16):
-// Cursor When Over A Hotspot That Allows You To Move Down
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingDownCursorPalmUp[] = {
- 0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0,
- 0, 0, 1, 4, 2, 2, 4, 2, 2, 2, 4, 1, 0,
- 0, 1, 3, 4, 2, 2, 4, 4, 4, 4, 4, 1, 0,
- 0, 1, 4, 2, 2, 4, 3, 3, 3, 1, 1, 1, 1,
- 1, 2, 2, 2, 4, 3, 3, 1, 1, 2, 1, 2, 1,
- 1, 2, 2, 2, 3, 3, 3, 4, 1, 2, 1, 2, 1,
- 1, 2, 2, 3, 1, 1, 1, 2, 1, 2, 1, 2, 1,
- 1, 3, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1,
- 0, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1,
- 0, 0, 1, 2, 4, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Up Cursor (Palm Up)(13x16):
-// Cursor When Over A Hotspot That Allows You To Move Up
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingUpCursorPalmUp[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 2, 4, 1, 0, 0,
- 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 0,
- 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 3, 1,
- 1, 2, 1, 2, 1, 2, 1, 1, 1, 3, 2, 2, 1,
- 1, 2, 1, 2, 1, 4, 3, 3, 3, 2, 2, 2, 1,
- 1, 2, 1, 2, 1, 1, 3, 3, 4, 2, 2, 2, 1,
- 1, 1, 1, 1, 3, 3, 3, 4, 2, 2, 4, 1, 0,
- 0, 1, 4, 4, 4, 4, 4, 2, 2, 4, 3, 1, 0,
- 0, 1, 4, 2, 2, 2, 4, 2, 2, 4, 1, 0, 0,
- 0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Left Cursor (Bent)(15x13):
-// Cursor When Over A Hotspot That Allows You To Turn Left 180 Degrees
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingLeftCursorBent[] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1,
- 1, 3, 2, 4, 4, 2, 1, 2, 3, 3, 2, 2, 4, 4, 4,
- 1, 2, 4, 3, 3, 4, 1, 2, 1, 3, 4, 2, 2, 2, 2,
- 1, 4, 4, 1, 1, 1, 1, 2, 1, 1, 3, 4, 2, 2, 2,
- 1, 1, 1, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 1, 3, 4, 3, 2,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 4, 2, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 4, 2, 4,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Right Cursor (Bent)(15x13):
-// Cursor When Over A Hotspot That Allows You To Turn Right 180 Degrees
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingRightCursorBent[] = {
- 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0,
- 1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
- 4, 4, 4, 2, 2, 3, 3, 2, 1, 2, 4, 4, 2, 3, 1,
- 2, 2, 2, 2, 4, 3, 1, 2, 1, 4, 3, 3, 4, 2, 1,
- 2, 2, 2, 4, 3, 1, 1, 2, 1, 1, 1, 1, 4, 4, 1,
- 2, 4, 4, 3, 3, 3, 1, 1, 1, 1, 0, 0, 1, 1, 1,
- 2, 3, 4, 3, 1, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 2, 2, 4, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 4, 2, 4, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Down Cursor (Palm Down)(15x16):
-// Similar to Standard Cursor
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingDownCursorPalmDown[] = {
- 0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 1, 3, 4, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 1, 3, 4, 2, 2, 2, 2, 2, 2, 2, 4, 1, 0, 0, 0,
- 1, 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 4, 1, 0, 0,
- 1, 4, 1, 2, 2, 3, 2, 3, 2, 1, 2, 4, 1, 0, 0,
- 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 1, 2, 3, 1, 0,
- 0, 1, 1, 4, 1, 4, 1, 4, 2, 1, 0, 1, 2, 4, 1,
- 0, 0, 1, 1, 1, 1, 1, 4, 2, 1, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 3, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Hand Cursor Palette:
-// Palette For All Hand Cursors
-////////////////////////////////////////
-static const byte s_handCursorPalette[] = {
- 0x00, 0x00, 0x00, 0x00, // Black
- 0xED, 0xCD, 0x96, 0x00, // Light Peach
- 0x8A, 0x67, 0x2F, 0x00, // Brown
- 0xE8, 0x9A, 0x62, 0x00 // Dark Peach
-};
-
-
-////////////////////////////////////////
-// Pellet Cursor (8x8):
-// Cursor When Using The Pellet In The Frog Trap
-//
-// 0 = Transparent
-// 1 = Light Olive Green (0x5D6730)
-// 2 = Maroon (0x5E3333)
-// 3 = Light Gray (0x555555)
-// 4 = Medium Gray (0x444444)
-// 5 = Dark Gray (0x333333)
-// 6 = Dark Green (0x2D3300)
-// 7 = Darkest Gray (0x222222)
-////////////////////////////////////////
-static const byte s_pelletCursor[] = {
- 0, 0, 1, 1, 2, 3, 0, 0,
- 0, 2, 1, 4, 1, 2, 5, 0,
- 4, 1, 4, 1, 2, 1, 5, 4,
- 4, 2, 1, 2, 1, 1, 2, 6,
- 6, 4, 2, 1, 4, 4, 1, 5,
- 5, 6, 5, 2, 1, 2, 4, 4,
- 0, 7, 5, 5, 4, 2, 5, 0,
- 0, 0, 5, 6, 6, 5, 0, 0
-};
-
-////////////////////////////////////////
-// Pellet Cursor Palette:
-// Palette For The Pellet Cursor
-////////////////////////////////////////
-static const byte s_pelletCursorPalette[] = {
- 0x5D, 0x67, 0x30, 0x00,
- 0x5E, 0x33, 0x33, 0x00,
- 0x55, 0x55, 0x55, 0x00,
- 0x44, 0x44, 0x44, 0x00,
- 0x33, 0x33, 0x33, 0x00,
- 0x2D, 0x33, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x00
-};
-
-////////////////////////////////////////
-// Red Marble Cursor (12x12):
-// Cursor When Holding The Red Marble
-////////////////////////////////////////
-static const byte s_redMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 2, 5, 2, 2, 2, 2, 0, 0,
- 0, 6, 1, 1, 2, 2, 5, 2, 2, 2, 2, 0,
- 0, 6, 3, 4, 5, 2, 2, 7, 8, 5, 2, 0,
- 9, 6, 10,11,2, 2, 2, 12,13,2, 2, 2,
- 14,10,6, 4, 1, 2, 8, 2, 2, 5, 2, 2,
- 15,16,6, 3, 1, 2, 2, 2, 2, 2, 2, 5,
- 17,9,18, 3, 4, 4, 4, 5, 2, 5, 1, 2,
- 0, 16,9, 6, 6, 19,1, 20,1, 4, 11,0,
- 0, 17,15,18,9, 10,6, 10,3, 21,4, 0,
- 0, 0, 18,15,9, 18,6, 22,10,23,0, 0,
- 0, 0, 0, 0, 15,15,16,9, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Red Marble Cursor Palette:
-// Palette For The Red Marble Cursor
-////////////////////////////////////////
-static const byte s_redMarbleCursorPalette[] = {
- 0xb8, 0x33, 0x32, 0x00,
- 0xe5, 0x33, 0x31, 0x00,
- 0x98, 0x06, 0x00, 0x00,
- 0xb8, 0x00, 0x34, 0x00,
- 0xe6, 0x00, 0x34, 0x00,
- 0x7a, 0x04, 0x00, 0x00,
- 0xe8, 0x9a, 0x62, 0x00,
- 0xea, 0x31, 0x67, 0x00,
- 0x6a, 0x03, 0x00, 0x00,
- 0x8c, 0x00, 0x35, 0x00,
- 0xb6, 0x36, 0x00, 0x00,
- 0xed, 0xcd, 0x96, 0x00,
- 0xe9, 0x66, 0x65, 0x00,
- 0x5b, 0x35, 0x00, 0x00,
- 0x5b, 0x02, 0x00, 0x00,
- 0x5f, 0x00, 0x35, 0x00,
- 0x4c, 0x01, 0x00, 0x00,
- 0x5e, 0x33, 0x33, 0x00,
- 0x89, 0x05, 0x00, 0x00,
- 0xb6, 0x08, 0x00, 0x00,
- 0xa7, 0x07, 0x00, 0x00,
- 0x88, 0x36, 0x00, 0x00,
- 0x8b, 0x33, 0x33, 0x00
-};
-
-////////////////////////////////////////
-// Orange Marble Cursor (12x12):
-// Cursor When Holding The Orange Marble
-////////////////////////////////////////
-static const byte s_orangeMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 2, 3, 0, 0, 0, 0,
- 0, 0, 4, 5, 2, 2, 3, 3, 3, 3, 0, 0,
- 0, 6, 7, 4, 2, 1, 2, 2, 3, 3, 3, 0,
- 0, 6, 6, 7, 1, 2, 3, 8, 9, 2, 10,0,
- 11,12,7, 4, 2, 3, 3, 13,9, 2, 2, 1,
- 14,15,6, 4, 2, 16,3, 3, 2, 1, 1, 1,
- 14,14,12,17,4, 2, 2, 1, 2, 1, 2, 1,
- 14,18,12,6, 4, 4, 4, 19,2, 19,20,4,
- 0, 14,14,15,6, 15,6, 4, 4, 4, 4, 0,
- 0, 14,11,14,14,12,12,12,17,6, 17,0,
- 0, 0, 14,14,17,14,17,6, 6, 17,0, 0,
- 0, 0, 0, 0, 14,11,14,11,0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Orange Marble Cursor Palette:
-// Palette For The Orange Marble Cursor
-////////////////////////////////////////
-static const byte s_orangeMarbleCursorPalette[] = {
- 0xe1, 0x9e, 0x00, 0x00,
- 0xe3, 0x9b, 0x28, 0x00,
- 0xe2, 0xcf, 0x20, 0x00,
- 0xb5, 0x6a, 0x00, 0x00,
- 0xb6, 0x9b, 0x29, 0x00,
- 0x87, 0x69, 0x00, 0x00,
- 0xb7, 0x67, 0x2f, 0x00,
- 0xe9, 0xff, 0x93, 0x00,
- 0xe1, 0xff, 0x5a, 0x00,
- 0xe0, 0xd0, 0x00, 0x00,
- 0x5e, 0x33, 0x33, 0x00,
- 0x88, 0x36, 0x00, 0x00,
- 0xf3, 0xff, 0xc9, 0x00,
- 0x5b, 0x35, 0x00, 0x00,
- 0x8b, 0x33, 0x33, 0x00,
- 0xe6, 0xce, 0x5f, 0x00,
- 0x8a, 0x67, 0x2f, 0x00,
- 0x5d, 0x67, 0x30, 0x00,
- 0xe2, 0x6a, 0x00, 0x00,
- 0xb3, 0x9d, 0x00, 0x00
-};
-
-////////////////////////////////////////
-// Yellow Marble Cursor (12x12):
-// Cursor When Holding The Yellow Marble
-////////////////////////////////////////
-static const byte s_yellowMarbleCursor[] = {
- 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 1, 1, 1, 5, 6, 6, 0, 0,
- 0, 3, 3, 7, 1, 1, 1, 1, 2, 1, 6, 0,
- 0, 3, 3, 3, 3, 1, 1, 8, 6, 1, 6, 0,
- 9, 9, 3, 3, 1, 1, 2, 10,8, 1, 1, 2,
- 11,9, 3, 3, 1, 1, 1, 1, 1, 1, 5, 1,
- 9, 9, 12,3, 3, 1, 1, 1, 1, 1, 1, 1,
- 9, 9, 9, 3, 3, 3, 3, 3, 1, 1, 1, 1,
- 0, 11,9, 9, 12,3, 3, 3, 3, 3, 3, 0,
- 0, 9, 9, 13,9, 14,12,3, 3, 3, 3, 0,
- 0, 0, 9, 9, 9, 12,14,3, 13,3, 0, 0,
- 0, 0, 0, 0, 11,9, 11,9, 0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Yellow Marble Cursor Palette:
-// Palette For The Yellow Marble Cursor
-////////////////////////////////////////
-static const byte s_yellowMarbleCursorPalette[] = {
- 0xb3, 0xd0, 0x00, 0x00,
- 0xb0, 0xff, 0x00, 0x00,
- 0x86, 0x9c, 0x00, 0x00,
- 0x87, 0xd0, 0x00, 0x00,
- 0xe0, 0xd0, 0x00, 0x00,
- 0xdc, 0xff, 0x00, 0x00,
- 0xb3, 0x9d, 0x00, 0x00,
- 0xdc, 0xff, 0x11, 0x00,
- 0x5a, 0x68, 0x00, 0x00,
- 0xe1, 0xff, 0x5a, 0x00,
- 0x5d, 0x67, 0x30, 0x00,
- 0x87, 0x69, 0x00, 0x00,
- 0x88, 0x9b, 0x2a, 0x00,
- 0x5a, 0x9c, 0x00, 0x00
-};
-
-////////////////////////////////////////
-// Green Marble Cursor (12x12):
-// Cursor When Holding The Green Marble
-////////////////////////////////////////
-static const byte s_greenMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0,
- 0, 0, 4, 5, 2, 1, 2, 3, 6, 6, 0, 0,
- 0, 7, 5, 8, 8, 1, 1, 2, 3, 6, 6, 0,
- 0, 7, 7, 4, 8, 1, 2, 9, 6, 2, 6, 0,
- 10,7, 7, 4, 1, 2, 3, 11,12,2, 2, 3,
- 13,13,7, 4, 1, 2, 3, 2, 1, 2, 2, 3,
- 14,13,7, 7, 5, 1, 1, 8, 2, 1, 1, 2,
- 15,16,13,7, 4, 4, 5, 5, 1, 8, 1, 1,
- 0, 15,13,7, 7, 7, 4, 4, 4, 5, 8, 0,
- 0, 14,16,15,13, 7, 7, 7, 4,17,5, 0,
- 0, 0, 10,16,13,13,13,17,18,17,0, 0,
- 0, 0, 0, 0, 15,10,19,10,0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Green Marble Cursor Palette:
-// Palette For The Green Marble Cursor
-////////////////////////////////////////
-static const byte s_greenMarbleCursorPalette[] = {
- 0x0e, 0xd0, 0x00, 0x00,
- 0x0f, 0xe1, 0x00, 0x00,
- 0x10, 0xf2, 0x00, 0x00,
- 0x0b, 0x9c, 0x00, 0x00,
- 0x0c, 0xad, 0x00, 0x00,
- 0x11, 0xff, 0x00, 0x00,
- 0x09, 0x8a, 0x00, 0x00,
- 0x0d, 0xbe, 0x00, 0x00,
- 0x30, 0xff, 0x5a, 0x00,
- 0x0d, 0x67, 0x30, 0x00,
- 0x6b, 0xff, 0x92, 0x00,
- 0x00, 0xff, 0x28, 0x00,
- 0x08, 0x79, 0x00, 0x00,
- 0x05, 0x57, 0x00, 0x00,
- 0x30, 0x67, 0x30, 0x00,
- 0x06, 0x68, 0x00, 0x00,
- 0x00, 0x9b, 0x2c, 0x00,
- 0x2e, 0x9c, 0x00, 0x00,
- 0x2e, 0x68, 0x00, 0x00
-};
-
-////////////////////////////////////////
-// Blue Marble Cursor (12x12):
-// Cursor When Holding The Blue Marble
-////////////////////////////////////////
-static const byte s_blueMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0,
- 0, 0, 4, 5, 2, 2, 6, 3, 7, 3, 0, 0,
- 0, 8, 9, 5, 10,11,2, 6, 3, 3, 7, 0,
- 0, 12,13,9, 10,11,6, 14,7, 6, 3, 0,
- 15,8, 4, 13,2, 6, 3, 16,17,6, 6, 3,
- 18,15,19,13,10,7, 3, 6, 2, 2, 6, 7,
- 20,8, 18,4, 21,11,2, 10,6, 2, 2, 2,
- 15,15,18,8, 13,9, 21,5, 11,10,2, 1,
- 0, 8, 15,19,15,13,13,21,21,5, 9, 0,
- 0, 22,20,15, 8,19,15,19,4, 9, 4, 0,
- 0, 0, 15,20,15,15,19,15,9, 15,0, 0,
- 0, 0, 0, 0, 20,15, 8,15,0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Blue Marble Cursor Palette:
-// Palette For The Blue Marble Cursor
-////////////////////////////////////////
-static const byte s_blueMarbleCursorPalette[] = {
- 0x6b, 0x00, 0xd2, 0x00,
- 0x66, 0x00, 0xe3, 0x00,
- 0x72, 0x00, 0xff, 0x00,
- 0x53, 0x2d, 0x9d, 0x00,
- 0x4e, 0x00, 0xaf, 0x00,
- 0x6d, 0x00, 0xf5, 0x00,
- 0x7d, 0x00, 0xff, 0x00,
- 0x44, 0x00, 0x69, 0x00,
- 0x56, 0x00, 0x9d, 0x00,
- 0x56, 0x00, 0xc0, 0x00,
- 0x5e, 0x00, 0xd2, 0x00,
- 0x2b, 0x31, 0x68, 0x00,
- 0x3f, 0x00, 0x8c, 0x00,
- 0x91, 0x22, 0xff, 0x00,
- 0x41, 0x31, 0x68, 0x00,
- 0xd7, 0x95, 0xff, 0x00,
- 0x77, 0x22, 0xff, 0x00,
- 0x2f, 0x00, 0x69, 0x00,
- 0x37, 0x00, 0x7a, 0x00,
- 0x27, 0x00, 0x58, 0x00,
- 0x46, 0x00, 0x9d, 0x00,
- 0x33, 0x33, 0x33, 0x00
-};
-
-////////////////////////////////////////
-// Violet Marble Cursor (12x12):
-// Cursor When Holding The Violet Marble
-////////////////////////////////////////
-static const byte s_violetMarbleCursor[] = {
- 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0,
- 0, 0, 3, 3, 1, 1, 1, 4, 2, 4, 0, 0,
- 0, 3, 3, 3, 1, 5, 1, 1, 4, 2, 4, 0,
- 0, 3, 3, 3, 3, 1, 1, 6, 4, 1, 2, 0,
- 3, 7, 8, 3, 1, 1, 4, 9, 4, 1, 1, 4,
- 8, 7, 8, 3, 10,4, 1, 1, 1, 1, 4, 1,
- 8, 3, 8, 7, 3, 1, 1, 5, 1, 1, 1, 1,
- 7, 7, 11,3, 3, 3, 3, 3, 1, 3, 1, 1,
- 0, 8, 7, 7, 8, 8, 7, 3, 3, 3, 1, 0,
- 0, 7, 8, 3, 11,7, 3, 11,3, 10,3, 0,
- 0, 0, 8, 7, 3, 3, 7, 3, 3, 3, 0, 0,
- 0, 0, 0, 0, 8, 7, 11,3, 0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Violet Marble Cursor Palette:
-// Palette For The Violet Marble Cursor
-////////////////////////////////////////
-static const byte s_violetMarbleCursorPalette[] = {
- 0xaa, 0x00, 0xd1, 0x00,
- 0xd8, 0x00, 0xff, 0x00,
- 0x76, 0x00, 0x9d, 0x00,
- 0xb5, 0x00, 0xff, 0x00,
- 0x87, 0x00, 0xd2, 0x00,
- 0xd7, 0x22, 0xff, 0x00,
- 0x68, 0x00, 0x69, 0x00,
- 0x44, 0x00, 0x69, 0x00,
- 0xd7, 0x5e, 0xff, 0x00,
- 0x9c, 0x00, 0x9d, 0x00,
- 0x56, 0x00, 0x9d, 0x00
-};
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index a82af4614b..7c453dec48 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -216,20 +216,37 @@ void RivenExternal::runDemoBoundaryDialog() {
dialog.runModal();
}
-void RivenExternal::runEndGame(uint16 video) {
+void RivenExternal::runEndGame(uint16 video, uint32 delay) {
_vm->_sound->stopAllSLST();
_vm->_video->playMovieRiven(video);
- runCredits(video);
+ runCredits(video, delay);
}
-void RivenExternal::runCredits(uint16 video) {
- // TODO: Play until the last frame and then run the credits
+void RivenExternal::runCredits(uint16 video, uint32 delay) {
+ // Initialize our credits state
+ _vm->_cursor->hideCursor();
+ _vm->_gfx->beginCredits();
+ uint nextCreditsFrameStart = 0;
VideoHandle videoHandle = _vm->_video->findVideoHandleRiven(video);
- while (!_vm->_video->endOfVideo(videoHandle) && !_vm->shouldQuit()) {
- if (_vm->_video->updateMovies())
- _vm->_system->updateScreen();
+ while (!_vm->shouldQuit() && _vm->_gfx->getCurCreditsImage() <= 320) {
+ if (_vm->_video->getCurFrame(videoHandle) >= (int32)_vm->_video->getFrameCount(videoHandle) - 1) {
+ if (nextCreditsFrameStart == 0) {
+ // Set us up to start after delay ms
+ nextCreditsFrameStart = _vm->_system->getMillis() + delay;
+ } else if (_vm->_system->getMillis() >= nextCreditsFrameStart) {
+ // the first two frames stay on for 5 seconds
+ // the rest of the scroll updates happen at 30Hz
+ if (_vm->_gfx->getCurCreditsImage() < 304)
+ nextCreditsFrameStart = _vm->_system->getMillis() + 5000;
+ else
+ nextCreditsFrameStart = _vm->_system->getMillis() + 1000 / 30;
+
+ _vm->_gfx->updateCredits();
+ }
+ } else if (_vm->_video->updateMovies())
+ _vm->_system->updateScreen();
Common::Event event;
while (_vm->_system->getEventManager()->pollEvent(event))
@@ -259,7 +276,7 @@ void RivenExternal::runDomeCheck() {
// frame that is the magic one is the one with the golden symbol) but we
// give a 3 frame leeway in either direction.
if (frameCount - curFrame < 3 || curFrame < 3)
- *_vm->getVar("domecheck") = 1;
+ _vm->_vars["domecheck"] = 1;
}
void RivenExternal::resetDomeSliders(uint16 soundId, uint16 startHotspot) {
@@ -297,7 +314,7 @@ void RivenExternal::resetDomeSliders(uint16 soundId, uint16 startHotspot) {
void RivenExternal::checkDomeSliders(uint16 resetSlidersHotspot, uint16 openDomeHotspot) {
// Let's see if we're all matched up...
- if (*_vm->getVar("adomecombo") == _sliderState) {
+ if (_vm->_vars["adomecombo"] == _sliderState) {
// Set the button hotspot to the open dome hotspot
_vm->_hotspots[resetSlidersHotspot].enabled = false;
_vm->_hotspots[openDomeHotspot].enabled = true;
@@ -316,6 +333,7 @@ void RivenExternal::checkSliderCursorChange(uint16 startHotspot) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
else
_vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
break;
}
}
@@ -341,6 +359,7 @@ void RivenExternal::dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, u
// We've clicked down, so show the closed hand cursor
_vm->_cursor->setCursor(kRivenClosedHandCursor);
+ _vm->_system->updateScreen();
bool done = false;
while (!done) {
@@ -427,7 +446,7 @@ void RivenExternal::xasetupcomplete(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->getVar("aatruspage");
+ uint32 &page = _vm->_vars["aatruspage"];
// Set hotspots depending on the page
if (page == 1) {
@@ -446,18 +465,18 @@ void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- _vm->changeToStack(*_vm->getVar("returnstackid"));
- _vm->changeToCard(*_vm->getVar("returncardid"));
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
}
void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("aatruspage");
+ uint32 &page = _vm->_vars["aatruspage"];
// Decrement the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
if (_vm->getFeatures() & GF_DEMO)
@@ -472,12 +491,12 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("aatruspage");
+ uint32 &page = _vm->_vars["aatruspage"];
// Increment the page if it's not the last page
- if (((_vm->getFeatures() & GF_DEMO) && *page == 6) || *page == 10)
+ if (((_vm->getFeatures() & GF_DEMO) && page == 6) || page == 10)
return;
- (*page)++;
+ page++;
// Play the page turning sound
if (_vm->getFeatures() & GF_DEMO)
@@ -492,7 +511,7 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->getVar("acathpage");
+ uint32 page = _vm->_vars["acathpage"];
// Set hotspots depending on the page
if (page == 1) {
@@ -518,7 +537,7 @@ void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
// Draw the telescope combination
// The images for the numbers are tBMP's 13 through 17.
// The start point is at (156, 247)
- uint32 teleCombo = *_vm->getVar("tcorrectorder");
+ uint32 teleCombo = _vm->_vars["tcorrectorder"];
static const uint16 kNumberWidth = 32;
static const uint16 kNumberHeight = 25;
static const uint16 kDstX = 156;
@@ -535,18 +554,18 @@ void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xacathbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- _vm->changeToStack(*_vm->getVar("returnstackid"));
- _vm->changeToCard(*_vm->getVar("returncardid"));
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
}
void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 *page = _vm->getVar("acathpage");
+ uint32 &page = _vm->_vars["acathpage"];
// Increment the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
_vm->_sound->playSound(5);
@@ -558,12 +577,12 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 *page = _vm->getVar("acathpage");
+ uint32 &page = _vm->_vars["acathpage"];
// Increment the page if it's not the last page
- if (*page == 49)
+ if (page == 49)
return;
- (*page)++;
+ page++;
// Play the page turning sound
_vm->_sound->playSound(6);
@@ -575,14 +594,14 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- *_vm->getVar("atrap") = 0;
- _vm->changeToStack(*_vm->getVar("returnstackid"));
- _vm->changeToCard(*_vm->getVar("returncardid"));
+ _vm->_vars["atrap"] = 0;
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
}
void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
// Close the trap book
- *_vm->getVar("atrap") = 0;
+ _vm->_vars["atrap"] = 0;
// Play the page turning sound
_vm->_sound->playSound(8);
@@ -592,7 +611,7 @@ void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) {
// Open the trap book
- *_vm->getVar("atrap") = 1;
+ _vm->_vars["atrap"] = 1;
// Play the page turning sound
_vm->_sound->playSound(9);
@@ -686,7 +705,7 @@ void RivenExternal::xaexittomain(uint16 argc, uint16 *argv) {
void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->getVar("blabbook");
+ uint32 page = _vm->_vars["blabpage"];
// Draw the image of the page based on the blabbook variable
_vm->_gfx->drawPLST(page);
@@ -695,7 +714,7 @@ void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
// Draw the dome combination
// The images for the numbers are tBMP's 364 through 368
// The start point is at (240, 82)
- uint32 domeCombo = *_vm->getVar("adomecombo");
+ uint32 domeCombo = _vm->_vars["adomecombo"];
static const uint16 kNumberWidth = 32;
static const uint16 kNumberHeight = 24;
static const uint16 kDstX = 240;
@@ -718,12 +737,12 @@ void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("blabbook");
+ uint32 &page = _vm->_vars["blabpage"];
// Decrement the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
_vm->_sound->playSound(22);
@@ -735,12 +754,12 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("blabbook");
+ uint32 &page = _vm->_vars["blabpage"];
// Increment the page if it's not the last page
- if (*page == 22)
+ if (page == 22)
return;
- (*page)++;
+ page++;
// Play the page turning sound
_vm->_sound->playSound(23);
@@ -751,21 +770,18 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
}
void RivenExternal::xsoundplug(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->getVar("bheat");
- uint32 boilerInactive = *_vm->getVar("bcratergg");
-
- if (heat != 0)
+ if (_vm->_vars["bheat"] != 0)
_vm->_sound->playSLST(1, _vm->getCurCard());
- else if (boilerInactive != 0)
+ else if (_vm->_vars["bcratergg"] != 0)
_vm->_sound->playSLST(2, _vm->getCurCard());
else
_vm->_sound->playSLST(3, _vm->getCurCard());
}
void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->getVar("bheat");
- uint32 water = *_vm->getVar("bblrwtr");
- uint32 platform = *_vm->getVar("bblrgrt");
+ uint32 heat = _vm->_vars["bheat"];
+ uint32 water = _vm->_vars["bblrwtr"];
+ uint32 platform = _vm->_vars["bblrgrt"];
// Stop any background videos
_vm->_video->stopVideos();
@@ -834,11 +850,8 @@ void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->getVar("bheat");
- uint32 platform = *_vm->getVar("bblrgrt");
-
- if (heat) {
- if (platform == 0) {
+ if (_vm->_vars["bheat"] != 0) {
+ if (_vm->_vars["bblrgrt"] == 0) {
_vm->_video->activateMLST(8, _vm->getCurCard());
_vm->_video->playMovieRiven(8);
} else {
@@ -851,17 +864,63 @@ void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
}
}
+static void ytramTrapTimer(MohawkEngine_Riven *vm) {
+ // Remove this timer
+ vm->removeTimer();
+
+ // Check if we've caught a Ytram
+ vm->_externalScriptHandler->checkYtramCatch(true);
+}
+
void RivenExternal::xbsettrap(uint16 argc, uint16 *argv) {
- // TODO: Set the Ytram trap
+ // Set the Ytram trap
+
+ // We can catch the Ytram between 10 seconds and 3 minutes from now
+ uint32 timeUntilCatch = _vm->_rnd->getRandomNumberRng(10, 60 * 3) * 1000;
+ _vm->_vars["bytramtime"] = timeUntilCatch + _vm->getTotalPlayTime();
+
+ // And set the timer too
+ _vm->installTimer(&ytramTrapTimer, timeUntilCatch);
+}
+
+void RivenExternal::checkYtramCatch(bool playSound) {
+ // Check if we've caught a Ytram
+
+ uint32 &ytramTime = _vm->_vars["bytramtime"];
+
+ // If the trap still has not gone off, reinstall our timer
+ // This is in case you set the trap, walked away, and returned
+ if (_vm->getTotalPlayTime() < ytramTime) {
+ _vm->installTimer(&ytramTrapTimer, ytramTime - _vm->getTotalPlayTime());
+ return;
+ }
+
+ // Increment the movie per catch (max = 3)
+ uint32 &ytramMovie = _vm->_vars["bytram"];
+ ytramMovie++;
+ if (ytramMovie > 3)
+ ytramMovie = 3;
+
+ // Reset variables
+ _vm->_vars["bytrapped"] = 1;
+ _vm->_vars["bbait"] = 0;
+ _vm->_vars["bytrap"] = 0;
+ ytramTime = 0;
+
+ // Play the capture sound, if requested
+ if (playSound)
+ _vm->_sound->playSound(33);
}
void RivenExternal::xbcheckcatch(uint16 argc, uint16 *argv) {
- // TODO: Check if we've caught a Ytram
+ // Just pass our parameter along...
+ checkYtramCatch(argv[0] != 0);
}
void RivenExternal::xbait(uint16 argc, uint16 *argv) {
// Set the cursor to the pellet
_vm->_cursor->setCursor(kRivenPelletCursor);
+ _vm->_system->updateScreen();
// Loop until the player lets go (or quits)
Common::Event event;
@@ -881,10 +940,11 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) {
// Set back the cursor
_vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
// Set the bait if we put it on the plate
if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *_vm->getVar("bbait") = 1;
+ _vm->_vars["bbait"] = 1;
_vm->_gfx->drawPLST(4);
_vm->_gfx->updateScreen();
_vm->_hotspots[3].enabled = false; // Disable bait hotspot
@@ -893,14 +953,35 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbfreeytram(uint16 argc, uint16 *argv) {
- // TODO: Play a random Ytram movie
+ // Play a random Ytram movie after freeing it
+ uint16 mlstId;
+
+ switch (_vm->_vars["bytram"]) {
+ case 1:
+ mlstId = 11;
+ break;
+ case 2:
+ mlstId = 12;
+ break;
+ default:
+ mlstId = _vm->_rnd->getRandomNumberRng(13, 15);
+ break;
+ }
+
+ // Activate the MLST and play the video
+ _vm->_video->activateMLST(mlstId, _vm->getCurCard());
+ _vm->_video->playMovieBlockingRiven(11);
+
+ // Now play the second movie
+ _vm->_video->activateMLST(mlstId + 5, _vm->getCurCard());
+ _vm->_video->playMovieBlockingRiven(12);
}
void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) {
// Remove the pellet from the plate and put it in your hand
_vm->_gfx->drawPLST(3);
- _vm->_gfx->updateScreen();
_vm->_cursor->setCursor(kRivenPelletCursor);
+ _vm->_gfx->updateScreen();
// Loop until the player lets go (or quits)
Common::Event event;
@@ -920,16 +1001,17 @@ void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) {
// Set back the cursor
_vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
// Set the bait if we put it on the plate, remove otherwise
if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *_vm->getVar("bbait") = 1;
+ _vm->_vars["bbait"] = 1;
_vm->_gfx->drawPLST(4);
_vm->_gfx->updateScreen();
_vm->_hotspots[3].enabled = false; // Disable bait hotspot
_vm->_hotspots[9].enabled = true; // Enable baitplate hotspot
} else {
- *_vm->getVar("bbait") = 0;
+ _vm->_vars["bbait"] = 0;
_vm->_hotspots[3].enabled = true; // Enable bait hotspot
_vm->_hotspots[9].enabled = false; // Disable baitplate hotspot
}
@@ -963,7 +1045,7 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
// Get the variable for the valve
- uint32 *valve = _vm->getVar("bvalve");
+ uint32 &valve = _vm->_vars["bvalve"];
int changeX = 0;
int changeY = 0;
@@ -985,26 +1067,30 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
break;
case Common::EVENT_LBUTTONUP:
// FIXME: These values for changes in x/y could be tweaked.
- if (*valve == 0 && changeY <= -10) {
- *valve = 1;
+ if (valve == 0 && changeY <= -10) {
+ valve = 1;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(2);
_vm->refreshCard();
- } else if (*valve == 1) {
+ } else if (valve == 1) {
if (changeX >= 0 && changeY >= 10) {
- *valve = 0;
+ valve = 0;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(3);
_vm->refreshCard();
} else if (changeX <= -10 && changeY <= 10) {
- *valve = 2;
+ valve = 2;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(1);
_vm->refreshCard();
}
- } else if (*valve == 2 && changeX >= 10) {
- *valve = 1;
+ } else if (valve == 2 && changeX >= 10) {
+ valve = 1;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(4);
_vm->refreshCard();
}
@@ -1018,27 +1104,27 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// If we changed state and the new state is that the valve is flowing to
// the boiler, we need to update the boiler state.
- if (*valve == 1) {
- if (*_vm->getVar("bidvlv") == 1) { // Check which way the water is going at the boiler
- if (*_vm->getVar("bblrarm") == 1) {
+ if (valve == 1) {
+ if (_vm->_vars["bidvlv"] == 1) { // Check which way the water is going at the boiler
+ if (_vm->_vars["bblrarm"] == 1) {
// If the pipe is open, make sure the water is drained out
- *_vm->getVar("bheat") = 0;
- *_vm->getVar("bblrwtr") = 0;
+ _vm->_vars["bheat"] = 0;
+ _vm->_vars["bblrwtr"] = 0;
} else {
// If the pipe is closed, fill the boiler again
- *_vm->getVar("bheat") = *_vm->getVar("bblrvalve");
- *_vm->getVar("bblrwtr") = 1;
+ _vm->_vars["bheat"] = _vm->_vars["bblrvalve"];
+ _vm->_vars["bblrwtr"] = 1;
}
} else {
// Have the grating inside the boiler match the switch outside
- *_vm->getVar("bblrgrt") = (*_vm->getVar("bblrsw") == 1) ? 0 : 1;
+ _vm->_vars["bblrgrt"] = (_vm->_vars["bblrsw"] == 1) ? 0 : 1;
}
}
}
void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
// Why is this an external command....?
- if (*_vm->getVar("bvalve") == 2)
+ if (_vm->_vars["bvalve"] == 2)
_vm->_video->playMovieBlockingRiven(2);
}
@@ -1049,54 +1135,54 @@ void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
void RivenExternal::lowerPins() {
// Lower the pins
- uint32 *pinUp = _vm->getVar("gpinup");
+ uint32 &pinUp = _vm->_vars["gpinup"];
- if (*pinUp == 0)
+ if (pinUp == 0)
return;
- uint32 *pinPos = _vm->getVar("gpinpos");
- uint32 startTime = (*pinPos - 1) * 600 + 4830;
- *pinUp = 0;
+ uint32 &pinPos = _vm->_vars["gpinpos"];
+ uint32 startTime = (pinPos - 1) * 600 + 4830;
+ pinUp = 0;
// Play the down sound
_vm->_sound->playSound(13);
- uint32 *upMovie = _vm->getVar("gupmoov");
+ uint32 &upMovie = _vm->_vars["gupmoov"];
// Play the video of the pins going down
- VideoHandle handle = _vm->_video->playMovieRiven(*upMovie);
+ VideoHandle handle = _vm->_video->playMovieRiven(upMovie);
assert(handle != NULL_VID_HANDLE);
_vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600));
_vm->_video->waitUntilMovieEnds(handle);
- *upMovie = 0;
+ upMovie = 0;
}
void RivenExternal::xgresetpins(uint16 argc, uint16 *argv) {
// As the function name suggests, this resets the pins
lowerPins();
- *_vm->getVar("gupmoov") = 0;
+ _vm->_vars["gupmoov"] = 0;
}
void RivenExternal::xgrotatepins(uint16 argc, uint16 *argv) {
// Rotate the pins, if necessary
- if (*_vm->getVar("gpinup") == 0)
+ if (_vm->_vars["gpinup"] == 0)
return;
- uint32 *pinPos = _vm->getVar("gpinpos");
- uint32 startTime = (*pinPos - 1) * 1200;
+ uint32 &pinPos = _vm->_vars["gpinpos"];
+ uint32 startTime = (pinPos - 1) * 1200;
- if (*pinPos == 4)
- *pinPos = 1;
+ if (pinPos == 4)
+ pinPos = 1;
else
- *pinPos += 1;
+ pinPos++;
// Play the rotating sound
_vm->_sound->playSound(12);
// Play the video of the pins rotating
- VideoHandle handle = _vm->_video->playMovieRiven(*_vm->getVar("gupmoov"));
+ VideoHandle handle = _vm->_video->playMovieRiven(_vm->_vars["gupmoov"]);
assert(handle != NULL_VID_HANDLE);
_vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 1215, 600));
_vm->_video->waitUntilMovieEnds(handle);
@@ -1115,7 +1201,7 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
mousePos.y /= 11;
// Lastly, adjust it based on the rotational position
- uint32 pinPos = *_vm->getVar("gpinpos");
+ uint32 &pinPos = _vm->_vars["gpinpos"];
switch (pinPos) {
case 1:
mousePos.x = 5 - mousePos.x;
@@ -1139,7 +1225,7 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
}
// Now check to see if this section of the island exists
- uint32 islandIndex = *_vm->getVar("glkbtns") - 1;
+ uint32 islandIndex = _vm->_vars["glkbtns"] - 1;
uint16 imagePos = mousePos.x + mousePos.y;
static const uint16 islandImages[5][11] = {
@@ -1151,7 +1237,7 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
};
// The scripts set gimagemax to hold the max pin array length in islandPins above
- uint32 imageCount = *_vm->getVar("gimagemax");
+ uint32 imageCount = _vm->_vars["gimagemax"];
uint32 image = 0;
for (; image < imageCount; image++)
if (islandImages[islandIndex][image] == imagePos)
@@ -1161,15 +1247,15 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
if (image == imageCount)
return;
- uint32 *pinUp = _vm->getVar("gpinup");
- uint32 *curImage = _vm->getVar("gimagecurr");
+ uint32 &pinUp = _vm->_vars["gpinup"];
+ uint32 &curImage = _vm->_vars["gimagecurr"];
// Lower the pins if they are currently raised
- if (*pinUp == 1) {
+ if (pinUp == 1) {
lowerPins();
// If we just lowered the selected section, don't raise it up again
- if (*curImage == image)
+ if (curImage == image)
return;
}
@@ -1187,9 +1273,9 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
_vm->_video->waitUntilMovieEnds(handle);
// Update the relevant variables
- *_vm->getVar("gupmoov") = pinMovieCodes[imagePos - 1];
- *pinUp = 1;
- *curImage = image;
+ _vm->_vars["gupmoov"] = pinMovieCodes[imagePos - 1];
+ pinUp = 1;
+ curImage = image;
}
void RivenExternal::xgisland25_opencard(uint16 argc, uint16 *argv) {
@@ -1219,19 +1305,20 @@ void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) {
void RivenExternal::xgplateau3160_dopools(uint16 argc, uint16 *argv) {
// Play the deactivation of a pool if one is active and a different one is activated
_vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_video->playMovieBlockingRiven(*_vm->getVar("glkbtns") * 2);
+ _vm->_system->updateScreen();
+ _vm->_video->playMovieBlockingRiven(_vm->_vars["glkbtns"] * 2);
}
void RivenExternal::xgwt200_scribetime(uint16 argc, uint16 *argv) {
// Get the current time
- *_vm->getVar("gscribetime") = _vm->_system->getMillis();
+ _vm->_vars["gscribetime"] = _vm->_system->getMillis();
}
void RivenExternal::xgwt900_scribe(uint16 argc, uint16 *argv) {
- uint32 *scribeVar = _vm->getVar("gscribe");
+ uint32 &scribeVar = _vm->_vars["gscribe"];
- if (*scribeVar == 1 && _vm->_system->getMillis() > *_vm->getVar("gscribetime") + 40000)
- *scribeVar = 2;
+ if (scribeVar == 1 && _vm->_system->getMillis() > _vm->_vars["gscribetime"] + 40000)
+ scribeVar = 2;
}
static const uint16 s_viewerTimeIntervals[] = { 0, 816, 1617, 2416, 3216, 4016, 4816, 5616, 6416, 7216, 8016, 8816 };
@@ -1241,9 +1328,9 @@ void RivenExternal::xgrviewer(uint16 argc, uint16 *argv) {
// (It shows the colors of the marbles)
// If the light is on, turn it off
- uint32 *viewerLight = _vm->getVar("grview");
- if (*viewerLight == 1) {
- *viewerLight = 0;
+ uint32 &viewerLight = _vm->_vars["grview"];
+ if (viewerLight == 1) {
+ viewerLight = 0;
_vm->_sound->playSound(27);
_vm->refreshCard();
@@ -1253,17 +1340,17 @@ void RivenExternal::xgrviewer(uint16 argc, uint16 *argv) {
// Calculate how much we're moving
static const uint16 hotspotPositions[] = { 2, 1, 5, 4, 3 };
- uint32 *curPos = _vm->getVar("grviewpos");
- uint32 newPos = *curPos + hotspotPositions[_vm->_curHotspot - 1];
+ uint32 &curPos = _vm->_vars["grviewpos"];
+ uint32 newPos = curPos + hotspotPositions[_vm->_curHotspot - 1];
// Now play the movie
VideoHandle handle = _vm->_video->playMovieRiven(1);
assert(handle != NULL_VID_HANDLE);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[*curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
_vm->_video->waitUntilMovieEnds(handle);
// Set the new position and let the card's scripts take over again
- *curPos = newPos % 6; // Clip it to 0-5
+ curPos = newPos % 6; // Clip it to 0-5
_vm->refreshCard();
}
@@ -1271,25 +1358,25 @@ void RivenExternal::xgplaywhark(uint16 argc, uint16 *argv) {
// The whark response to using the lights
// If we've gotten a visit already since we turned out the light, bail out
- uint32 *wharkState = _vm->getVar("gwharktime");
+ uint32 &wharkState = _vm->_vars["gwharktime"];
- if (*wharkState != 1)
+ if (wharkState != 1)
return;
- *wharkState = 0;
+ wharkState = 0;
// Increase the amount of times the whark has visited
- uint32 *wharkVisits = _vm->getVar("gwhark");
- *wharkVisits += 1;
+ uint32 &wharkVisits = _vm->_vars["gwhark"];
+ wharkVisits++;
// If we're at 5 or more, the whark will no longer visit us :(
- if (*wharkVisits >= 5) {
- *wharkVisits = 5;
+ if (wharkVisits >= 5) {
+ wharkVisits = 5;
return;
}
// Activate the correct video based on the amount of times we've been visited
- switch (*wharkVisits) {
+ switch (wharkVisits) {
case 1:
_vm->_video->activateMLST(3, _vm->getCurCard());
break;
@@ -1322,43 +1409,136 @@ void RivenExternal::xglviewer(uint16 argc, uint16 *argv) {
// Calculate how much we're moving
static const uint16 hotspotPositions[] = { 1, 5, 4, 2, 0, 0, 3 };
- uint32 *curPos = _vm->getVar("glviewpos");
- uint32 newPos = *curPos + hotspotPositions[_vm->_curHotspot - 1];
+ uint32 &curPos = _vm->_vars["glviewpos"];
+ uint32 newPos = curPos + hotspotPositions[_vm->_curHotspot - 1];
// Now play the movie
VideoHandle handle = _vm->_video->playMovieRiven(1);
assert(handle != NULL_VID_HANDLE);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[*curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
_vm->_video->waitUntilMovieEnds(handle);
// Set the new position to the variable
- *curPos = newPos % 6; // Clip it to 0-5
+ curPos = newPos % 6; // Clip it to 0-5
// And update the screen with the new image
- _vm->_gfx->drawPLST(*curPos + 2);
+ _vm->_gfx->drawPLST(curPos + 2);
_vm->_gfx->updateScreen();
}
void RivenExternal::xglview_villageon(uint16 argc, uint16 *argv) {
// Turn on the left viewer to 'village mode'
- *_vm->getVar("glview") = 2;
- _vm->_gfx->drawPLST(*_vm->getVar("glviewpos") + 2);
+ _vm->_vars["glview"] = 2;
+ _vm->_gfx->drawPLST(_vm->_vars["glviewpos"] + 2);
_vm->_gfx->updateScreen();
}
void RivenExternal::xglview_villageoff(uint16 argc, uint16 *argv) {
// Turn off the left viewer when in 'village mode' (why is this external?)
- *_vm->getVar("glview") = 0;
+ _vm->_vars["glview"] = 0;
_vm->_gfx->drawPLST(1);
_vm->_gfx->updateScreen();
}
+static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) {
+ uint32 &cathState = vm->_vars["gcathstate"];
+ uint16 movie;
+
+ // Choose a new movie
+ if (cathState == 1) {
+ static const int movieList[] = { 9, 10, 19, 19, 21, 21 };
+ movie = movieList[vm->_rnd->getRandomNumber(5)];
+ } else if (cathState == 2) {
+ static const int movieList[] = { 18, 20, 22 };
+ movie = movieList[vm->_rnd->getRandomNumber(2)];
+ } else {
+ static const int movieList[] = { 11, 11, 12, 17, 17, 17, 17, 23 };
+ movie = movieList[vm->_rnd->getRandomNumber(7)];
+ }
+
+ // Update Catherine's state
+ if (movie == 10 || movie == 17 || movie == 18 || movie == 20)
+ cathState = 1;
+ else if (movie == 19 || movie == 21 || movie == 23)
+ cathState = 2;
+ else
+ cathState = 3;
+
+ // Begin playing the new movie
+ vm->_video->activateMLST(movie, vm->getCurCard());
+ VideoHandle videoHandle = vm->_video->playMovieRiven(30);
+
+ // Reset the timer
+ vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle) + vm->_rnd->getRandomNumber(60) * 1000);
+}
+
void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) {
- // TODO: Activate random background Catherine videos
+ // Activate random background Catherine videos
+
+ // Turn on the left viewer to 'prison mode'
+ _vm->_vars["glview"] = 1;
+
+ // Get basic starting states
+ uint16 cathMovie = _vm->_rnd->getRandomNumberRng(8, 23);
+ uint16 turnOnMovie = 4;
+ uint32 &cathState = _vm->_vars["gcathstate"];
+
+ // Adjust the turn on movie
+ if (cathMovie == 14)
+ turnOnMovie = 6;
+ else if (cathMovie == 15)
+ turnOnMovie = 7;
+
+ // Adjust Catherine's state
+ if (cathMovie == 9 || cathMovie == 11 || cathMovie == 12 || cathMovie == 22)
+ cathState = 3;
+ else if (cathMovie == 19 || cathMovie == 21 || cathMovie == 23 || cathMovie == 14)
+ cathState = 2;
+ else
+ cathState = 1;
+
+ // Turn on the viewer
+ _vm->_cursor->hideCursor();
+ _vm->_video->playMovieBlockingRiven(turnOnMovie);
+ _vm->_cursor->showCursor();
+
+ uint32 timeUntilNextMovie;
+
+ // Begin playing a movie immediately if Catherine is already in the viewer
+ if (cathMovie == 8 || (cathMovie >= 13 && cathMovie <= 16)) {
+ _vm->_video->activateMLST(cathMovie, _vm->getCurCard());
+ VideoHandle videoHandle = _vm->_video->playMovieRiven(30);
+
+ timeUntilNextMovie = _vm->_video->getDuration(videoHandle) + _vm->_rnd->getRandomNumber(60) * 1000;
+ } else {
+ // Otherwise, just redraw the imager
+ timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000;
+ _vm->_gfx->drawPLST(8);
+ _vm->_gfx->updateScreen();
+ }
+
+ // Create the timer for the next video
+ _vm->installTimer(&catherineViewerIdleTimer, timeUntilNextMovie);
}
void RivenExternal::xglview_prisonoff(uint16 argc, uint16 *argv) {
- // TODO: Deactivate random background Catherine videos
+ // Deactivate random background Catherine videos
+
+ // Update the viewer state (now off)
+ _vm->_vars["glview"] = 0;
+
+ // Remove the timer we set in xglview_prisonon()
+ _vm->removeTimer();
+
+ // Play the 'turn off' movie after stopping any videos still playing
+ _vm->_video->stopVideos();
+ _vm->_cursor->hideCursor();
+ _vm->_video->playMovieBlockingRiven(5);
+ _vm->_cursor->showCursor();
+
+ // Redraw the viewer
+ _vm->_gfx->drawPLST(1);
+ _vm->_gfx->updateScreen();
}
// ------------------------------------------------------------------------------------
@@ -1367,9 +1547,9 @@ void RivenExternal::xglview_prisonoff(uint16 argc, uint16 *argv) {
void RivenExternal::xreseticons(uint16 argc, uint16 *argv) {
// Reset the icons when going to Tay (rspit)
- *_vm->getVar("jicons") = 0;
- *_vm->getVar("jiconorder") = 0;
- *_vm->getVar("jrbook") = 0;
+ _vm->_vars["jicons"] = 0;
+ _vm->_vars["jiconorder"] = 0;
+ _vm->_vars["jrbook"] = 0;
}
// Count up how many icons are pressed
@@ -1390,49 +1570,49 @@ static byte countDepressedIcons(uint32 iconOrderVar) {
void RivenExternal::xicon(uint16 argc, uint16 *argv) {
// Set atemp as the status of whether or not the icon can be depressed.
- if (*_vm->getVar("jicons") & (1 << (argv[0] - 1))) {
+ if (_vm->_vars["jicons"] & (1 << (argv[0] - 1))) {
// This icon is depressed. Allow depression only if the last depressed icon was this one.
- if ((*_vm->getVar("jiconorder") & 0x1f) == argv[0])
- *_vm->getVar("atemp") = 1;
+ if ((_vm->_vars["jiconorder"] & 0x1f) == argv[0])
+ _vm->_vars["atemp"] = 1;
else
- *_vm->getVar("atemp") = 2;
+ _vm->_vars["atemp"] = 2;
} else
- *_vm->getVar("atemp") = 0;
+ _vm->_vars["atemp"] = 0;
}
void RivenExternal::xcheckicons(uint16 argc, uint16 *argv) {
// Reset the icons if this is the sixth icon
- uint32 *iconOrderVar = _vm->getVar("jiconorder");
- if (countDepressedIcons(*iconOrderVar) == 5) {
- *iconOrderVar = 0;
- *_vm->getVar("jicons") = 0;
+ uint32 &iconOrderVar = _vm->_vars["jiconorder"];
+ if (countDepressedIcons(iconOrderVar) == 5) {
+ iconOrderVar = 0;
+ _vm->_vars["jicons"] = 0;
_vm->_sound->playSound(46);
}
}
void RivenExternal::xtoggleicon(uint16 argc, uint16 *argv) {
// Get the variables
- uint32 *iconsDepressed = _vm->getVar("jicons");
- uint32 *iconOrderVar = _vm->getVar("jiconorder");
+ uint32 &iconsDepressed = _vm->_vars["jicons"];
+ uint32 &iconOrderVar = _vm->_vars["jiconorder"];
- if (*iconsDepressed & (1 << (argv[0] - 1))) {
+ if (iconsDepressed & (1 << (argv[0] - 1))) {
// The icon is depressed, now unpress it
- *iconsDepressed &= ~(1 << (argv[0] - 1));
- *iconOrderVar >>= 5;
+ iconsDepressed &= ~(1 << (argv[0] - 1));
+ iconOrderVar >>= 5;
} else {
// The icon is not depressed, now depress it
- *iconsDepressed |= 1 << (argv[0] - 1);
- *iconOrderVar = (*iconOrderVar << 5) + argv[0];
+ iconsDepressed |= 1 << (argv[0] - 1);
+ iconOrderVar = (iconOrderVar << 5) + argv[0];
}
// Check if the puzzle is complete now and assign 1 to jrbook if the puzzle is complete.
- if (*iconOrderVar == *_vm->getVar("jiconcorrectorder"))
- *_vm->getVar("jrbook") = 1;
+ if (iconOrderVar == _vm->_vars["jiconcorrectorder"])
+ _vm->_vars["jrbook"] = 1;
}
void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 0))
@@ -1453,7 +1633,7 @@ void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 9))
@@ -1476,7 +1656,7 @@ void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 3))
@@ -1497,7 +1677,7 @@ void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 16))
@@ -1522,17 +1702,18 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
// Run the gallows's carriage
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_video->playMovieBlockingRiven(1); // Play handle movie
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(1); // Play handle movie
_vm->_gfx->scheduleTransition(15); // Set pan down transition
_vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor (again)
- _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop
_vm->_gfx->scheduleTransition(14); // Set pan up transition
_vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again
_vm->_video->playMovieBlockingRiven(2);
- uint32 *gallows = _vm->getVar("jgallows");
- if (*gallows == 1) {
+ if (_vm->_vars["jgallows"] == 1) {
// If the gallows is open, play the up movie and return
_vm->_video->playMovieBlockingRiven(3);
return;
@@ -1560,19 +1741,22 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
}
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
if (gotClick) {
_vm->_gfx->scheduleTransition(16); // Schedule dissolve transition
_vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
_vm->_system->delayMillis(500); // Delay a half second before changing again
_vm->_gfx->scheduleTransition(12); // Schedule pan left transition
_vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie
_vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top
} else
- _vm->_video->playMovieBlockingRiven(3); // Too slow!
+ _vm->_video->playMovieBlockingRiven(3); // Too slow!
}
void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
@@ -1603,6 +1787,7 @@ int RivenExternal::jspitElevatorLoop() {
_vm->_cursor->setCursor(kRivenClosedHandCursor);
_vm->_system->updateScreen();
+
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
@@ -1663,11 +1848,11 @@ void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlockingRiven(6);
// If the whark's mouth is open, close it
- uint32 *mouthVar = _vm->getVar("jwmouth");
- if (*mouthVar == 1) {
+ uint32 &mouthVar = _vm->_vars["jwmouth"];
+ if (mouthVar == 1) {
_vm->_video->playMovieBlockingRiven(3);
_vm->_video->playMovieBlockingRiven(8);
- *mouthVar = 0;
+ mouthVar = 0;
}
// Play the elevator video and then change the card
@@ -1682,27 +1867,27 @@ void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
void RivenExternal::xjplaybeetle_550(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_600(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_950(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_1050(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_1450(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time as long as the girl is not present
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && *_vm->getVar("jgirl") != 1) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && _vm->_vars["jgirl"] != 1) ? 1 : 0;
}
void RivenExternal::xjlagoon700_alert(uint16 argc, uint16 *argv) {
@@ -1715,12 +1900,12 @@ void RivenExternal::xjlagoon800_alert(uint16 argc, uint16 *argv) {
void RivenExternal::xjlagoon1500_alert(uint16 argc, uint16 *argv) {
// Have the sunners move a bit as you get closer ;)
- uint32 *sunners = _vm->getVar("jsunners");
- if (*sunners == 0) {
+ uint32 &sunners = _vm->_vars["jsunners"];
+ if (sunners == 0) {
_vm->_video->playMovieBlockingRiven(3);
- } else if (*sunners == 1) {
+ } else if (sunners == 1) {
_vm->_video->playMovieBlockingRiven(2);
- *sunners = 2;
+ sunners = 2;
}
}
@@ -1750,14 +1935,14 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) {
uint16 spinMLST, overlayPLST, doomMLST, snackMLST;
// Choose left or right based on jwharkpos (which is set by the scripts)
- if (*_vm->getVar("jwharkpos") == 1) {
- posVar = _vm->getVar("jleftpos");
+ if (_vm->_vars["jwharkpos"] == 1) {
+ posVar = &_vm->_vars["jleftpos"];
spinMLST = 1;
overlayPLST = 12;
doomMLST = 3;
snackMLST = 4;
} else {
- posVar = _vm->getVar("jrightpos");
+ posVar = &_vm->_vars["jrightpos"];
spinMLST = 2;
overlayPLST = 13;
doomMLST = 5;
@@ -1766,6 +1951,7 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
// Play the spin movie
_vm->_video->playMovieBlockingRiven(spinMLST);
@@ -1811,26 +1997,27 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) {
// WORKAROUND: The special change stuff only handles one destination and it would
// be messy to modify the way that currently works. If we use the trap book on Tay,
// we should be using the Tay end game sequences.
- if (*_vm->getVar("returnstackid") == rspit) {
+ if (_vm->_vars["returnstackid"] == rspit) {
_vm->changeToStack(rspit);
_vm->changeToCard(2);
return;
}
// You used the trap book... why? What were you thinking?
- uint32 *gehnState = _vm->getVar("agehn");
+ uint32 gehnState = _vm->_vars["agehn"];
- if (*gehnState == 0) // Gehn who?
- runEndGame(1);
- else if (*gehnState == 4) // You freed him? Are you kidding me?
- runEndGame(2);
- else // You already spoke with Gehn. What were you thinking?
- runEndGame(3);
+ if (gehnState == 0) // Gehn who?
+ runEndGame(1, 9500);
+ else if (gehnState == 4) // You freed him? Are you kidding me?
+ runEndGame(2, 12000);
+ else // You already spoke with Gehn. What were you thinking?
+ runEndGame(3, 8000);
}
void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
// Let's hook onto our video
VideoHandle video = _vm->_video->findVideoHandleRiven(argv[0]);
@@ -1873,6 +2060,8 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
else
_vm->_cursor->setCursor(kRivenMainCursor);
+
+ _vm->_system->updateScreen();
// OK, Gehn has opened the trap book and has asked us to go in. Let's watch
// and see what the player will do...
@@ -1887,7 +2076,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
else
_vm->_cursor->setCursor(kRivenMainCursor);
- updateScreen = false; // Don't update twice, changing the cursor already updates the screen
+ updateScreen = true;
break;
case Common::EVENT_LBUTTONUP:
if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) {
@@ -1899,11 +2088,11 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
_vm->_gfx->updateScreen(); // Update the screen
_vm->_sound->playSound(0); // Play the link sound
_vm->_video->activateMLST(7, _vm->getCurCard()); // Activate Gehn Link Video
- _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video
- *_vm->getVar("agehn") = 4; // Set Gehn to the trapped state
- *_vm->getVar("atrapbook") = 1; // We've got the trap book again
+ _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video
+ _vm->_vars["agehn"] = 4; // Set Gehn to the trapped state
+ _vm->_vars["atrapbook"] = 1; // We've got the trap book again
_vm->_sound->playSound(0); // Play the link sound again
- _vm->changeToCard(_vm->matchRMAPToCard(0x2885)); // Link out! (TODO: Shouldn't this card change?)
+ _vm->changeToCard(_vm->matchRMAPToCard(0x2885)); // Link out!
return;
}
break;
@@ -1924,13 +2113,14 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
// Hide the cursor again
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
// If there was no click and this is the third time Gehn asks us to
// use the trap book, he will shoot the player. Dead on arrival.
// Run the credits from here.
- if (*_vm->getVar("agehn") == 3) {
+ if (_vm->_vars["agehn"] == 3) {
_vm->_scriptMan->stopAllScripts();
- runCredits(argv[0]);
+ runCredits(argv[0], 5000);
return;
}
@@ -1940,12 +2130,12 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
// Close the blank linking book if it's open
- uint32 *book = _vm->getVar("odeskbook");
- if (*book != 1)
+ uint32 &book = _vm->_vars["odeskbook"];
+ if (book != 1)
return;
// Set the variable to be "closed"
- *book = 0;
+ book = 0;
// Play the movie
_vm->_video->playMovieBlockingRiven(1);
@@ -1963,21 +2153,21 @@ void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
void RivenExternal::xobedroom5_closedrawer(uint16 argc, uint16 *argv) {
// Close the drawer if open when clicking on the journal.
_vm->_video->playMovieBlockingRiven(2);
- *_vm->getVar("ostanddrawer") = 0;
+ _vm->_vars["ostanddrawer"] = 0;
}
void RivenExternal::xogehnopenbook(uint16 argc, uint16 *argv) {
- _vm->_gfx->drawPLST(*_vm->getVar("ogehnpage"));
+ _vm->_gfx->drawPLST(_vm->_vars["ogehnpage"]);
}
void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("ogehnpage");
+ uint32 &page = _vm->_vars["ogehnpage"];
// Decrement the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
_vm->_sound->playSound(12);
@@ -1989,12 +2179,12 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("ogehnpage");
+ uint32 &page = _vm->_vars["ogehnpage"];
// Increment the page if it's not the last page
- if (*page == 13)
+ if (page == 13)
return;
- (*page)++;
+ page++;
// Play the page turning sound
_vm->_sound->playSound(13);
@@ -2012,8 +2202,9 @@ uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) {
void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
- uint32 *prisonCombo = _vm->getVar("pcorrectorder");
+ uint32 &prisonCombo = _vm->_vars["pcorrectorder"];
uint32 soundTime = _vm->_system->getMillis() - 500; // Start the first sound instantly
byte curSound = 0;
@@ -2023,7 +2214,7 @@ void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
if (curSound == 5) // Break out after the last sound is done
break;
- _vm->_sound->playSound(getComboDigit(*prisonCombo, curSound) + 13);
+ _vm->_sound->playSound(getComboDigit(prisonCombo, curSound) + 13);
curSound++;
soundTime = _vm->_system->getMillis();
}
@@ -2055,17 +2246,17 @@ void RivenExternal::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
// It is impossible to get here if Gehn is not trapped. However,
// the original also disallows brute forcing the ending if you have
// not yet trapped Gehn.
- if (*_vm->getVar("agehn") != 4)
+ if (_vm->_vars["agehn"] != 4)
return;
- uint32 *correctDigits = _vm->getVar("pelevcombo");
+ uint32 &correctDigits = _vm->_vars["pelevcombo"];
// pelevcombo keeps count of how many buttons we have pressed in the correct order.
// When pelevcombo is 5, clicking the handle will show the video freeing Catherine.
- if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->getVar("pcorrectorder"), *correctDigits))
- *correctDigits += 1;
+ if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["pcorrectorder"], correctDigits))
+ correctDigits++;
else
- *correctDigits = 0;
+ correctDigits = 0;
}
void RivenExternal::xpscpbtn(uint16 argc, uint16 *argv) {
@@ -2104,13 +2295,13 @@ void RivenExternal::xrcredittime(uint16 argc, uint16 *argv) {
// For the record, when agehn == 4, Gehn will thank you for
// showing him the rebel age and then leave you to die.
// Otherwise, the rebels burn the book. Epic fail either way.
- runEndGame(1);
+ runEndGame(1, 1500);
}
void RivenExternal::xrshowinventory(uint16 argc, uint16 *argv) {
// Give the trap book and Catherine's journal to the player
- *_vm->getVar("atrapbook") = 1;
- *_vm->getVar("acathbook") = 1;
+ _vm->_vars["atrapbook"] = 1;
+ _vm->_vars["acathbook"] = 1;
_vm->_gfx->showInventory();
}
@@ -2118,8 +2309,53 @@ void RivenExternal::xrhideinventory(uint16 argc, uint16 *argv) {
_vm->_gfx->hideInventory();
}
+static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) {
+ // Randomize a video out in the middle of Tay
+ uint16 movie = vm->_rnd->getRandomNumberRng(2, 13);
+ vm->_video->activateMLST(movie, vm->getCurCard());
+ VideoHandle handle = vm->_video->playMovieRiven(movie);
+
+ // Ensure the next video starts after this one ends
+ uint32 timeUntilNextVideo = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(38, 58) * 1000;
+
+ // Save the time in case we leave the card and return
+ vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime();
+
+ // Reinstall this timer with the new time
+ vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
+}
+
void RivenExternal::xrwindowsetup(uint16 argc, uint16 *argv) {
- // TODO: Randomizing what effect happens when you look out into the middle of Tay (useless! :P)
+ // Randomize what effect happens when you look out into the middle of Tay
+
+ uint32 villageTime = _vm->_vars["rvillagetime"];
+
+ // If we have time leftover from a previous run, set up the timer again
+ if (_vm->getTotalPlayTime() < villageTime) {
+ _vm->installTimer(&rebelPrisonWindowTimer, villageTime - _vm->getTotalPlayTime());
+ return;
+ }
+
+ uint32 timeUntilNextVideo;
+
+ // Randomize the time until the next video
+ if (_vm->_rnd->getRandomNumber(2) == 0 && _vm->_vars["rrichard"] == 0) {
+ // In this case, a rebel is placed on a bridge
+ // The video itself is handled by the scripts later on
+ _vm->_vars["rrebelview"] = 0;
+ timeUntilNextVideo = _vm->_rnd->getRandomNumberRng(38, 58) * 1000;
+ } else {
+ // Otherwise, just a random video from the timer
+ _vm->_vars["rrebelview"] = 1;
+ timeUntilNextVideo = _vm->_rnd->getRandomNumber(20) * 1000;
+ }
+
+ // We don't set rvillagetime here because the scripts later just reset it to 0
+ // Of course, because of this, you can't return to the window twice and expect
+ // the timer to reinstall itself...
+
+ // Install our timer and we're on our way
+ _vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
}
// ------------------------------------------------------------------------------------
@@ -2131,48 +2367,45 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlockingRiven(3);
// Don't do anything else if the telescope power is off
- if (*_vm->getVar("ttelevalve") == 0)
+ if (_vm->_vars["ttelevalve"] == 0)
return;
- uint32 *telescopePos = _vm->getVar("ttelescope");
- uint32 *telescopeCover = _vm->getVar("ttelecover");
+ uint32 &telescopePos = _vm->_vars["ttelescope"];
+ uint32 &telescopeCover = _vm->_vars["ttelecover"];
- if (*telescopePos == 1) {
+ if (telescopePos == 1) {
// We're at the bottom, which means one of two things can happen...
- if (*telescopeCover == 1 && *_vm->getVar("ttelepin") == 1) {
+ if (telescopeCover == 1 && _vm->_vars["ttelepin"] == 1) {
// ...if the cover is open and the pin is up, the game is now over.
- if (*_vm->getVar("pcage") == 2) {
+ if (_vm->_vars["pcage"] == 2) {
// The best ending: Catherine is free, Gehn is trapped, Atrus comes to rescue you.
// And now we fall back to Earth... all the way...
- warning("xtexterior300_telescopedown: Good ending");
_vm->_video->activateMLST(8, _vm->getCurCard());
- runEndGame(8);
- } else if (*_vm->getVar("agehn") == 4) {
+ runEndGame(8, 5000);
+ } else if (_vm->_vars["agehn"] == 4) {
// The ok ending: Catherine is still trapped, Gehn is trapped, Atrus comes to rescue you.
// Nice going! Catherine and the islanders are all dead now! Just go back to your home...
- warning("xtexterior300_telescopedown: OK ending");
_vm->_video->activateMLST(9, _vm->getCurCard());
- runEndGame(9);
- } else if (*_vm->getVar("atrapbook") == 1) {
+ runEndGame(9, 5000);
+ } else if (_vm->_vars["atrapbook"] == 1) {
// The bad ending: Catherine is trapped, Gehn is free, Atrus gets shot by Gehn,
// And then you get shot by Cho. Nice going! Catherine and the islanders are dead
// and you have just set Gehn free from Riven, not to mention you're dead.
- warning("xtexterior300_telescopedown: Bad ending");
_vm->_video->activateMLST(10, _vm->getCurCard());
- runEndGame(10);
+ runEndGame(10, 5000);
} else {
// The impossible ending: You don't have Catherine's journal and yet you were somehow
// able to open the hatch on the telescope. The game provides an ending for those who
// cheat, load a saved game with the combo, or just guess the telescope combo. Atrus
// doesn't come and you just fall into the fissure.
- warning("xtexterior300_telescopedown: Wtf ending");
_vm->_video->activateMLST(11, _vm->getCurCard());
- runEndGame(11);
+ runEndGame(11, 5000);
}
} else {
// ...the telescope can't move down anymore.
// Play the sound of not being able to move
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_sound->playSoundBlocking(13);
}
} else {
@@ -2180,14 +2413,14 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
// Play a piece of the moving down movie
static const uint32 timeIntervals[] = { 4320, 3440, 2560, 1760, 880, 0 };
- uint16 movieCode = (*telescopeCover) ? 1 : 2;
+ uint16 movieCode = telescopeCover ? 1 : 2;
VideoHandle handle = _vm->_video->playMovieRiven(movieCode);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[*telescopePos], 600), Audio::Timestamp(0, timeIntervals[*telescopePos - 1], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[telescopePos], 600), Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600));
_vm->_sound->playSound(14); // Play the moving sound
_vm->_video->waitUntilMovieEnds(handle);
// Now move the telescope down a position and refresh
- *telescopePos -= 1;
+ telescopePos--;
_vm->refreshCard();
}
}
@@ -2197,54 +2430,52 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlockingRiven(3);
// Don't do anything else if the telescope power is off
- if (*_vm->getVar("ttelevalve") == 0)
+ if (_vm->_vars["ttelevalve"] == 0)
return;
- uint32 *telescopePos = _vm->getVar("ttelescope");
+ uint32 &telescopePos = _vm->_vars["ttelescope"];
// Check if we can't move up anymore
- if (*telescopePos == 5) {
+ if (telescopePos == 5) {
// Play the sound of not being able to move
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_sound->playSoundBlocking(13);
return;
}
// Play a piece of the moving up movie
static const uint32 timeIntervals[] = { 0, 800, 1680, 2560, 3440, 4320 };
- uint16 movieCode = (*_vm->getVar("ttelecover")) ? 4 : 5;
+ uint16 movieCode = _vm->_vars["ttelecover"] ? 4 : 5;
VideoHandle handle = _vm->_video->playMovieRiven(movieCode);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[*telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[*telescopePos], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[telescopePos], 600));
_vm->_sound->playSound(14); // Play the moving sound
_vm->_video->waitUntilMovieEnds(handle);
// Now move the telescope up a position and refresh
- *telescopePos += 1;
+ telescopePos++;
_vm->refreshCard();
}
void RivenExternal::xtisland390_covercombo(uint16 argc, uint16 *argv) {
// Called when clicking the telescope cover buttons. argv[0] is the button number (1...5).
- uint32 *correctDigits = _vm->getVar("tcovercombo");
+ uint32 &correctDigits = _vm->_vars["tcovercombo"];
- if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->getVar("tcorrectorder"), *correctDigits))
- *correctDigits += 1;
+ if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["tcorrectorder"], correctDigits))
+ correctDigits++;
else
- *correctDigits = 0;
+ correctDigits = 0;
// If we have hit the correct 5 buttons in a row, activate the hotspot to open up the
// telescope cover.
- if (*correctDigits == 5)
- _vm->_hotspots[9].enabled = true;
- else
- _vm->_hotspots[9].enabled = false;
+ _vm->_hotspots[9].enabled = (correctDigits == 5);
}
// Atrus' Journal and Trap Book are added to inventory
void RivenExternal::xtatrusgivesbooks(uint16 argc, uint16 *argv) {
// Give the player Atrus' Journal and the Trap book
- *_vm->getVar("aatrusbook") = 1;
- *_vm->getVar("atrapbook") = 1;
+ _vm->_vars["aatrusbook"] = 1;
+ _vm->_vars["atrapbook"] = 1;
}
// Trap Book is removed from inventory
@@ -2252,7 +2483,7 @@ void RivenExternal::xtchotakesbook(uint16 argc, uint16 *argv) {
// And now Cho takes the trap book. Sure, this isn't strictly
// necessary to add and them remove the trap book... but it
// seems better to do this ;)
- *_vm->getVar("atrapbook") = 0;
+ _vm->_vars["atrapbook"] = 0;
}
void RivenExternal::xthideinventory(uint16 argc, uint16 *argv) {
@@ -2269,20 +2500,20 @@ static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "
// Marble Puzzle helper functions
// The y portion takes the upper 16 bits, while the x portion takes the lower 16 bits
-static void setMarbleX(uint32 *var, byte x) {
- *var = (*var & 0xff00) | (x + 1);
+static void setMarbleX(uint32 &var, byte x) {
+ var = (var & 0xff00) | (x + 1);
}
-static void setMarbleY(uint32 *var, byte y) {
- *var = ((y + 1) << 16) | (*var & 0xff);
+static void setMarbleY(uint32 &var, byte y) {
+ var = ((y + 1) << 16) | (var & 0xff);
}
-static byte getMarbleX(uint32 *var) {
- return (*var & 0xff) - 1;
+static byte getMarbleX(uint32 var) {
+ return (var & 0xff) - 1;
}
-static byte getMarbleY(uint32 *var) { // Give that that Y you old hag! </bad Seinfeld reference>
- return ((*var >> 16) & 0xff) - 1;
+static byte getMarbleY(uint32 var) { // Give that that Y you old hag! </bad Seinfeld reference>
+ return ((var >> 16) & 0xff) - 1;
}
static Common::Rect generateMarbleGridRect(uint16 x, uint16 y) {
@@ -2302,7 +2533,7 @@ void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
static const uint32 marbleFinalValues[] = { 1114121, 1441798, 0, 65552, 65558, 262146 };
for (uint16 i = 0; i < kMarbleCount; i++)
- if (*_vm->getVar(s_marbleNames[i]) != marbleFinalValues[i]) {
+ if (_vm->_vars[s_marbleNames[i]] != marbleFinalValues[i]) {
valid = false;
break;
}
@@ -2310,24 +2541,24 @@ void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
// If we have the correct combo, activate the power and reset the marble positions
// Otherwise, make sure the power is off
if (valid) {
- *_vm->getVar("apower") = 1;
+ _vm->_vars["apower"] = 1;
for (uint16 i = 0; i < kMarbleCount; i++)
- *_vm->getVar(s_marbleNames[i]) = 0;
+ _vm->_vars[s_marbleNames[i]] = 0;
} else
- *_vm->getVar("apower") = 0;
+ _vm->_vars["apower"] = 0;
}
void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
// Draw the small marbles when we're a step away from the waffle
uint16 baseBitmapId = _vm->findResourceID(ID_TBMP, "*tsmallred");
- bool waffleDown = *_vm->getVar("twaffle") != 0;
+ bool waffleDown = _vm->_vars["twaffle"] != 0;
// Note that each of the small marble images is exactly 4x2
for (uint16 i = 0; i < kMarbleCount; i++) {
- uint32 *var = _vm->getVar(s_marbleNames[i]);
+ uint32 &var = _vm->_vars[s_marbleNames[i]];
- if (*var == 0) {
+ if (var == 0) {
// The marble is still in its initial place
// (Note that this is still drawn even if the waffle is down)
int marbleX = 376 + i * 2;
@@ -2346,9 +2577,9 @@ void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
void RivenExternal::setMarbleHotspots() {
// Set the hotspots
for (uint16 i = 0; i < kMarbleCount; i++) {
- uint32 *marblePos = _vm->getVar(s_marbleNames[i]);
+ uint32 &marblePos = _vm->_vars[s_marbleNames[i]];
- if (*marblePos == 0) // In the receptacle
+ if (marblePos == 0) // In the receptacle
_vm->_hotspots[i + 3].rect = _marbleBaseHotspots[i];
else // On the grid
_vm->_hotspots[i + 3].rect = generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos));
@@ -2363,13 +2594,13 @@ void RivenExternal::xt7800_setup(uint16 argc, uint16 *argv) {
// Move the marble hotspots based on their position variables
setMarbleHotspots();
- *_vm->getVar("themarble") = 0;
+ _vm->_vars["themarble"] = 0;
}
void RivenExternal::drawMarbles() {
for (uint32 i = 0; i < kMarbleCount; i++) {
// Don't draw the marble if we're holding it
- if (*_vm->getVar("themarble") - 1 == i)
+ if (_vm->_vars["themarble"] - 1 == i)
continue;
Common::Rect rect = _vm->_hotspots[i + 3].rect;
@@ -2395,17 +2626,17 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
// Pick up and move a marble
// First, let's figure out what marble we're now holding
- uint32 *marble = _vm->getVar("themarble");
- *marble = 0;
+ uint32 &marble = _vm->_vars["themarble"];
+ marble = 0;
for (uint32 i = 0; i < kMarbleCount; i++)
if (_vm->_hotspots[i + 3].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *marble = i + 1;
+ marble = i + 1;
break;
}
// xtakeit() shouldn't be called if we're not on a marble hotspot
- assert(*marble);
+ assert(marble != 0);
// Redraw the background
_vm->_gfx->drawPLST(1);
@@ -2428,7 +2659,7 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
}
// Check if we landed in a valid location and no other marble has that location
- uint32 *marblePos = _vm->getVar(s_marbleNames[*marble - 1]);
+ uint32 &marblePos = _vm->_vars[s_marbleNames[marble - 1]];
bool foundMatch = false;
for (int y = 0; y < 25 && !foundMatch; y++) {
@@ -2443,8 +2674,8 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
// Let's make sure no other marble is in this spot...
for (uint16 i = 0; i < kMarbleCount; i++)
- if (i != *marble - 1 && *_vm->getVar(s_marbleNames[i]) == *marblePos)
- *marblePos = 0;
+ if (i != marble - 1 && _vm->_vars[s_marbleNames[i]] == marblePos)
+ marblePos = 0;
// We have a match
foundMatch = true;
@@ -2454,10 +2685,10 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
// If we still don't have a match, reset it to the original location
if (!foundMatch)
- *marblePos = 0;
+ marblePos = 0;
// Check the new hotspots and refresh everything
- *marble = 0;
+ marble = 0;
setMarbleHotspots();
_vm->updateCurrentHotspot();
_vm->_gfx->updateScreen();
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index 818bc06c54..034cd662f6 100644
--- a/engines/mohawk/riven_external.h
+++ b/engines/mohawk/riven_external.h
@@ -41,6 +41,7 @@ public:
uint16 getComboDigit(uint32 correctCombo, uint32 digit);
uint32 getDomeSliderState() { return _sliderState; }
void setDomeSliderState(uint32 state) { _sliderState = state; }
+ void checkYtramCatch(bool playSound);
private:
MohawkEngine_Riven *_vm;
@@ -61,8 +62,8 @@ private:
// Supplementary Functions
int jspitElevatorLoop();
void runDemoBoundaryDialog();
- void runEndGame(uint16 video);
- void runCredits(uint16 video);
+ void runEndGame(uint16 video, uint32 delay);
+ void runCredits(uint16 video, uint32 delay);
void runDomeCheck();
void runDomeButtonMovie();
void resetDomeSliders(uint16 soundId, uint16 startHotspot);
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index c7b5cd01fd..35ce7aad84 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -165,16 +165,24 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
if (name == "dropLeftStart" || name == "dropRightStart")
continue;
- uint32 *var = _vm->getVar(name);
-
- *var = rawVariables[i];
-
- if (name.equalsIgnoreCase("CurrentStackID"))
+ uint32 &var = _vm->_vars[name];
+ name.toLowercase();
+
+ // Handle any special variables here
+ // WORKAROUND: time variables are reset here for one main reason:
+ // The save does not store any start point for the time, so we don't know the real time.
+ // Because of this, in many cases, the original would just give a 'free' Ytram upon saving
+ // since the time would be used in a new (improper) time frame.
+ if (name.equalsIgnoreCase("CurrentStackID")) // Remap to our definitions, store for later
stackID = mapOldStackIDToNew(rawVariables[i]);
- else if (name.equalsIgnoreCase("CurrentCardID"))
+ else if (name.equalsIgnoreCase("CurrentCardID")) // Store for later
cardID = rawVariables[i];
- else if (name.equalsIgnoreCase("ReturnStackID"))
- *var = mapOldStackIDToNew(rawVariables[i]);
+ else if (name.equalsIgnoreCase("ReturnStackID") && var != 0) // if 0, the game did not use the variable yet
+ var = mapOldStackIDToNew(rawVariables[i]);
+ else if (name.contains("time")) // WORKAROUND: See above
+ var = 0;
+ else // Otherwise, just store it
+ var = rawVariables[i];
}
_vm->changeToStack(stackID);
@@ -216,14 +224,14 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVERSSection() {
Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
- for (uint32 i = 0; i < _vm->getVarCount(); i++) {
+ for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
stream->writeUint32BE(0); // Unknown
stream->writeUint32BE(0); // Unknown
// Remap returnstackid here because we don't actually want to change
// our internal returnstackid.
- uint32 variable = _vm->getGlobalVar(i);
- if (_vm->getGlobalVarName(i) == "returnstackid")
+ uint32 variable = it->_value;
+ if (it->_key == "returnstackid")
variable = mapNewStackIDToOld(variable);
stream->writeUint32BE(variable);
@@ -235,19 +243,19 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
Common::MemoryWriteStreamDynamic *RivenSaveLoad::genNAMESection() {
Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
- stream->writeUint16BE((uint16)_vm->getVarCount());
+ stream->writeUint16BE(_vm->_vars.size());
uint16 curPos = 0;
- for (uint16 i = 0; i < _vm->getVarCount(); i++) {
+ for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
stream->writeUint16BE(curPos);
- curPos += _vm->getGlobalVarName(i).size() + 1;
+ curPos += it->_key.size() + 1;
}
- for (uint16 i = 0; i < _vm->getVarCount(); i++)
+ for (uint16 i = 0; i < _vm->_vars.size(); i++)
stream->writeUint16BE(i);
- for (uint16 i = 0; i < _vm->getVarCount(); i++) {
- stream->write(_vm->getGlobalVarName(i).c_str(), _vm->getGlobalVarName(i).size());
+ for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
+ stream->write(it->_key.c_str(), it->_key.size());
stream->writeByte(0);
}
@@ -276,8 +284,8 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
filename += ".rvn";
// Convert class variables to variable numbers
- *_vm->getVar("currentstackid") = mapNewStackIDToOld(_vm->getCurStack());
- *_vm->getVar("currentcardid") = _vm->getCurCard();
+ _vm->_vars["currentstackid"] = mapNewStackIDToOld(_vm->getCurStack());
+ _vm->_vars["currentcardid"] = _vm->getCurCard();
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
if (!saveFile)
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 5d459354e9..35f38c4069 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -31,8 +31,8 @@
#include "mohawk/sound.h"
#include "mohawk/video.h"
+#include "common/memstream.h"
#include "common/stream.h"
-#include "graphics/cursorman.h"
namespace Mohawk {
@@ -139,7 +139,7 @@ void RivenScript::setupOpcodes() {
// 0x24 (36 decimal)
OPCODE(unk_36), // Unknown
OPCODE(fadeAmbientSounds),
- OPCODE(complexPlayMovie),
+ OPCODE(storeMovieOpcode),
OPCODE(activatePLST),
// 0x28 (40 decimal)
OPCODE(activateSLST),
@@ -260,7 +260,7 @@ void RivenScript::processCommands(bool runCommands) {
// Run the following block if the block's variable is equal to the variable to check against
// Don't run it if the parent block is not executed
// And don't run it if another block has already evaluated to true (needed for the default case)
- runBlock = (*_vm->getLocalVar(var) == checkValue || checkValue == 0xffff) && runCommands && !anotherBlockEvaluated;
+ runBlock = (_vm->getStackVar(var) == checkValue || checkValue == 0xffff) && runCommands && !anotherBlockEvaluated;
processCommands(runBlock);
if (runBlock)
@@ -363,8 +363,7 @@ void RivenScript::playSound(uint16 op, uint16 argc, uint16 *argv) {
// Command 7: set variable value (variable, value)
void RivenScript::setVariable(uint16 op, uint16 argc, uint16 *argv) {
- debug(2, "Setting variable %d to %d", argv[0], argv[1]);
- *_vm->getLocalVar(argv[0]) = argv[1];
+ _vm->getStackVar(argv[0]) = argv[1];
}
// Command 8: conditional branch
@@ -424,6 +423,7 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) {
void RivenScript::changeCursor(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Change to cursor %d", argv[0]);
_vm->_cursor->setCursor(argv[0]);
+ _vm->_system->updateScreen();
}
// Command 14: pause script execution (delay in ms, u1)
@@ -470,12 +470,10 @@ void RivenScript::enableScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
// Command 24: increment variable (variable, value)
void RivenScript::incrementVariable(uint16 op, uint16 argc, uint16 *argv) {
- uint32 *localVar = _vm->getLocalVar(argv[0]);
- *localVar += argv[1];
- debug(2, "Incrementing variable %d by %d, variable now is equal to %d", argv[0], argv[1], *localVar);
+ _vm->getStackVar(argv[0]) += argv[1];
}
-// Command 27: go to stack (stack_name code_hi code_lo)
+// Command 27: go to stack (stack name, code high, code low)
void RivenScript::changeStack(uint16 op, uint16 argc, uint16 *argv) {
Common::String stackName = _vm->getName(StackNames, argv[0]);
int8 index = -1;
@@ -512,9 +510,9 @@ void RivenScript::enableMovie(uint16 op, uint16 argc, uint16 *argv) {
// Command 32: play foreground movie - blocking (movie_id)
void RivenScript::playMovieBlocking(uint16 op, uint16 argc, uint16 *argv) {
- CursorMan.showMouse(false); // Hide the cursor before playing the video
+ _vm->_cursor->hideCursor();
_vm->_video->playMovieBlockingRiven(argv[0]);
- CursorMan.showMouse(true); // Show the cursor again when we're done ;)
+ _vm->_cursor->showCursor();
}
// Command 33: play background movie - nonblocking (movie_id)
@@ -538,18 +536,41 @@ void RivenScript::fadeAmbientSounds(uint16 op, uint16 argc, uint16 *argv) {
_vm->_sound->stopAllSLST(true);
}
-// Command 38: Play a movie with extra parameters (movie id, delay high, delay low, record type, record id)
-void RivenScript::complexPlayMovie(uint16 op, uint16 argc, uint16 *argv) {
- warning("STUB: complexPlayMovie");
- debugN("\tMovie ID = %d\n", argv[0]);
- debugN("\tDelay = %d\n", (argv[1] << 16) + argv[2]);
+// Command 38: Store an opcode for use when playing a movie (movie id, time high, time low, opcode, arguments...)
+void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
+ uint32 scriptSize = 6 + (argc - 4) * 2;
- if (argv[3] == 0)
- debugN("\tDraw PLST %d\n", argv[4]);
- else if (argv[3] == 40)
- debugN("\tPlay SLST %d\n", argv[4]);
- else
- error("Unknown complexPlayMovie record type %d", argv[3]);
+ // Create our dummy script
+ byte *scriptBuf = (byte *)malloc(scriptSize);
+ WRITE_BE_UINT16(scriptBuf, 1); // One command
+ WRITE_BE_UINT16(scriptBuf + 2, argv[3]); // One opcode
+ WRITE_BE_UINT16(scriptBuf + 4, argc - 4); // argc - 4 args
+
+ for (int i = 0; i < argc - 4; i++)
+ WRITE_BE_UINT16(scriptBuf + 6 + (i * 2), argv[i + 4]);
+
+ // Build a script out of 'er
+ Common::SeekableReadStream *scriptStream = new Common::MemoryReadStream(scriptBuf, scriptSize, DisposeAfterUse::YES);
+ RivenScript *script = new RivenScript(_vm, scriptStream, kStoredOpcodeScript, getParentStack(), getParentCard());
+
+ uint32 delayTime = (argv[1] << 16) + argv[2];
+
+ if (delayTime > 0) {
+ // Store the script
+ RivenScriptManager::StoredMovieOpcode storedOp;
+ storedOp.script = script;
+ storedOp.time = delayTime + _vm->getTotalPlayTime();
+ storedOp.id = argv[0];
+
+ // TODO: Actually store the movie and call it in our movie loop
+ // For now, just delete the script and move on
+ //_vm->_scriptMan->setStoredMovieOpcode(storedOp);
+ delete script;
+ } else {
+ // Run immediately if we have no delay
+ script->runScript();
+ delete script;
+ }
}
// Command 39: activate PLST record (card picture lists)
@@ -640,11 +661,16 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
_vm = vm;
+ _storedMovieOpcode.script = 0;
+ _storedMovieOpcode.time = 0;
+ _storedMovieOpcode.id = 0;
}
RivenScriptManager::~RivenScriptManager() {
for (uint32 i = 0; i < _currentScripts.size(); i++)
delete _currentScripts[i];
+
+ clearStoredMovieOpcode();
}
RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) {
@@ -685,4 +711,33 @@ void RivenScriptManager::unloadUnusedScripts() {
}
}
+void RivenScriptManager::setStoredMovieOpcode(const StoredMovieOpcode &op) {
+ clearStoredMovieOpcode();
+ _storedMovieOpcode.script = op.script;
+ _storedMovieOpcode.id = op.id;
+ _storedMovieOpcode.time = op.time;
+}
+
+void RivenScriptManager::runStoredMovieOpcode(uint16 id) {
+ if (_storedMovieOpcode.script) {
+ if (_storedMovieOpcode.id == id) {
+ // If we've passed the time, run our script
+ if (_vm->getTotalPlayTime() >= _storedMovieOpcode.time) {
+ _storedMovieOpcode.script->runScript();
+ clearStoredMovieOpcode();
+ }
+ } else {
+ // We're on a completely different video, kill off any remaining opcode
+ clearStoredMovieOpcode();
+ }
+ }
+}
+
+void RivenScriptManager::clearStoredMovieOpcode() {
+ delete _storedMovieOpcode.script;
+ _storedMovieOpcode.script = 0;
+ _storedMovieOpcode.time = 0;
+ _storedMovieOpcode.id = 0;
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index 89e5ff0836..46cd965f40 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -34,6 +34,7 @@ class MohawkEngine_Riven;
#define DECLARE_OPCODE(x) void x(uint16 op, uint16 argc, uint16 *argv)
namespace Mohawk {
+
// Script Types
enum {
kMouseDownScript = 0,
@@ -46,7 +47,9 @@ enum {
kCardLoadScript = 6,
kCardLeaveScript = 7,
kCardOpenScript = 9,
- kCardUpdateScript = 10
+ kCardUpdateScript = 10,
+
+ kStoredOpcodeScript // This is ScummVM-only to denote the script from a storeMovieOpcode() call
};
class RivenScript;
@@ -114,7 +117,7 @@ private:
DECLARE_OPCODE(stopMovie);
DECLARE_OPCODE(unk_36);
DECLARE_OPCODE(fadeAmbientSounds);
- DECLARE_OPCODE(complexPlayMovie);
+ DECLARE_OPCODE(storeMovieOpcode);
DECLARE_OPCODE(activatePLST);
DECLARE_OPCODE(activateSLST);
DECLARE_OPCODE(activateMLSTAndPlay);
@@ -134,10 +137,22 @@ public:
RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
void stopAllScripts();
+ struct StoredMovieOpcode {
+ RivenScript *script;
+ uint32 time;
+ uint16 id;
+ };
+
+ void setStoredMovieOpcode(const StoredMovieOpcode &op);
+ void runStoredMovieOpcode(uint16 id);
+ void clearStoredMovieOpcode();
+
private:
void unloadUnusedScripts();
RivenScriptList _currentScripts;
MohawkEngine_Riven *_vm;
+
+ StoredMovieOpcode _storedMovieOpcode;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index b18a753c31..7f06a67a1d 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -270,85 +270,64 @@ static const char *variableNames[] = {
"currentcardid"
};
-uint32 *MohawkEngine_Riven::getLocalVar(uint32 index) {
- return getVar(getName(VariableNames, index));
-}
-
-uint32 MohawkEngine_Riven::getGlobalVar(uint32 index) {
- return _vars[index];
-}
-
-Common::String MohawkEngine_Riven::getGlobalVarName(uint32 index) {
- return variableNames[index];
-}
-
-uint32 *MohawkEngine_Riven::getVar(const Common::String &varName) {
- for (uint32 i = 0; i < _varCount; i++)
- if (varName.equalsIgnoreCase(variableNames[i]))
- return &_vars[i];
-
- error ("Unknown variable: '%s'", varName.c_str());
- return NULL;
+uint32 &MohawkEngine_Riven::getStackVar(uint32 index) {
+ return _vars[getName(VariableNames, index)];
}
void MohawkEngine_Riven::initVars() {
- _varCount = ARRAYSIZE(variableNames);
-
- _vars = new uint32[_varCount];
-
- // Temporary:
- for (uint32 i = 0; i < _varCount; i++)
- _vars[i] = 0;
+ // Most variables just start at 0, it's simpler to do this
+ for (uint32 i = 0; i < ARRAYSIZE(variableNames); i++)
+ _vars[variableNames[i]] = 0;
- // Init Variables to their correct starting state.
- *getVar("ttelescope") = 5;
- *getVar("tgatestate") = 1;
- *getVar("jbridge1") = 1;
- *getVar("jbridge4") = 1;
- *getVar("jgallows") = 1;
- *getVar("jiconcorrectorder") = 12068577;
- *getVar("bblrvalve") = 1;
- *getVar("bblrwtr") = 1;
- *getVar("bfans") = 1;
- *getVar("bytrap") = 2;
- *getVar("aatruspage") = 1;
- *getVar("acathpage") = 1;
- *getVar("bheat") = 1;
- *getVar("waterenabled") = 1;
- *getVar("ogehnpage") = 1;
- *getVar("bblrsw") = 1;
- *getVar("ocage") = 1;
- *getVar("jbeetle") = 1;
- *getVar("tdl") = 1;
- *getVar("bmagcar") = 1;
- *getVar("gnmagcar") = 1;
- *getVar("omusicplayer") = 1;
+ // Initialize the rest of the variables to their proper state
+ _vars["ttelescope"] = 5;
+ _vars["tgatestate"] = 1;
+ _vars["jbridge1"] = 1;
+ _vars["jbridge4"] = 1;
+ _vars["jgallows"] = 1;
+ _vars["jiconcorrectorder"] = 12068577;
+ _vars["bblrvalve"] = 1;
+ _vars["bblrwtr"] = 1;
+ _vars["bfans"] = 1;
+ _vars["bytrap"] = 2;
+ _vars["aatruspage"] = 1;
+ _vars["acathpage"] = 1;
+ _vars["bheat"] = 1;
+ _vars["waterenabled"] = 1;
+ _vars["ogehnpage"] = 1;
+ _vars["bblrsw"] = 1;
+ _vars["ocage"] = 1;
+ _vars["jbeetle"] = 1;
+ _vars["tdl"] = 1;
+ _vars["bmagcar"] = 1;
+ _vars["gnmagcar"] = 1;
+ _vars["omusicplayer"] = 1;
// Randomize the telescope combination
- uint32 *teleCombo = getVar("tcorrectorder");
+ uint32 &teleCombo = _vars["tcorrectorder"];
for (byte i = 0; i < 5; i++) {
- *teleCombo *= 10;
- *teleCombo += _rnd->getRandomNumberRng(1, 5); // 5 buttons
+ teleCombo *= 10;
+ teleCombo += _rnd->getRandomNumberRng(1, 5); // 5 buttons
}
// Randomize the prison combination
- uint32 *prisonCombo = getVar("pcorrectorder");
+ uint32 &prisonCombo = _vars["pcorrectorder"];
for (byte i = 0; i < 5; i++) {
- *prisonCombo *= 10;
- *prisonCombo += _rnd->getRandomNumberRng(1, 3); // 3 buttons/sounds
+ prisonCombo *= 10;
+ prisonCombo += _rnd->getRandomNumberRng(1, 3); // 3 buttons/sounds
}
// Randomize the dome combination -- each bit represents a slider position,
// the highest bit (1 << 24) represents 1, (1 << 23) represents 2, etc.
- uint32 *domeCombo = getVar("adomecombo");
+ uint32 &domeCombo = _vars["adomecombo"];
for (byte bitsSet = 0; bitsSet < 5;) {
uint32 randomBit = 1 << (24 - _rnd->getRandomNumber(24));
// Don't overwrite a bit we already set, and throw out the bottom five bits being set
- if (*domeCombo & randomBit || (*domeCombo | randomBit) == 31)
+ if (domeCombo & randomBit || (domeCombo | randomBit) == 31)
continue;
- *domeCombo |= randomBit;
+ domeCombo |= randomBit;
bitsSet++;
}
}
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index ca642f1376..b4ae50b74a 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -90,11 +90,11 @@ Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id));
break;
case GType_LIVINGBOOKSV1:
- audStream = makeOldMohawkWaveStream(_vm->getResource(ID_WAV, id));
+ audStream = makeLivingBooksWaveStream_v1(_vm->getResource(ID_WAV, id));
break;
case GType_LIVINGBOOKSV2:
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
- audStream = makeOldMohawkWaveStream(_vm->getResource(ID_WAV, id));
+ audStream = makeLivingBooksWaveStream_v1(_vm->getResource(ID_WAV, id));
break;
}
// fall through
@@ -493,7 +493,7 @@ Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stre
return NULL;
}
-Audio::AudioStream *Sound::makeOldMohawkWaveStream(Common::SeekableReadStream *stream) {
+Audio::AudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
uint16 header = stream->readUint16BE();
uint16 rate = 0;
uint32 size = 0;
@@ -576,6 +576,15 @@ bool Sound::isPlaying(uint16 id) {
return false;
}
+bool Sound::isPlaying() {
+ for (uint32 i = 0; i < _handles.size(); i++)
+ if (_handles[i].type == kUsedHandle)
+ if (_vm->_mixer->isSoundHandleActive(_handles[i].handle))
+ return true;
+
+ return false;
+}
+
uint Sound::getNumSamplesPlayed(uint16 id) {
for (uint32 i = 0; i < _handles.size(); i++)
if (_handles[i].type == kUsedHandle && _handles[i].id == id) {
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 938f15fcb2..702c6f61f3 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -133,6 +133,7 @@ public:
void pauseSound();
void resumeSound();
bool isPlaying(uint16 id);
+ bool isPlaying();
uint getNumSamplesPlayed(uint16 id);
// Myst-specific sound functions
@@ -158,7 +159,7 @@ private:
byte *_midiData;
static Audio::AudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL);
- static Audio::AudioStream *makeOldMohawkWaveStream(Common::SeekableReadStream *stream);
+ static Audio::AudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
void initMidi();
Common::Array<SndHandle> _handles;
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 9bf202083a..f481b5ceb2 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -490,6 +490,11 @@ uint32 VideoManager::getElapsedTime(VideoHandle handle) {
return _videoStreams[handle]->getElapsedTime();
}
+uint32 VideoManager::getDuration(VideoHandle handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getDuration();
+}
+
bool VideoManager::endOfVideo(VideoHandle handle) {
assert(handle != NULL_VID_HANDLE);
return _videoStreams[handle].endOfVideo();
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 6b9cfa25d2..e65629a1ec 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -104,6 +104,7 @@ public:
int32 getCurFrame(VideoHandle handle);
uint32 getFrameCount(VideoHandle handle);
uint32 getElapsedTime(VideoHandle handle);
+ uint32 getDuration(VideoHandle videoHandle);
bool endOfVideo(VideoHandle handle);
void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end);
void seekToTime(VideoHandle handle, Audio::Timestamp time);
diff --git a/engines/mohawk/view.cpp b/engines/mohawk/view.cpp
index 241b2c3663..837d386b58 100644
--- a/engines/mohawk/view.cpp
+++ b/engines/mohawk/view.cpp
@@ -421,13 +421,13 @@ void View::installBG(uint16 id) {
void View::setColors(Common::SeekableReadStream *tpalStream) {
uint16 colorStart = tpalStream->readUint16BE();
uint16 colorCount = tpalStream->readUint16BE();
- byte *palette = new byte[colorCount * 4];
+ byte *palette = new byte[colorCount * 3];
for (uint16 i = 0; i < colorCount; i++) {
- palette[i * 4] = tpalStream->readByte();
- palette[i * 4 + 1] = tpalStream->readByte();
- palette[i * 4 + 2] = tpalStream->readByte();
- palette[i * 4 + 3] = tpalStream->readByte();
+ palette[i * 3 + 0] = tpalStream->readByte();
+ palette[i * 3 + 1] = tpalStream->readByte();
+ palette[i * 3 + 2] = tpalStream->readByte();
+ tpalStream->readByte();
}
// TODO: copy into temporary buffer
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 98770b9a6d..133b7bef6c 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -91,7 +91,7 @@ NSArchive::NSArchive(Common::SeekableReadStream *stream, Common::Platform platfo
if (features & GF_DEMO) {
isSmallArchive = stream->size() == SIZEOF_SMALL_ARCHIVE;
} else if (features & GF_LANG_MULT) {
- isSmallArchive = (stream->readUint32BE() != MKID_BE('NDOS'));
+ isSmallArchive = (stream->readUint32BE() != MKTAG('N','D','O','S'));
}
}
@@ -801,7 +801,7 @@ void AmigaDisk_ns::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 b
uint16 planeSize = bytesPerPlane * height;
for (uint32 i = 0; i < numFrames; i++) {
- if (READ_BE_UINT32(src) == MKID_BE('DLTA')) {
+ if (READ_BE_UINT32(src) == MKTAG('D','L','T','A')) {
uint size = READ_BE_UINT32(src + 4);
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 259ad84f69..35441d7e3e 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -152,34 +152,32 @@ void Palette::fadeTo(const Palette& target, uint step) {
if (_data[i] == target._data[i]) continue;
if (_data[i] < target._data[i])
- _data[i] = CLIP(_data[i] + step, (uint)0, (uint)target._data[i]);
+ _data[i] = CLIP(_data[i] + (int)step, (int)0, (int)target._data[i]);
else
- _data[i] = CLIP(_data[i] - step, (uint)target._data[i], (uint)255);
+ _data[i] = CLIP(_data[i] - (int)step, (int)target._data[i], (int)255);
}
return;
}
-uint Palette::fillRGBA(byte *rgba) {
+uint Palette::fillRGB(byte *rgb) {
byte r, g, b;
- byte *hbPal = rgba + _colors * 4;
+ byte *hbPal = rgb + _colors * 3;
for (uint32 i = 0; i < _colors; i++) {
r = (_data[i*3] << 2) | (_data[i*3] >> 4);
g = (_data[i*3+1] << 2) | (_data[i*3+1] >> 4);
b = (_data[i*3+2] << 2) | (_data[i*3+2] >> 4);
- rgba[i*4] = r;
- rgba[i*4+1] = g;
- rgba[i*4+2] = b;
- rgba[i*4+3] = 0;
+ rgb[i*3] = r;
+ rgb[i*3+1] = g;
+ rgb[i*3+2] = b;
if (_hb) {
- hbPal[i*4] = r >> 1;
- hbPal[i*4+1] = g >> 1;
- hbPal[i*4+2] = b >> 1;
- hbPal[i*4+3] = 0;
+ hbPal[i*3] = r >> 1;
+ hbPal[i*3+1] = g >> 1;
+ hbPal[i*3+2] = b >> 1;
}
}
@@ -222,9 +220,9 @@ void Palette::rotate(uint first, uint last, bool forward) {
void Gfx::setPalette(Palette pal) {
- byte sysPal[256*4];
+ byte sysPal[256*3];
- uint n = pal.fillRGBA(sysPal);
+ uint n = pal.fillRGB(sysPal);
_vm->_system->getPaletteManager()->setPalette(sysPal, 0, n);
}
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index afabcad21c..d6732e6fe4 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -250,7 +250,7 @@ public:
void setEntry(uint index, int red, int green, int blue);
void makeGrayscale();
void fadeTo(const Palette& target, uint step);
- uint fillRGBA(byte *rgba);
+ uint fillRGB(byte *rgb);
void rotate(uint first, uint last, bool forward);
};
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 1113eb5dca..3055439e47 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -52,6 +52,8 @@ uint32 _globalFlags = 0;
Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _location(getGameType()),
_dialogueMan(0) {
+ // Setup mixer
+ syncSoundSettings();
_vm = this;
DebugMan.addDebugChannel(kDebugDialogue, "dialogue", "Dialogues debug level");
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 457c421fd7..619a4f7559 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -61,9 +61,7 @@ Common::Error Parallaction_br::init() {
_disk = new DosDisk_br(this);
}
_disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters.
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- MidiDriver *driver = MidiDriver::createMidi(dev);
- _soundManI = new DosSoundMan_br(this, driver);
+ _soundManI = new DosSoundMan_br(this);
} else {
_disk = new AmigaDisk_br(this);
_disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters.
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index c3d917a33d..ffac22e118 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -166,9 +166,7 @@ Common::Error Parallaction_ns::init() {
_disk->init();
if (getPlatform() == Common::kPlatformPC) {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- MidiDriver *driver = MidiDriver::createMidi(dev);
- _soundManI = new DosSoundMan_ns(this, driver);
+ _soundManI = new DosSoundMan_ns(this);
_soundManI->setMusicVolume(ConfMan.getInt("music_volume"));
} else {
_soundManI = new AmigaSoundMan_ns(this);
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index 7b3eff37cb..455189d1fc 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -140,7 +140,7 @@ class DosSoundMan_ns : public SoundMan_ns {
public:
- DosSoundMan_ns(Parallaction_ns *vm, MidiDriver *midiDriver);
+ DosSoundMan_ns(Parallaction_ns *vm);
~DosSoundMan_ns();
void playMusic();
void stopMusic();
@@ -228,7 +228,7 @@ class DosSoundMan_br : public SoundMan_br {
Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
- DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver);
+ DosSoundMan_br(Parallaction_br *vm);
~DosSoundMan_br();
void playMusic();
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index e127cf2838..ee53f9641e 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -27,8 +27,8 @@
#include "common/util.h"
#include "audio/mixer.h"
-#include "audio/mididrv.h"
#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/mods/protracker.h"
#include "audio/decoders/raw.h"
@@ -201,122 +201,76 @@ MidiParser *createParser_MSC() {
}
-class MidiPlayer_MSC : public MidiDriver {
+class MidiPlayer_MSC : public Audio::MidiPlayer {
public:
- enum {
- NUM_CHANNELS = 16
- };
-
- MidiPlayer_MSC(MidiDriver *driver);
- ~MidiPlayer_MSC();
+ MidiPlayer_MSC();
void play(Common::SeekableReadStream *stream);
- void stop();
- void pause(bool p);
- void updateTimer();
- void adjustVolume(int diff);
- void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
- void setLooping(bool loop) { _isLooping = loop; }
-
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ virtual void pause(bool p);
+ virtual void setVolume(int volume);
+ virtual void onTimer();
-private:
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
- static void timerCallback(void *p);
- void setVolumeInternal(int volume);
- Common::Mutex _mutex;
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
+private:
+ void setVolumeInternal(int volume);
bool _paused;
-
- int _masterVolume;
- MidiChannel *_channels[NUM_CHANNELS];
- uint8 _volume[NUM_CHANNELS];
};
-MidiPlayer_MSC::MidiPlayer_MSC(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _paused(false), _masterVolume(0) {
- assert(_driver);
- memset(_channels, 0, sizeof(_channels));
- for (int i = 0; i < NUM_CHANNELS; i++) {
- _volume[i] = 127;
- }
+MidiPlayer_MSC::MidiPlayer_MSC()
+ : _paused(false) {
- open();
-}
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
-MidiPlayer_MSC::~MidiPlayer_MSC() {
- close();
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) {
- if (!stream) {
- stop();
- return;
- }
+ Common::StackLock lock(_mutex);
stop();
+ if (!stream)
+ return;
+
int size = stream->size();
_midiData = (uint8 *)malloc(size);
if (_midiData) {
stream->read(_midiData, size);
delete stream;
- _mutex.lock();
+
+ _parser = createParser_MSC();
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
_isLooping = true;
_isPlaying = true;
- _mutex.unlock();
}
}
-void MidiPlayer_MSC::stop() {
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
- }
- _mutex.unlock();
-}
-
void MidiPlayer_MSC::pause(bool p) {
_paused = p;
setVolumeInternal(_paused ? 0 : _masterVolume);
}
-void MidiPlayer_MSC::updateTimer() {
- if (_paused) {
- return;
- }
-
+void MidiPlayer_MSC::onTimer() {
Common::StackLock lock(_mutex);
- if (_isPlaying) {
+
+ if (!_paused && _isPlaying && _parser) {
_parser->onTimer();
}
}
-void MidiPlayer_MSC::adjustVolume(int diff) {
- setVolume(_masterVolume + diff);
-}
-
void MidiPlayer_MSC::setVolume(int volume) {
_masterVolume = CLIP(volume, 0, 255);
setVolumeInternal(_masterVolume);
@@ -324,76 +278,32 @@ void MidiPlayer_MSC::setVolume(int volume) {
void MidiPlayer_MSC::setVolumeInternal(int volume) {
Common::StackLock lock(_mutex);
- for (int i = 0; i < NUM_CHANNELS; ++i) {
- if (_channels[i]) {
- _channels[i]->volume(_volume[i] * volume / 255);
+ for (int i = 0; i < kNumChannels; ++i) {
+ if (_channelsTable[i]) {
+ _channelsTable[i]->volume(_channelsVolume[i] * volume / 255);
}
}
}
-int MidiPlayer_MSC::open() {
- int ret = _driver->open();
- if (ret == 0) {
- _parser = createParser_MSC();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
- }
- return ret;
-}
-
-void MidiPlayer_MSC::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _driver;
- _driver = 0;
- _parser->setMidiDriver(NULL);
- delete _parser;
- _mutex.unlock();
-}
-
void MidiPlayer_MSC::send(uint32 b) {
+ // FIXME/TODO: Unlike Audio::MidiPlayer::send(), this code
+ // does not handle All Note Off. Is this on purpose?
+ // If not, we could simply remove this method, and use the
+ // inherited one.
const byte ch = b & 0x0F;
byte param2 = (b >> 16) & 0xFF;
switch (b & 0xFFF0) {
case 0x07B0: // volume change
- _volume[ch] = param2;
- break;
- }
-
- if (!_channels[ch]) {
- _channels[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- }
- if (_channels[ch]) {
- _channels[ch]->send(b);
- }
-}
-
-void MidiPlayer_MSC::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
+ _channelsVolume[ch] = param2;
break;
}
-}
-
-void MidiPlayer_MSC::timerCallback(void *p) {
- MidiPlayer_MSC *player = (MidiPlayer_MSC *)p;
- player->updateTimer();
+ sendToChannel(ch, b);
}
-DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm, MidiDriver *driver) : SoundMan_br(vm) {
- _midiPlayer = new MidiPlayer_MSC(driver);
+DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm) : SoundMan_br(vm) {
+ _midiPlayer = new MidiPlayer_MSC();
assert(_midiPlayer);
}
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index 15fdede571..ba81314da6 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -29,6 +29,7 @@
#include "audio/mixer.h"
#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/mods/protracker.h"
#include "audio/decoders/raw.h"
@@ -38,206 +39,75 @@
namespace Parallaction {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
- enum {
- NUM_CHANNELS = 16
- };
-
- MidiPlayer(MidiDriver *driver);
- ~MidiPlayer();
+ MidiPlayer();
void play(Common::SeekableReadStream *stream);
- void stop();
void pause(bool p);
- void updateTimer();
- void adjustVolume(int diff);
- void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
- void setLooping(bool loop) { _isLooping = loop; }
-
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ virtual void onTimer();
private:
-
- static void timerCallback(void *p);
-
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
bool _paused;
- int _masterVolume;
- MidiChannel *_channelsTable[NUM_CHANNELS];
- uint8 _channelsVolume[NUM_CHANNELS];
- Common::Mutex _mutex;
};
-MidiPlayer::MidiPlayer(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _paused(false), _masterVolume(0) {
- assert(_driver);
- memset(_channelsTable, 0, sizeof(_channelsTable));
- for (int i = 0; i < NUM_CHANNELS; i++) {
- _channelsVolume[i] = 127;
- }
+MidiPlayer::MidiPlayer()
+ : _paused(false) {
- open();
-}
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
-MidiPlayer::~MidiPlayer() {
- close();
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer::play(Common::SeekableReadStream *stream) {
- if (!stream) {
- stop();
+ Common::StackLock lock(_mutex);
+
+ stop();
+ if (!stream)
return;
- }
int size = stream->size();
-
_midiData = (uint8 *)malloc(size);
if (_midiData) {
stream->read(_midiData, size);
delete stream;
- _mutex.lock();
+
+ _parser = MidiParser::createParser_SMF();
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
_isLooping = true;
_isPlaying = true;
- _mutex.unlock();
- }
-}
-
-void MidiPlayer::stop() {
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
}
- _mutex.unlock();
}
void MidiPlayer::pause(bool p) {
_paused = p;
- for (int i = 0; i < NUM_CHANNELS; ++i) {
+ for (int i = 0; i < kNumChannels; ++i) {
if (_channelsTable[i]) {
_channelsTable[i]->volume(_paused ? 0 : _channelsVolume[i] * _masterVolume / 255);
}
}
}
-void MidiPlayer::updateTimer() {
- if (_paused) {
- return;
- }
+void MidiPlayer::onTimer() {
+ Common::StackLock lock(_mutex);
- _mutex.lock();
- if (_isPlaying) {
+ if (!_paused && _isPlaying && _parser) {
_parser->onTimer();
}
- _mutex.unlock();
-}
-
-void MidiPlayer::adjustVolume(int diff) {
- setVolume(_masterVolume + diff);
-}
-
-void MidiPlayer::setVolume(int volume) {
- _masterVolume = CLIP(volume, 0, 255);
- _mutex.lock();
- for (int i = 0; i < NUM_CHANNELS; ++i) {
- if (_channelsTable[i]) {
- _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
- }
- }
- _mutex.unlock();
-}
-
-int MidiPlayer::open() {
- int ret = _driver->open();
- if (ret == 0) {
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
- }
- return ret;
-}
-
-void MidiPlayer::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _driver;
- _driver = 0;
- _parser->setMidiDriver(NULL);
- delete _parser;
- _mutex.unlock();
-}
-
-void MidiPlayer::send(uint32 b) {
- byte volume, ch = (byte)(b & 0xF);
- switch (b & 0xFFF0) {
- case 0x07B0: // volume change
- volume = (byte)((b >> 16) & 0x7F);
- _channelsVolume[ch] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- break;
- case 0x7BB0: // all notes off
- if (!_channelsTable[ch]) {
- // channel not yet allocated, no need to send the event
- return;
- }
- break;
- }
-
- if (!_channelsTable[ch]) {
- _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- }
- if (_channelsTable[ch]) {
- _channelsTable[ch]->send(b);
- }
-}
-
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
-// warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiPlayer::timerCallback(void *p) {
- MidiPlayer *player = (MidiPlayer *)p;
-
- player->updateTimer();
}
-DosSoundMan_ns::DosSoundMan_ns(Parallaction_ns *vm, MidiDriver *midiDriver) : SoundMan_ns(vm), _playing(false) {
- _midiPlayer = new MidiPlayer(midiDriver);
+DosSoundMan_ns::DosSoundMan_ns(Parallaction_ns *vm) : SoundMan_ns(vm), _playing(false) {
+ _midiPlayer = new MidiPlayer();
}
DosSoundMan_ns::~DosSoundMan_ns() {
diff --git a/engines/queen/command.cpp b/engines/queen/command.cpp
index 543cd15772..356856e940 100644
--- a/engines/queen/command.cpp
+++ b/engines/queen/command.cpp
@@ -367,6 +367,17 @@ void Command::readCommandsFrom(byte *&ptr) {
memset(&_cmdObject[0], 0, sizeof(CmdObject));
for (i = 1; i <= _numCmdObject; i++) {
_cmdObject[i].readFromBE(ptr);
+
+ // WORKAROUND bug #1858081: Fix an off by one error in the object
+ // command 175. Object 309 should be copied to 308 (disabled).
+ //
+ // _objectData[307].name = -195
+ // _objectData[308].name = 50
+ // _objectData[309].name = -50
+
+ if (i == 175 && _cmdObject[i].id == 320 && _cmdObject[i].dstObj == 307 && _cmdObject[i].srcObj == 309) {
+ _cmdObject[i].dstObj = 308;
+ }
}
}
diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp
index 4557588732..b130b27a89 100644
--- a/engines/queen/display.cpp
+++ b/engines/queen/display.cpp
@@ -159,15 +159,7 @@ void Display::palSet(const uint8 *pal, int start, int end, bool updateScreen) {
debug(9, "Display::palSet(%d, %d)", start, end);
const int numColors = end - start + 1;
assert(numColors <= 256);
- uint8 tempPal[256 * 4];
- pal += start * 3;
- for (int i = 0; i < numColors; i++) {
- tempPal[4 * i + 0] = *pal++;
- tempPal[4 * i + 1] = *pal++;
- tempPal[4 * i + 2] = *pal++;
- tempPal[4 * i + 3] = 0;
- }
- _system->getPaletteManager()->setPalette(tempPal, start, numColors);
+ _system->getPaletteManager()->setPalette(pal + start * 3, start, numColors);
if (updateScreen) {
_vm->input()->delay(20);
}
@@ -851,19 +843,19 @@ void Display::decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dst
uint32 size = READ_BE_UINT32(src + 4);
src += 8;
switch (type) {
- case MKID_BE('BMHD'): {
+ case MKTAG('B','M','H','D'): {
*w = READ_BE_UINT16(src + 0);
*h = READ_BE_UINT16(src + 2);
planeCount = src[8];
planePitch = ((*w + 15) >> 4) * 2;
}
break;
- case MKID_BE('CMAP'): {
+ case MKTAG('C','M','A','P'): {
assert(palStart <= palEnd && palEnd <= size / 3);
memcpy(pal, src + palStart * 3, (palEnd - palStart) * 3);
}
break;
- case MKID_BE('BODY'): {
+ case MKTAG('B','O','D','Y'): {
uint32 planarSize = (*h) * planeCount * planePitch;
uint8 *planarBuf = new uint8[planarSize];
uint8 *dstPlanar = planarBuf;
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index c3bc6d1c17..b03c90f653 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -30,8 +30,6 @@
namespace Queen {
-class AdLibMidiChannel;
-
class AdLibMidiDriver : public MidiDriver_Emulated {
public:
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index 4dc698dac9..58ecfa6d16 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -40,9 +40,9 @@ namespace Queen {
extern MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *);
MidiMusic::MidiMusic(QueenEngine *vm)
- : _isPlaying(false), _looping(false), _randomLoop(false), _masterVolume(192), _buf(0) {
+ : _isPlaying(false), _isLooping(false), _randomLoop(false), _masterVolume(192), _buf(0) {
- memset(_channel, 0, sizeof(_channel));
+ memset(_channelsTable, 0, sizeof(_channelsTable));
_queuePos = _lastSong = _currentSong = 0;
queueClear();
@@ -78,8 +78,10 @@ MidiMusic::MidiMusic(QueenEngine *vm)
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
}
}
+ assert(_driver);
- _driver->open();
+ int ret = _driver->open();
+ assert(ret == 0);
_driver->setTimerCallback(this, &timerCallback);
if (_nativeMT32)
@@ -116,8 +118,8 @@ void MidiMusic::setVolume(int volume) {
_masterVolume = volume;
for (int i = 0; i < 16; ++i) {
- if (_channel[i])
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
+ if (_channelsTable[i])
+ _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
}
}
@@ -154,7 +156,7 @@ bool MidiMusic::queueSong(uint16 songNum) {
void MidiMusic::queueClear() {
_lastSong = _songQueue[0];
_queuePos = 0;
- _looping = _randomLoop = false;
+ _isLooping = _randomLoop = false;
memset(_songQueue, 0, sizeof(_songQueue));
}
@@ -168,7 +170,7 @@ void MidiMusic::send(uint32 b) {
if ((b & 0xFFF0) == 0x07B0) {
// Adjust volume changes by master volume
byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
+ _channelsVolume[channel] = volume;
volume = volume * _masterVolume / 255;
b = (b & 0xFF00FFFF) | (volume << 16);
} else if ((b & 0xF0) == 0xC0 && !_nativeMT32) {
@@ -176,7 +178,7 @@ void MidiMusic::send(uint32 b) {
} else if ((b & 0xFFF0) == 0x007BB0) {
//Only respond to All Notes Off if this channel
//has currently been allocated
- if (_channel[channel])
+ if (!_channelsTable[channel])
return;
}
@@ -188,17 +190,17 @@ void MidiMusic::send(uint32 b) {
if (channel == 5 && _currentSong == 38)
return;
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ if (!_channelsTable[channel])
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- if (_channel[channel])
- _channel[channel]->send(b);
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
switch (type) {
case 0x2F: // End of Track
- if (_looping || _songQueue[1]) {
+ if (_isLooping || _songQueue[1]) {
playMusic();
} else {
stopMusic();
@@ -216,10 +218,9 @@ void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
}
void MidiMusic::onTimer() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
if (_isPlaying)
_parser->onTimer();
- _mutex.unlock();
}
void MidiMusic::queueTuneList(int16 tuneList) {
@@ -317,11 +318,10 @@ void MidiMusic::playMusic() {
stopMusic();
- _mutex.lock();
+ Common::StackLock lock(_mutex);
_parser->loadMusic(musicPtr, size);
_parser->setTrack(0);
_isPlaying = true;
- _mutex.unlock();
debug(8, "Playing song %d [queue position: %d]", songNum, _queuePos);
queueUpdatePos();
@@ -333,7 +333,7 @@ void MidiMusic::queueUpdatePos() {
} else {
if (_queuePos < (MUSIC_QUEUE_SIZE - 1) && _songQueue[_queuePos + 1])
_queuePos++;
- else if (_looping)
+ else if (_isLooping)
_queuePos = 0;
}
}
@@ -347,14 +347,13 @@ uint8 MidiMusic::randomQueuePos() {
if (!queueSize)
return 0;
- return (uint8) _rnd.getRandomNumber(queueSize - 1) & 0xFF;
+ return (uint8)_rnd.getRandomNumber(queueSize - 1) & 0xFF;
}
void MidiMusic::stopMusic() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
_isPlaying = false;
_parser->unloadMusic();
- _mutex.unlock();
}
uint32 MidiMusic::songOffset(uint16 songNum) const {
diff --git a/engines/queen/music.h b/engines/queen/music.h
index fe45d56fde..3e8fc585ca 100644
--- a/engines/queen/music.h
+++ b/engines/queen/music.h
@@ -39,7 +39,7 @@ struct TuneData;
class QueenEngine;
-class MidiMusic : public MidiDriver {
+class MidiMusic : public MidiDriver_BASE {
public:
MidiMusic(QueenEngine *vm);
~MidiMusic();
@@ -50,25 +50,15 @@ public:
void stopSong() { stopMusic(); }
void playMusic();
void stopMusic();
- void setLoop(bool loop) { _looping = loop; }
+ void setLoop(bool loop) { _isLooping = loop; }
void queueTuneList(int16 tuneList);
bool queueSong(uint16 songNum);
void queueClear();
void toggleVChange();
- //MidiDriver interface implementation
- int open() { return 0; }
- void close() {}
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
protected:
@@ -86,15 +76,15 @@ protected:
MidiDriver *_driver;
MidiParser *_parser;
- MidiChannel *_channel[16];
- byte _channelVolume[16];
+ MidiChannel *_channelsTable[16];
+ byte _channelsVolume[16];
bool _adlib;
bool _nativeMT32;
Common::Mutex _mutex;
Common::RandomSource _rnd;
bool _isPlaying;
- bool _looping;
+ bool _isLooping;
bool _randomLoop;
byte _masterVolume;
uint8 _queuePos;
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index 74bb52f574..519f028cda 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -240,14 +240,20 @@ void QueenEngine::checkOptionSettings() {
}
void QueenEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
readOptionSettings();
}
void QueenEngine::readOptionSettings() {
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
_sound->setVolume(ConfMan.getInt("music_volume"));
- _sound->musicToggle(!ConfMan.getBool("music_mute"));
- _sound->sfxToggle(!ConfMan.getBool("sfx_mute"));
- _sound->speechToggle(!ConfMan.getBool("speech_mute"));
+ _sound->musicToggle(!(mute || ConfMan.getBool("music_mute")));
+ _sound->sfxToggle(!(mute || ConfMan.getBool("sfx_mute")));
+ _sound->speechToggle(!(mute || ConfMan.getBool("speech_mute")));
_talkSpeed = (ConfMan.getInt("talkspeed") * (MAX_TEXT_SPEED - MIN_TEXT_SPEED) + 255 / 2) / 255 + MIN_TEXT_SPEED;
_subtitles = ConfMan.getBool("subtitles");
checkOptionSettings();
@@ -397,7 +403,7 @@ Common::InSaveFile *QueenEngine::readGameStateHeader(int slot, GameStateHeader *
char name[20];
makeGameStateName(slot, name);
Common::InSaveFile *file = _saveFileMan->openForLoading(name);
- if (file && file->readUint32BE() == MKID_BE('SCVM')) {
+ if (file && file->readUint32BE() == MKTAG('S','C','V','M')) {
gsh->version = file->readUint32BE();
gsh->flags = file->readUint32BE();
gsh->dataSize = file->readUint32BE();
@@ -470,11 +476,14 @@ Common::Error QueenEngine::run() {
}
_sound = Sound::makeSoundInstance(_mixer, this, _resource->getCompression());
+
_walk = new Walk(this);
//_talkspeedScale = (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 255.0;
registerDefaultSettings();
- readOptionSettings();
+
+ // Setup mixer
+ syncSoundSettings();
_logic->start();
if (ConfMan.hasKey("save_slot") && canLoadOrSave()) {
diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp
index a70d1f1613..e8519ee68b 100644
--- a/engines/queen/resource.cpp
+++ b/engines/queen/resource.cpp
@@ -132,7 +132,7 @@ void Resource::loadTextFile(const char *filename, Common::StringArray &stringLis
bool Resource::detectVersion(DetectedGameVersion *ver, Common::File *f) {
memset(ver, 0, sizeof(DetectedGameVersion));
- if (f->readUint32BE() == MKID_BE('QTBL')) {
+ if (f->readUint32BE() == MKTAG('Q','T','B','L')) {
f->read(ver->str, 6);
f->skip(2);
ver->compression = f->readByte();
@@ -269,7 +269,7 @@ void Resource::seekResourceFile(int num, uint32 offset) {
void Resource::readTableFile(uint8 version, uint32 offset) {
Common::File tableFile;
tableFile.open(_tableFilename);
- if (tableFile.isOpen() && tableFile.readUint32BE() == MKID_BE('QTBL')) {
+ if (tableFile.isOpen() && tableFile.readUint32BE() == MKTAG('Q','T','B','L')) {
uint32 tableVersion = tableFile.readUint32BE();
if (version > tableVersion) {
error("The game you are trying to play requires version %d of queen.tbl, "
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index 6eb7362338..a34af99ec3 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -192,10 +192,12 @@ Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 comp
}
void Sound::setVolume(int vol) {
- _musicVolume = vol;
+ if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
+ _musicVolume = 0;
+ else
+ _musicVolume = vol;
+
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicVolume);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
}
void Sound::saveState(byte *&ptr) {
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index e43f1ee5c7..b1bcc99295 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -264,7 +264,7 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s
if (version < 4)
warning("This savegame is not endian-safe. There may be problems");
- if (type != MKID_BE('SAGA')) {
+ if (type != MKTAG('S','A','G','A')) {
error("SagaEngine::load wrong save game format");
}
@@ -372,12 +372,13 @@ Common::Error SagaEngine::saveGameState(int slot, const char *desc) {
}
bool SagaEngine::canLoadGameStateCurrently() {
- return !_scene->isInIntro();
+ return !_scene->isInIntro() &&
+ (_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
}
bool SagaEngine::canSaveGameStateCurrently() {
return !_scene->isInIntro() &&
- (_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
+ (_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
}
} // End of namespace Saga
diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp
index 01e74d2984..2434f7aad8 100644
--- a/engines/saga/font.cpp
+++ b/engines/saga/font.cpp
@@ -434,7 +434,6 @@ int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags
int textWidth;
int textLength;
int fitWidth;
- const char *startPointer;
const char *searchPointer;
const char *measurePointer;
const char *foundPointer;
@@ -465,7 +464,6 @@ int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags
len_total = 0;
wc = 0;
- startPointer = text;
measurePointer = text;
searchPointer = text;
endPointer = text + textLength;
@@ -498,7 +496,6 @@ int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags
len_total = 0;
wc = 0;
measurePointer = searchPointer;
- startPointer = searchPointer;
} else {
// Word will fit ok
w_total += w;
diff --git a/engines/saga/gfx.cpp b/engines/saga/gfx.cpp
index 771284f632..5fc2082178 100644
--- a/engines/saga/gfx.cpp
+++ b/engines/saga/gfx.cpp
@@ -201,20 +201,19 @@ void Gfx::setPalette(const PalEntry *pal, bool full) {
numcolors = 248;
}
- for (i = 0, ppal = &_currentPal[from * 4]; i < numcolors; i++, ppal += 4) {
+ for (i = 0, ppal = &_currentPal[from * 3]; i < numcolors; i++, ppal += 3) {
ppal[0] = _globalPalette[i].red = pal[i].red;
ppal[1] = _globalPalette[i].green = pal[i].green;
ppal[2] = _globalPalette[i].blue = pal[i].blue;
- ppal[3] = 0;
}
// Color 0 should always be black in IHNM
if (_vm->getGameId() == GID_IHNM)
- memset(&_currentPal[0 * 4], 0, 4);
+ memset(&_currentPal[0 * 3], 0, 3);
// Make 256th color black. See bug #1256368
if ((_vm->getPlatform() == Common::kPlatformMacintosh) && !_vm->_scene->isInIntro())
- memset(&_currentPal[255 * 4], 0, 4);
+ memset(&_currentPal[255 * 3], 0, 3);
_system->getPaletteManager()->setPalette(_currentPal, 0, PAL_ENTRIES);
}
@@ -225,32 +224,28 @@ void Gfx::setPaletteColor(int n, int r, int g, int b) {
// This function may get called a lot. To avoid forcing full-screen
// updates, only update the palette if the color actually changes.
- if (_currentPal[4 * n + 0] != r) {
- _currentPal[4 * n + 0] = _globalPalette[n].red = r;
+ if (_currentPal[3 * n + 0] != r) {
+ _currentPal[3 * n + 0] = _globalPalette[n].red = r;
update = true;
}
- if (_currentPal[4 * n + 1] != g) {
- _currentPal[4 * n + 1] = _globalPalette[n].green = g;
+ if (_currentPal[3 * n + 1] != g) {
+ _currentPal[3 * n + 1] = _globalPalette[n].green = g;
update = true;
}
- if (_currentPal[4 * n + 2] != b) {
- _currentPal[4 * n + 2] = _globalPalette[n].blue = b;
- update = true;
- }
- if (_currentPal[4 * n + 3] != 0) {
- _currentPal[4 * n + 3] = 0;
+ if (_currentPal[3 * n + 2] != b) {
+ _currentPal[3 * n + 2] = _globalPalette[n].blue = b;
update = true;
}
if (update)
- _system->getPaletteManager()->setPalette(_currentPal, n, 1);
+ _system->getPaletteManager()->setPalette(_currentPal + n * 3, n, 1);
}
void Gfx::getCurrentPal(PalEntry *src_pal) {
int i;
byte *ppal;
- for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 4) {
+ for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 3) {
src_pal[i].red = ppal[0];
src_pal[i].green = ppal[1];
src_pal[i].blue = ppal[2];
@@ -285,7 +280,7 @@ void Gfx::palToBlack(PalEntry *srcPal, double percent) {
fpercent = 1.0 - fpercent;
// Use the correct percentage change per frame for each palette entry
- for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 4) {
+ for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 3) {
if (i < from || i >= from + numcolors)
palE = &_globalPalette[i];
else
@@ -314,16 +309,15 @@ void Gfx::palToBlack(PalEntry *srcPal, double percent) {
} else {
ppal[2] = (byte) new_entry;
}
- ppal[3] = 0;
}
// Color 0 should always be black in IHNM
if (_vm->getGameId() == GID_IHNM)
- memset(&_currentPal[0 * 4], 0, 4);
+ memset(&_currentPal[0 * 3], 0, 3);
// Make 256th color black. See bug #1256368
if ((_vm->getPlatform() == Common::kPlatformMacintosh) && !_vm->_scene->isInIntro())
- memset(&_currentPal[255 * 4], 0, 4);
+ memset(&_currentPal[255 * 3], 0, 3);
_system->getPaletteManager()->setPalette(_currentPal, 0, PAL_ENTRIES);
}
@@ -352,7 +346,7 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
fpercent = percent * percent;
// Use the correct percentage change per frame for each palette entry
- for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 4) {
+ for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 3) {
if (i < from || i >= from + numcolors)
palE = &_globalPalette[i];
else
@@ -381,16 +375,15 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
} else {
ppal[2] = (byte) new_entry;
}
- ppal[3] = 0;
}
// Color 0 should always be black in IHNM
if (_vm->getGameId() == GID_IHNM)
- memset(&_currentPal[0 * 4], 0, 4);
+ memset(&_currentPal[0 * 3], 0, 3);
// Make 256th color black. See bug #1256368
if ((_vm->getPlatform() == Common::kPlatformMacintosh) && !_vm->_scene->isInIntro())
- memset(&_currentPal[255 * 4], 0, 4);
+ memset(&_currentPal[255 * 3], 0, 3);
_system->getPaletteManager()->setPalette(_currentPal, 0, PAL_ENTRIES);
}
@@ -420,10 +413,10 @@ void Gfx::palFade(PalEntry *srcPal, int16 from, int16 to, int16 start, int16 num
if (from > to)
percent = 1.0 - percent;
- byte fadePal[PAL_ENTRIES * 4];
+ byte fadePal[PAL_ENTRIES * 3];
// Use the correct percentage change per frame for each palette entry
- for (i = start, ppal = fadePal + start * 4; i < start + numColors; i++, ppal += 4) {
+ for (i = start, ppal = fadePal + start * 3; i < start + numColors; i++, ppal += 3) {
palE = &srcPal[i];
new_entry = (int)(palE->red * percent);
@@ -449,13 +442,12 @@ void Gfx::palFade(PalEntry *srcPal, int16 from, int16 to, int16 start, int16 num
} else {
ppal[2] = (byte) new_entry;
}
- ppal[3] = 0;
}
// Color 0 should always be black in IHNM
- memset(&fadePal[0 * 4], 0, 4);
+ memset(&fadePal[0 * 3], 0, 3);
- _system->getPaletteManager()->setPalette(&fadePal[start * 4], start, numColors);
+ _system->getPaletteManager()->setPalette(&fadePal[start * 3], start, numColors);
}
#endif
diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h
index 18d88503ce..33fac10c63 100644
--- a/engines/saga/gfx.h
+++ b/engines/saga/gfx.h
@@ -224,7 +224,7 @@ public:
private:
Surface _backBuffer;
- byte _currentPal[PAL_ENTRIES * 4];
+ byte _currentPal[PAL_ENTRIES * 3];
OSystem *_system;
SagaEngine *_vm;
diff --git a/engines/saga/image.cpp b/engines/saga/image.cpp
index 87d9e514c8..ac9fe94f2f 100644
--- a/engines/saga/image.cpp
+++ b/engines/saga/image.cpp
@@ -322,7 +322,6 @@ void SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns,
int rowjump_src;
int rowjump_dest;
const byte *src_p;
- byte *dst_p;
const byte *srcptr1, *srcptr2, *srcptr3, *srcptr4;
byte *dstptr1, *dstptr2, *dstptr3, *dstptr4;
@@ -332,7 +331,6 @@ void SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns,
assert(scanlines > 0);
src_p = src_buf;
- dst_p = dst_buf + columns;
srcptr1 = src_p;
srcptr2 = src_p + 1;
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index dd3034cdb9..eb0a911555 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -44,85 +44,88 @@ namespace Saga {
#define MUSIC_SUNSPOT 26
MusicDriver::MusicDriver() : _isGM(false) {
- memset(_channel, 0, sizeof(_channel));
- _masterVolume = 0;
- _nativeMT32 = ConfMan.getBool("native_mt32");
+
+ MidiPlayer::createDriver();
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = MidiDriver::createMidi(dev);
_driverType = MidiDriver::getMusicType(dev);
- if (isMT32())
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- this->open();
-}
+ int retValue = _driver->open();
+ if (retValue == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
-MusicDriver::~MusicDriver() {
- this->close();
- delete _driver;
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
-int MusicDriver::open() {
- int retValue = _driver->open();
- if (retValue)
- return retValue;
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
+void MusicDriver::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ // Remap MT32 instruments to General Midi
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+ Audio::MidiPlayer::send(b);
+}
- return 0;
+void MusicDriver::metaEvent(byte type, byte *data, uint16 length) {
+ // TODO: Seems SAGA does not want / need to handle end-of-track events?
}
-void MusicDriver::setVolume(int volume) {
- volume = CLIP(volume, 0, 255);
+void MusicDriver::play(SagaEngine *vm, ByteArray *buffer, bool loop) {
+ if (buffer->size() < 4) {
+ error("Music::play() wrong music resource size");
+ }
- if (_masterVolume == volume)
- return;
+ // Check if the game is using XMIDI or SMF music
+ if (vm->getGameId() == GID_IHNM && vm->isMacResources()) {
+ // Just set an XMIDI parser for Mac IHNM for now
+ _parser = MidiParser::createParser_XMIDI();
+ } else {
+ if (!memcmp(buffer->getBuffer(), "FORM", 4)) {
+ _parser = MidiParser::createParser_XMIDI();
+ // ITE had MT32 mapped instruments
+ _isGM = (vm->getGameId() != GID_ITE);
+ } else {
+ _parser = MidiParser::createParser_SMF();
+ // ITE with standalone MIDI files is General MIDI
+ _isGM = (vm->getGameId() == GID_ITE);
+ }
+ }
+
+ if (!_parser->loadMusic(buffer->getBuffer(), buffer->size()))
+ error("Music::play() wrong music resource");
- _masterVolume = volume;
+ _parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+ _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
- Common::StackLock lock(_mutex);
+ // Handle music looping
+ _parser->property(MidiParser::mpAutoLoop, loop);
+// _isLooping = loop;
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
- }
+ _isPlaying = true;
}
-void MusicDriver::send(uint32 b) {
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !isMT32()) {
- // Remap MT32 instruments to General Midi
- b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
- } else if ((b & 0xFFF0) == 0x007BB0) {
- // Only respond to All Notes Off if this channel
- // has currently been allocated
- if (!_channel[channel])
- return;
- }
+void MusicDriver::pause() {
+ _isPlaying = false;
+}
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- else
- _channel[channel]->send(b);
+void MusicDriver::resume() {
+ _isPlaying = true;
}
+
Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_currentVolume = 0;
_currentMusicBuffer = NULL;
- _driver = new MusicDriver();
+ _player = new MusicDriver();
_digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE);
- if (!_driver->isAdlib())
+ if (!_player->isAdlib())
_musicContext = _vm->_resource->getContext(GAME_MUSICFILE_GM);
else
_musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM);
@@ -159,55 +162,19 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
}
}
- // Check if the game is using XMIDI or SMF music
- if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
- // Just set an XMIDI parser for Mac IHNM for now
- _parser = MidiParser::createParser_XMIDI();
- } else {
- ByteArray resourceData;
- int resourceId = (_vm->getGameId() == GID_ITE ? 9 : 0);
- _vm->_resource->loadResource(_musicContext, resourceId, resourceData);
- if (resourceData.size() < 4) {
- error("Music::Music Unable to load midi resource data");
- }
- if (!memcmp(resourceData.getBuffer(), "FORM", 4)) {
- _parser = MidiParser::createParser_XMIDI();
- // ITE had MT32 mapped instruments
- _driver->setGM(_vm->getGameId() != GID_ITE);
- } else {
- _parser = MidiParser::createParser_SMF();
- // ITE with standalone MIDI files is General MIDI
- _driver->setGM(_vm->getGameId() == GID_ITE);
- }
- }
-
- _parser->setMidiDriver(_driver);
- _parser->setTimerRate(_driver->getBaseTempo());
- _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
- _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
-
_digitalMusic = false;
}
Music::~Music() {
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
_mixer->stopHandle(_musicHandle);
- _driver->setTimerCallback(NULL, NULL);
- delete _driver;
- _parser->setMidiDriver(NULL);
- delete _parser;
+ delete _player;
}
void Music::musicVolumeGaugeCallback(void *refCon) {
((Music *)refCon)->musicVolumeGauge();
}
-void Music::onTimer(void *refCon) {
- Music *music = (Music *)refCon;
- Common::StackLock lock(music->_driver->_mutex);
- music->_parser->onTimer();
-}
-
void Music::musicVolumeGauge() {
int volume;
@@ -223,7 +190,7 @@ void Music::musicVolumeGauge() {
volume = 1;
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
- _driver->setVolume(volume);
+ _player->setVolume(volume);
if (_currentVolumePercent == 100) {
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
@@ -239,8 +206,11 @@ void Music::setVolume(int volume, int time) {
volume = 255;
if (time == 1) {
+ if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
+ volume = 0;
+
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
- _driver->setVolume(volume);
+ _player->setVolume(volume);
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
_currentVolume = volume;
return;
@@ -250,7 +220,7 @@ void Music::setVolume(int volume, int time) {
}
bool Music::isPlaying() {
- return _mixer->isSoundHandleActive(_musicHandle) || _parser->isPlaying();
+ return _mixer->isSoundHandleActive(_musicHandle) || _player->isPlaying();
}
void Music::play(uint32 resourceId, MusicFlags flags) {
@@ -265,7 +235,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_trackNumber = resourceId;
_mixer->stopHandle(_musicHandle);
- _parser->unloadMusic();
+ _player->stop();
int realTrackNumber;
@@ -395,33 +365,20 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_vm->_resource->loadResource(_musicContext, resourceId, *_currentMusicBuffer);
}
- if (_currentMusicBuffer->size() < 4) {
- error("Music::play() wrong music resource size");
- }
-
- if (!_parser->loadMusic(_currentMusicBuffer->getBuffer(), _currentMusicBuffer->size()))
- error("Music::play() wrong music resource");
-
- _parser->setTrack(0);
- _driver->setTimerCallback(this, &onTimer);
-
+ _player->play(_vm, _currentMusicBuffer, (flags & MUSIC_LOOP));
setVolume(_vm->_musicVolume);
-
- // Handle music looping
- _parser->property(MidiParser::mpAutoLoop, (flags & MUSIC_LOOP) ? 1 : 0);
}
void Music::pause() {
- _driver->setTimerCallback(NULL, NULL);
+ _player->pause();
}
void Music::resume() {
- _driver->setTimerCallback(this, &onTimer);
+ _player->resume();
}
void Music::stop() {
- _driver->setTimerCallback(NULL, NULL);
- _parser->unloadMusic();
+ _player->stop();
}
} // End of namespace Saga
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 7d599d91c2..465d61e366 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -28,7 +28,7 @@
#ifndef SAGA_MUSIC_H
#define SAGA_MUSIC_H
-#include "audio/mididrv.h"
+#include "audio/midiplayer.h"
#include "audio/midiparser.h"
#include "audio/mixer.h"
#include "audio/decoders/mp3.h"
@@ -44,50 +44,26 @@ enum MusicFlags {
MUSIC_DEFAULT = 0xffff
};
-class MusicDriver : public MidiDriver {
+class MusicDriver : public Audio::MidiPlayer {
public:
MusicDriver();
- ~MusicDriver();
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
+ void play(SagaEngine *vm, ByteArray *buffer, bool loop);
+ virtual void pause();
+ virtual void resume();
- bool isAdlib() { return _driverType == MT_ADLIB; }
- bool isMT32() { return _driverType == MT_MT32 || _nativeMT32; }
- void setGM(bool isGM) { _isGM = isGM; }
+ bool isAdlib() const { return _driverType == MT_ADLIB; }
- //MidiDriver interface implementation
- int open();
- void close() { _driver->close(); }
- void send(uint32 b);
+ // FIXME
+ bool isPlaying() const { return _parser && _parser->isPlaying(); }
- void metaEvent(byte type, byte *data, uint16 length) {}
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); }
- uint32 getBaseTempo() { return _driver->getBaseTempo(); }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- Common::Mutex _mutex;
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
protected:
-
- static void onTimer(void *data);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
MusicType _driverType;
- byte _channelVolume[16];
bool _isGM;
- bool _nativeMT32;
-
- byte _masterVolume;
-
- byte *_musicData;
- uint16 *_buf;
- size_t _musicDataSize;
};
class Music {
@@ -112,7 +88,7 @@ private:
SagaEngine *_vm;
Audio::Mixer *_mixer;
- MusicDriver *_driver;
+ MusicDriver *_player;
Audio::SoundHandle _musicHandle;
uint32 _trackNumber;
@@ -123,7 +99,6 @@ private:
ResourceContext *_musicContext;
ResourceContext *_digitalMusicContext;
- MidiParser *_parser;
static void musicVolumeGaugeCallback(void *refCon);
diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp
index 2ec2099c8d..21cf0ef4c1 100644
--- a/engines/saga/resource_hrs.cpp
+++ b/engines/saga/resource_hrs.cpp
@@ -62,7 +62,7 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
readElement(_file, origin);
// Check if the file is valid
- if (origin.id != MKID_BE('HRES')) { // header
+ if (origin.id != MKTAG('H','R','E','S')) { // header
return false;
}
diff --git a/engines/saga/resource_rsc.cpp b/engines/saga/resource_rsc.cpp
index 42c4dc05e8..089757ca27 100644
--- a/engines/saga/resource_rsc.cpp
+++ b/engines/saga/resource_rsc.cpp
@@ -30,7 +30,7 @@
namespace Saga {
-#define ID_MIDI MKID_BE('Midi')
+#define ID_MIDI MKTAG('M','i','d','i')
bool ResourceContext_RSC::loadMacMIDI() {
// Sanity check
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 2e34b49dc5..62493f5eac 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -625,6 +625,8 @@ GUI::Debugger *SagaEngine::getDebugger() {
}
void SagaEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
_subtitlesEnabled = ConfMan.getBool("subtitles");
_readingSpeed = getTalkspeed();
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index c5388d6878..9edb79fa7c 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -151,7 +151,7 @@ void SagaEngine::fillSaveList() {
_saveHeader.version = in->readUint32LE();
in->read(_saveHeader.name, sizeof(_saveHeader.name));
- if (_saveHeader.type != MKID_BE('SAGA')) {
+ if (_saveHeader.type != MKTAG('S','A','G','A')) {
warning("SagaEngine::load wrong save %s format", name);
i++;
continue;
@@ -175,7 +175,7 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
return;
}
- _saveHeader.type = MKID_BE('SAGA');
+ _saveHeader.type = MKTAG('S','A','G','A');
_saveHeader.size = 0;
_saveHeader.version = CURRENT_SAGA_VER;
// Note that IHNM has a smaller save title size than ITE
@@ -287,7 +287,7 @@ void SagaEngine::load(const char *fileName) {
if (_saveHeader.version < 4)
warning("This savegame is not endian-safe. There may be problems");
- if (_saveHeader.type != MKID_BE('SAGA')) {
+ if (_saveHeader.type != MKTAG('S','A','G','A')) {
error("SagaEngine::load wrong save game format");
}
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 3ae2f19e1b..bd1d6e5d84 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -160,7 +160,7 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) {
}
// Script export segment (lookup table)
- uint32 saga2ExportSegId = MKID_BE('_EXP');
+ uint32 saga2ExportSegId = MKTAG('_','E','X','P');
int32 entryNum = _scriptContext->getEntryNum(saga2ExportSegId);
if (entryNum < 0)
error("Unable to locate the script's export segment");
@@ -176,7 +176,7 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) {
// Script data segment
/*
- uint32 saga2DataSegId = MKID_BE('__DA');
+ uint32 saga2DataSegId = MKTAG('_','_','D','A');
entryNum = _scriptContext->getEntryNum(saga2DataSegId);
if (entryNum < 0)
error("Unable to locate the script's data segment");
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index 07e8487ee4..8ffce4e6cd 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -175,8 +175,12 @@ void Sound::stopAll() {
}
void Sound::setVolume() {
- _vm->_soundVolume = ConfMan.getInt("sfx_volume");
- _vm->_speechVolume = ConfMan.getInt("speech_volume");
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _vm->_soundVolume = mute ? 0 : ConfMan.getInt("sfx_volume");
+ _vm->_speechVolume = mute ? 0 : ConfMan.getInt("speech_volume");
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_soundVolume);
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_speechVolume);
}
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index d77ac858c8..7c351c6220 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -40,12 +40,16 @@
#include "sci/sound/music.h"
#include "sci/sound/drivers/mididriver.h"
#include "sci/sound/drivers/map-mt32-to-gm.h"
+#include "sci/graphics/animate.h"
+#include "sci/graphics/cache.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint.h"
#include "sci/graphics/paint16.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/ports.h"
+#include "sci/graphics/view.h"
#include "sci/parser/vocabulary.h"
@@ -123,6 +127,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
DCmd_Register("undither", WRAP_METHOD(Console, cmdUndither));
DCmd_Register("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize));
DCmd_Register("play_video", WRAP_METHOD(Console, cmdPlayVideo));
+ DCmd_Register("animate_list", WRAP_METHOD(Console, cmdAnimateList));
+ DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias
+ DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList));
+ DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias
// Segments
DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable));
DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias
@@ -354,6 +362,8 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" draw_cel - Draws a cel from a view resource\n");
DebugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n");
DebugPrintf(" undither - Enable/disable undithering\n");
+ DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n");
+ DebugPrintf(" animate_object_list / al - Shows the current list of objects in kAnimate's draw list\n");
DebugPrintf("\n");
DebugPrintf("Segments:\n");
DebugPrintf(" segment_table / segtable - Lists all segments\n");
@@ -623,7 +633,7 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) {
bool Console::cmdRegisters(int argc, const char **argv) {
EngineState *s = _engine->_gamestate;
DebugPrintf("Current register values:\n");
- DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjust);
+ DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest);
if (!s->_executionStack.empty()) {
DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n",
@@ -1434,7 +1444,7 @@ bool Console::cmdSaid(int argc, const char **argv) {
_engine->getVocabulary()->dumpParseTree();
_engine->getVocabulary()->parserIsValid = true;
- int ret = said(_engine->_gamestate, (byte*)spec, true);
+ int ret = said((byte*)spec, true);
DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match"));
}
@@ -1503,7 +1513,14 @@ bool Console::cmdDrawCel(int argc, const char **argv) {
uint16 loopNo = atoi(argv[2]);
uint16 celNo = atoi(argv[3]);
- _engine->_gfxPaint->kernelDrawCel(resourceId, loopNo, celNo, 50, 50, 0, 0, false, NULL_REG);
+ if (_engine->_gfxPaint16) {
+ _engine->_gfxPaint16->kernelDrawCel(resourceId, loopNo, celNo, 50, 50, 0, 0, 128, 128, false, NULL_REG);
+ } else {
+ GfxView *view = _engine->_gfxCache->getView(resourceId);
+ Common::Rect celRect(50, 50, 50 + view->getWidth(loopNo, celNo), 50 + view->getHeight(loopNo, celNo));
+ view->draw(celRect, celRect, celRect, loopNo, celNo, 255, 0, false);
+ _engine->_gfxScreen->copyRectToScreen(celRect);
+ }
return true;
}
@@ -1567,6 +1584,22 @@ bool Console::cmdPlayVideo(int argc, const char **argv) {
}
}
+bool Console::cmdAnimateList(int argc, const char **argv) {
+ if (_engine->_gfxAnimate) {
+ DebugPrintf("Animate list:\n");
+ _engine->_gfxAnimate->printAnimateList(this);
+ }
+ return true;
+}
+
+bool Console::cmdWindowList(int argc, const char **argv) {
+ if (_engine->_gfxPorts) {
+ DebugPrintf("Window list:\n");
+ _engine->_gfxPorts->printWindowList(this);
+ }
+ return true;
+
+}
bool Console::cmdParseGrammar(int argc, const char **argv) {
DebugPrintf("Parse grammar, in strict GNF:\n");
@@ -1701,9 +1734,7 @@ bool Console::segmentInfo(int nr) {
for (uint i = 0; i < ct->_table.size(); i++)
if (ct->isValidEntry(i)) {
- reg_t objpos;
- objpos.offset = i;
- objpos.segment = nr;
+ reg_t objpos = make_reg(nr, i);
DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos));
// Object header
const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos());
@@ -2189,7 +2220,7 @@ bool Console::cmdStack(int argc, const char **argv) {
return true;
}
- ExecStack &xs = _engine->_gamestate->_executionStack.back();
+ const ExecStack &xs = _engine->_gamestate->_executionStack.back();
int nr = atoi(argv[1]);
for (int i = nr; i > 0; i--) {
@@ -2438,12 +2469,12 @@ bool Console::cmdScriptSteps(int argc, const char **argv) {
bool Console::cmdBacktrace(int argc, const char **argv) {
DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase);
- Common::List<ExecStack>::iterator iter;
+ Common::List<ExecStack>::const_iterator iter;
uint i = 0;
for (iter = _engine->_gamestate->_executionStack.begin();
iter != _engine->_gamestate->_executionStack.end(); ++iter, ++i) {
- ExecStack &call = *iter;
+ const ExecStack &call = *iter;
const char *objname = _engine->_gamestate->_segMan->getObjectName(call.sendp);
int paramc, totalparamc;
@@ -2607,7 +2638,7 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
const Object *obj = _engine->_gamestate->_segMan->getObject(objAddr);
int selectorId = _engine->getKernel()->findSelector(argv[2]);
- reg_t addr;
+ reg_t addr = NULL_REG;
if (!obj) {
DebugPrintf("Not an object.");
@@ -2626,13 +2657,22 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
for (int i = 3; i < argc; i++) {
if (!scumm_stricmp(argv[i], "bwt"))
- printBytecode = true;
- else if (!scumm_stricmp(argv[i], "bc"))
printBWTag = true;
+ else if (!scumm_stricmp(argv[i], "bc"))
+ printBytecode = true;
}
+ reg_t farthestTarget = addr;
do {
+ reg_t prevAddr = addr;
+ reg_t jumpTarget;
+ if (isJumpOpcode(_engine->_gamestate, addr, jumpTarget)) {
+ if (jumpTarget > farthestTarget)
+ farthestTarget = jumpTarget;
+ }
addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode);
+ if (addr.isNull() && prevAddr < farthestTarget)
+ addr = prevAddr + 1; // skip past the ret
} while (addr.offset > 0);
return true;
@@ -2699,26 +2739,30 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
int scriptSegment;
Script *script;
- SegManager *segMan = _engine->getEngineState()->_segMan;
+ // Create a custom segment manager here, so that the game's segment
+ // manager won't be affected by loading and unloading scripts here.
+ SegManager *customSegMan = new SegManager(_engine->getResMan());
while (itr != resources->end()) {
- if (_engine->getGameId() == GID_KQ5 && itr->getNumber() == 980) {
- // Ignore script 980 in KQ5. Seems to be a leftover, as it
- // uses a superclass from script 988, which doesn't exist
+ // Ignore specific leftover scripts, which require other non-existing scripts
+ if ((_engine->getGameId() == GID_HOYLE3 && itr->getNumber() == 995) ||
+ (_engine->getGameId() == GID_KQ5 && itr->getNumber() == 980) ||
+ (_engine->getGameId() == GID_SLATER && itr->getNumber() == 947) ||
+ (_engine->getGameId() == GID_MOTHERGOOSE256 && itr->getNumber() == 980)) {
itr++;
continue;
}
// Load script
- scriptSegment = segMan->instantiateScript(itr->getNumber());
- script = segMan->getScript(scriptSegment);
+ scriptSegment = customSegMan->instantiateScript(itr->getNumber());
+ script = customSegMan->getScript(scriptSegment);
// Iterate through all the script's objects
ObjMap::iterator it;
const ObjMap::iterator end = script->_objects.end();
for (it = script->_objects.begin(); it != end; ++it) {
- const Object *obj = segMan->getObject(it->_value.getPos());
- const char *objName = segMan->getObjectName(it->_value.getPos());
+ const Object *obj = customSegMan->getObject(it->_value.getPos());
+ const char *objName = customSegMan->getObjectName(it->_value.getPos());
// Now dissassemble each method of the script object
for (uint16 i = 0; i < obj->getMethodCount(); i++) {
@@ -2761,10 +2805,12 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
} // for (uint16 i = 0; i < obj->getMethodCount(); i++)
} // for (it = script->_objects.begin(); it != end; ++it)
- segMan->uninstantiateScript(itr->getNumber());
+ customSegMan->uninstantiateScript(itr->getNumber());
++itr;
}
+ delete customSegMan;
+
delete resources;
}
@@ -3108,10 +3154,9 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
}
bool Console::cmdBreakpointFunction(int argc, const char **argv) {
- // TODO/FIXME: Why does this accept 2 parameters (the high and the low part of the address)?"
if (argc != 3) {
DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
- DebugPrintf("Usage: %s <addr1> <addr2>\n", argv[0]);
+ DebugPrintf("Usage: %s <script number> <export number\n", argv[0]);
return true;
}
@@ -3120,6 +3165,7 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) {
A breakpoint set on an invalid method name will just never trigger. */
Breakpoint bp;
bp.type = BREAK_EXPORT;
+ // script number, export number
bp.address = (atoi(argv[1]) << 16 | atoi(argv[2]));
_debugState._breakpoints.push_back(bp);
@@ -3758,11 +3804,16 @@ int Console::printObject(reg_t pos) {
return 0;
}
+static void printChar(byte c) {
+ if (c < 32 || c >= 127)
+ c = '.';
+ debugN("%c", c);
+}
+
void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startOffset, bool isArray) {
// reg_t version of Common::hexdump
assert(1 <= regsPerLine && regsPerLine <= 8);
int i;
- byte c;
int offset = startOffset;
while (len >= regsPerLine) {
debugN("%06x: ", offset);
@@ -3771,14 +3822,13 @@ void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startO
}
debugN(" |");
for (i = 0; i < regsPerLine; i++) {
- c = data[i].toUint16() & 0xff;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
- c = data[i].toUint16() >> 8;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
+ if (g_sci->isBE()) {
+ printChar(data[i].toUint16() >> 8);
+ printChar(data[i].toUint16() & 0xff);
+ } else {
+ printChar(data[i].toUint16() & 0xff);
+ printChar(data[i].toUint16() >> 8);
+ }
}
debugN("|\n");
data += regsPerLine;
@@ -3798,14 +3848,13 @@ void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startO
}
debugN(" |");
for (i = 0; i < len; i++) {
- c = data[i].toUint16() & 0xff;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
- c = data[i].toUint16() >> 8;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
+ if (g_sci->isBE()) {
+ printChar(data[i].toUint16() >> 8);
+ printChar(data[i].toUint16() & 0xff);
+ } else {
+ printChar(data[i].toUint16() & 0xff);
+ printChar(data[i].toUint16() >> 8);
+ }
}
for (; i < regsPerLine; i++)
debugN(" ");
diff --git a/engines/sci/console.h b/engines/sci/console.h
index b0a1de6ebd..93ccc45503 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -37,6 +37,7 @@ class SciEngine;
struct List;
reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode);
+bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpOffset);
class Console : public GUI::Debugger {
public:
@@ -94,6 +95,8 @@ private:
bool cmdUndither(int argc, const char **argv);
bool cmdPicVisualize(int argc, const char **argv);
bool cmdPlayVideo(int argc, const char **argv);
+ bool cmdAnimateList(int argc, const char **argv);
+ bool cmdWindowList(int argc, const char **argv);
// Segments
bool cmdPrintSegmentTable(int argc, const char **argv);
bool cmdSegmentInfo(int argc, const char **argv);
diff --git a/engines/sci/debug.h b/engines/sci/debug.h
index d9959f0b7f..8ddbbd0d45 100644
--- a/engines/sci/debug.h
+++ b/engines/sci/debug.h
@@ -34,18 +34,18 @@ namespace Sci {
// These types are used both as identifiers and as elements of bitfields
enum BreakpointType {
/**
- * Break when selector is executed. data contains (char *) selector name
+ * Break when a selector is executed. Data contains (char *) selector name
* (in the format Object::Method)
*/
- BREAK_SELECTOREXEC = 1 << 0, // break when selector gets executed
- BREAK_SELECTORREAD = 1 << 1, // break when selector gets executed
- BREAK_SELECTORWRITE = 1 << 2, // break when selector gets executed
+ BREAK_SELECTOREXEC = 1 << 0, // break when a function selector is executed
+ BREAK_SELECTORREAD = 1 << 1, // break when a variable selector is read
+ BREAK_SELECTORWRITE = 1 << 2, // break when a variable selector is written
/**
- * Break when an exported function is called. data contains
+ * Break when an exported function is called. Data contains
* script_no << 16 | export_no.
*/
- BREAK_EXPORT = 1 << 3
+ BREAK_EXPORT = 1 << 3
};
struct Breakpoint {
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index f042664d8d..829831d3a6 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -622,6 +622,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ // Gabriel Knight - English DOS Floppy
+ // SCI interpreter version 2.000.000, VERSION file reports "1.0\nGabriel Knight\n11/22/10:33 pm\n\x1A"
+ {"gk1", "", {
+ {"resource.map", 0, "ef41df08cf2c1f680216cdbeed0f8311", 10783},
+ {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Gabriel Knight - German DOS Floppy (supplied my markcoolio in bug report #2723775)
// SCI interpreter version 2.000.000
{"gk1", "", {
@@ -1608,7 +1616,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Larry 1 VGA Remake - English Amiga (from www.back2roots.org)
+#if 0
+ // The resource.002 file, contained in disk 3, is broken in this version
+ // (it contains a large chunk of zeroes and several broken resources,
+ // e.g. pic 250 and views 250 and 251).
+ // Thus this detection entry isn't accurate.
+
+ // Larry 1 Remake - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.784
{"lsl1sci", "SCI", {
@@ -1619,6 +1633,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251},
AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+#endif
// Larry 1 VGA Remake - English DOS (from spookypeanut)
// Executable scanning reports "1.000.577", VERSION file reports "2.1"
@@ -1992,31 +2007,31 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Larry 6 - English/German/French DOS CD - LORES
+ // Larry 6 - English/German/French DOS CD - LOWRES
// SCI interpreter version 1.001.115
{"lsl6", "", {
{"resource.map", 0, "0b91234b7112782962cb480b7791b6e2", 7263},
{"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
- // Larry 6 - German DOS CD - LORES (provided by richiefs in bug report #2670691)
+ // Larry 6 - German DOS CD - LOWRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 1.001.115
{"lsl6", "", {
{"resource.map", 0, "bafe85f32738854135991d4324ad147e", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5773160},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE },
+ Common::DE_DEU, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
- // Larry 6 - French DOS CD - LORES (provided by richiefs in bug report #2670691)
+ // Larry 6 - French DOS CD - LOWRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 1.001.115
{"lsl6", "", {
{"resource.map", 0, "97797ea775baaf18a1907d357d3c0ea6", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5776092},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE },
+ Common::FR_FRA, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
- // Larry 6 - Spanish DOS - LORES (from the Leisure Suit Larry Collection)
+ // Larry 6 - Spanish DOS - LOWRES (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.001.113", VERSION file reports "1.000, 11.06.93, FIVE PATCHES ADDED TO DISK 6 ON 11-18-93"
{"lsl6", "", {
{"resource.map", 0, "633bf8f42170b6271019917c8009989b", 6943},
@@ -2274,7 +2289,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH },
// Mixed-Up Mother Goose - FM-Towns (supplied by abevi in bug report #3038720)
- {"mothergoose", "", {
+ {"mothergoose256", "", {
{"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772},
{"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713},
AD_LISTEND},
@@ -2588,13 +2603,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
- // Police Quest 4 - English DOS (from the Police Quest Collection)
+ // Police Quest 4 - English DOS CD (from the Police Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.100.000"
- {"pq4", "", {
+ {"pq4", "CD", {
{"resource.map", 0, "379dfe80ed6bd16c47e4b950c4722eac", 11374},
{"resource.000", 0, "fd316a09b628b7032248139003369022", 18841068},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
// Police Quest 4 - English DOS
// SCI interpreter version 2.000.000 (a guess?)
@@ -2628,6 +2643,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+ // Police Quest: SWAT - English DOS (from GOG.com)
+ // Executable scanning reports "2.100.002", VERSION file reports "1.0c"
+ {"pqswat", "", {
+ {"resmap.000", 0, "1c2563fee189885e29d9348f37306d94", 12175},
+ {"ressci.000", 0, "b2e1826ca81ce2e7e764587f5a14eee9", 127149181},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
+
// Police Quest: SWAT - English Windows (from the Police Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.0c"
// Original DOS/Windows release VERSION file reports "1.000" is the same
@@ -2641,7 +2664,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.004", 0, "4228038906f041623e65789500b22285", 6835},
{"ressci.004", 0, "b7e619e6ecf62fe65d5116a3a422e5f0", 46223872},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
#endif // ENABLE_SCI32
// Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by merkur in bug report #2718784)
@@ -2656,6 +2679,17 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by alonzotg in bug report #3206006)
+ {"qfg1", "", {
+ {"resource.map", 0, "85512508ed4e4ef1e3b309adabceeda9", 6486},
+ {"resource.000", 0, "481b034132106390cb5160fe61dd5f58", 80334},
+ {"resource.001", 0, "4d67acf52833ff45c7f753d6663532e8", 462729},
+ {"resource.002", 0, "439ba9b6dde216e6eb97ef3a9830fbe4", 647244},
+ {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203},
+ {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843)
// Executable scanning reports "0.000.566"
{"qfg1", "", {
@@ -2709,7 +2743,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes english language)
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language)
// Executable scanning reports "S.old.201"
{"qfg1", "8 Colors", {
{"resource.map", 0, "5cbeb95dd2a4b7cb242b415cc6ec1c47", 6444},
@@ -2719,7 +2753,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes english language)
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language)
// Executable scanning reports "S.old.201"
{"qfg1", "16 Colors", {
{"resource.map", 0, "3ecaba33bf77cb434067a0b8aee15097", 6444},
@@ -2959,13 +2993,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Quest for Glory 4 - English DOS/Windows (from jvprat)
+ // Quest for Glory 4 CD - English DOS/Windows (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
- {"qfg4", "", {
+ {"qfg4", "CD", {
{"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246},
{"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
// RAMA - English DOS/Windows Demo
// Executable scanning reports "2.100.002", VERSION file reports "000.000.008"
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 206624f87e..964097f57d 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -285,20 +285,16 @@ SciVersion GameFeatures::detectLofsType() {
}
// Find a function of the "Game" object (which is the game super class) which invokes lofsa/lofss
- reg_t gameSuperClass = g_sci->getGameSuperClassAddress();
+ const Object *gameObject = _segMan->getObject(g_sci->getGameObject());
+ const Object *gameSuperObject = _segMan->getObject(gameObject->getSuperClassSelector());
bool found = false;
- if (!gameSuperClass.isNull()) {
- Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass);
- const Object *gameSuperObject = _segMan->getObject(gameSuperClass);
+ if (gameSuperObject) {
+ Common::String gameSuperClassName = _segMan->getObjectName(gameObject->getSuperClassSelector());
- if (gameSuperObject) {
- for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
- found = autoDetectLofsType(gameSuperClassName, m);
- if (found)
- break;
- }
- } else {
- warning("detectLofsType(): Could not get superclass object");
+ for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
+ found = autoDetectLofsType(gameSuperClassName, m);
+ if (found)
+ break;
}
} else {
warning("detectLofsType(): Could not find superclass of game object");
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index 7692613ee5..e395eeab94 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -25,33 +25,47 @@
#include "sci/engine/gc.h"
#include "common/array.h"
+#include "sci/graphics/ports.h"
namespace Sci {
//#define GC_DEBUG_CODE
-struct WorklistManager {
- Common::Array<reg_t> _worklist;
- AddrSet _map; // used for 2 contains() calls, inside push() and run_gc()
+#ifdef GC_DEBUG_CODE
+const char *segmentTypeNames[] = {
+ "invalid", // 0
+ "script", // 1
+ "clones", // 2
+ "locals", // 3
+ "stack", // 4
+ "obsolete", // 5: obsolete system strings
+ "lists", // 6
+ "nodes", // 7
+ "hunk", // 8
+ "dynmem", // 9
+ "obsolete", // 10: obsolete string fragments
+ "array", // 11: SCI32 arrays
+ "string" // 12: SCI32 strings
+};
+#endif
- void push(reg_t reg) {
- if (!reg.segment) // No numbers
- return;
+void WorklistManager::push(reg_t reg) {
+ if (!reg.segment) // No numbers
+ return;
- debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg));
+ debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg));
- if (_map.contains(reg))
- return; // already dealt with it
+ if (_map.contains(reg))
+ return; // already dealt with it
- _map.setVal(reg, true);
- _worklist.push_back(reg);
- }
+ _map.setVal(reg, true);
+ _worklist.push_back(reg);
+}
- void pushArray(const Common::Array<reg_t> &tmp) {
- for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
- push(*it);
- }
-};
+void WorklistManager::pushArray(const Common::Array<reg_t> &tmp) {
+ for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+ push(*it);
+}
static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_map) {
AddrSet *normal_map = new AddrSet();
@@ -95,7 +109,7 @@ AddrSet *findAllActiveReferences(EngineState *s) {
// Initialize value stack
// We do this one by hand since the stack doesn't know the current execution stack
- Common::List<ExecStack>::iterator iter = s->_executionStack.reverse_begin();
+ Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin();
// Skip fake kernel stack frame if it's on top
if ((*iter).type == EXEC_STACK_TYPE_KERNEL)
@@ -103,9 +117,9 @@ AddrSet *findAllActiveReferences(EngineState *s) {
assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL));
- ExecStack &xs = *iter;
+ const StackPtr sp = iter->sp;
- for (reg_t *pos = s->stack_base; pos < xs.sp; pos++)
+ for (reg_t *pos = s->stack_base; pos < sp; pos++)
wm.push(*pos);
debugC(kDebugLevelGC, "[GC] -- Finished adding value stack");
@@ -113,7 +127,7 @@ AddrSet *findAllActiveReferences(EngineState *s) {
// Init: Execution Stack
for (iter = s->_executionStack.begin();
iter != s->_executionStack.end(); ++iter) {
- ExecStack &es = *iter;
+ const ExecStack &es = *iter;
if (es.type != EXEC_STACK_TYPE_KERNEL) {
wm.push(es.objp);
@@ -143,6 +157,9 @@ AddrSet *findAllActiveReferences(EngineState *s) {
processWorkList(s->_segMan, wm, heap);
+ if (g_sci->_gfxPorts)
+ g_sci->_gfxPorts->processEngineHunkList(wm);
+
return normalizeAddresses(s->_segMan, wm._map);
}
@@ -170,7 +187,7 @@ void run_gc(EngineState *s) {
if (mobj != NULL) {
#ifdef GC_DEBUG_CODE
const SegmentType type = mobj->getType();
- segnames[type] = SegmentObj::getSegmentTypeName(type);
+ segnames[type] = segmentTypeNames[type];
#endif
// Get a list of all deallocatable objects in this segment,
diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h
index f4318a1453..48e1c6b482 100644
--- a/engines/sci/engine/gc.h
+++ b/engines/sci/engine/gc.h
@@ -58,6 +58,15 @@ AddrSet *findAllActiveReferences(EngineState *s);
*/
void run_gc(EngineState *s);
+struct WorklistManager {
+ Common::Array<reg_t> _worklist;
+ AddrSet _map; // used for 2 contains() calls, inside push() and run_gc()
+
+ void push(reg_t reg);
+ void pushArray(const Common::Array<reg_t> &tmp);
+};
+
+
} // End of namespace Sci
#endif // SCI_ENGINE_GC_H
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index d8bbc75c18..ea6fa31d05 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -533,6 +533,7 @@ void Kernel::mapFunctions() {
switch (g_sci->getPlatform()) {
case Common::kPlatformPC:
+ case Common::kPlatformFMTowns:
platformMask = SIGFOR_DOS;
break;
case Common::kPlatformPC98:
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 202fc40ba4..9a55ef630b 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -255,6 +255,11 @@ private:
Common::StringArray checkStaticSelectorNames();
/**
+ * Automatically find specific selectors
+ */
+ void findSpecificSelectors(Common::StringArray &selectorNames);
+
+ /**
* Maps special selectors.
*/
void mapSelectors();
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 71892a8bea..16d56d10a8 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -56,7 +56,7 @@ struct SciKernelMapSubEntry {
#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
-#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE
+#define SIG_SCI1 SCI_VERSION_1_EGA_ONLY, SCI_VERSION_1_LATE
#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
#define SIG_SINCE_SCI11 SCI_VERSION_1_1, SCI_VERSION_NONE
#define SIG_SCI21 SCI_VERSION_2_1, SCI_VERSION_3
@@ -348,7 +348,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, kFindKey_workarounds },
{ MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL },
{ MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL },
+ { MAP_CALL(Format), SIG_EVERYWHERE, "r[ri](.*)", NULL, NULL },
{ MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL },
{ MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, kGetAngle_workarounds },
{ MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL },
@@ -434,7 +434,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL },
{ MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, kStrAt_workarounds },
- { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, kStrCat_workarounds },
+ { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL },
{ MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL },
{ MAP_CALL(StrCpy), SIG_EVERYWHERE, "r[r0](i)", NULL, NULL },
{ MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL },
@@ -490,6 +490,12 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
{ MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL },
{ "OnMe", kIsOnMe, SIG_EVERYWHERE, "iioi", NULL, NULL },
+ // Purge is used by the memory manager in SSCI to ensure that X number of bytes (the so called "unmovable
+ // memory") are available when the current room changes. This is similar to the SCI0-SCI1.1 FlushResources
+ // call, with the added functionality of ensuring that a specific amount of memory is available. We have
+ // our own memory manager and garbage collector, thus we simply call FlushResources, which in turn invokes
+ // our garbage collector (i.e. the SCI0-SCI1.1 semantics).
+ { "Purge", kFlushResources, SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(SetShowStyle), SIG_EVERYWHERE, "ioiiiii([ri])(i)", NULL, NULL },
{ MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL },
@@ -508,12 +514,6 @@ static SciKernelMapEntry s_kernelMap[] = {
// MakeSaveCatName - used in the Save/Load dialog of GK1CD (SRDialog, script 64990)
// MakeSaveFileName - used in the Save/Load dialog of GK1CD (SRDialog, script 64990)
- // SCI2 empty functions
-
- // Purge is used by the memory manager in SSCI to ensure that X number of bytes (the so called "unmovable
- // memory") are available. We have our own memory manager and garbage collector, thus we ignore this call.
- { MAP_EMPTY(Purge), SIG_EVERYWHERE, "i", NULL, NULL },
-
// Unused / debug SCI2 unused functions, always mapped to kDummy
{ MAP_DUMMY(InspectObject), SIG_EVERYWHERE, "(.*)", NULL, NULL },
// Profiler (same as SCI0-SCI1.1)
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index 58de38bd8e..725b78341b 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -35,11 +35,10 @@
#include "sci/event.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/cursor.h"
+#include "sci/graphics/maciconbar.h"
namespace Sci {
-#define SCI_VARIABLE_GAME_SPEED 3
-
reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
int mask = argv[0].toUint16();
reg_t obj = argv[1];
@@ -48,17 +47,25 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
Common::Point mousePos;
- // Limit the mouse cursor position, if necessary
- g_sci->_gfxCursor->refreshPosition();
- mousePos = g_sci->_gfxCursor->getPosition();
-#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1)
- g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
-#endif
+ // For Mac games with an icon bar, handle possible icon bar events first
+ if (g_sci->hasMacIconBar()) {
+ reg_t iconObj = g_sci->_gfxMacIconBar->handleEvents();
+ if (!iconObj.isNull())
+ invokeSelector(s, iconObj, SELECTOR(select), argc, argv, 0, NULL);
+ }
// If there's a simkey pending, and the game wants a keyboard event, use the
// simkey instead of a normal event
if (g_debug_simulated_key && (mask & SCI_EVENT_KEYBOARD)) {
+ // In case we use a simulated event we query the current mouse position
+ mousePos = g_sci->_gfxCursor->getPosition();
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1)
+ g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+#endif
+ // Limit the mouse cursor position, if necessary
+ g_sci->_gfxCursor->refreshPosition();
+
writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
writeSelectorValue(segMan, obj, SELECTOR(message), g_debug_simulated_key);
writeSelectorValue(segMan, obj, SELECTOR(modifiers), SCI_KEYMOD_NUMLOCK); // Numlock on
@@ -70,6 +77,15 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
curEvent = g_sci->getEventManager()->getSciEvent(mask);
+ // For a real event we use its associated mouse position
+ mousePos = curEvent.mousePos;
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1)
+ g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+#endif
+ // Limit the mouse cursor position, if necessary
+ g_sci->_gfxCursor->refreshPosition();
+
if (g_sci->getVocabulary())
g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event
@@ -137,7 +153,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
break;
default:
- s->r_acc = NULL_REG; // Unknown or no event
+ // Return a null event
+ writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE);
+ writeSelectorValue(segMan, obj, SELECTOR(message), 0);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ s->r_acc = NULL_REG;
}
if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) {
@@ -188,57 +208,42 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+struct KeyDirMapping {
+ uint16 key;
+ uint16 direction;
+};
+
+const KeyDirMapping keyToDirMap[] = {
+ { SCI_KEY_HOME, 8 }, { SCI_KEY_UP, 1 }, { SCI_KEY_PGUP, 2 },
+ { SCI_KEY_LEFT, 7 }, { SCI_KEY_CENTER, 0 }, { SCI_KEY_RIGHT, 3 },
+ { SCI_KEY_END, 6 }, { SCI_KEY_DOWN, 5 }, { SCI_KEY_PGDOWN, 4 },
+};
+
reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) {
reg_t obj = argv[0];
SegManager *segMan = s->_segMan;
if (readSelectorValue(segMan, obj, SELECTOR(type)) == SCI_EVENT_KEYBOARD) { // Keyboard
- int mover = -1;
- switch (readSelectorValue(segMan, obj, SELECTOR(message))) {
- case SCI_KEY_HOME:
- mover = 8;
- break;
- case SCI_KEY_UP:
- mover = 1;
- break;
- case SCI_KEY_PGUP:
- mover = 2;
- break;
- case SCI_KEY_LEFT:
- mover = 7;
- break;
- case SCI_KEY_CENTER:
- case 76:
- mover = 0;
- break;
- case SCI_KEY_RIGHT:
- mover = 3;
- break;
- case SCI_KEY_END:
- mover = 6;
- break;
- case SCI_KEY_DOWN:
- mover = 5;
- break;
- case SCI_KEY_PGDOWN:
- mover = 4;
- break;
- default:
- break;
+ uint16 message = readSelectorValue(segMan, obj, SELECTOR(message));
+ uint16 eventType = SCI_EVENT_DIRECTION;
+ // Check if the game is using cursor views. These games allowed control
+ // of the mouse cursor via the keyboard controls (the so called
+ // "PseudoMouse" functionality in script 933).
+ if (g_sci->_features->detectSetCursorType() == SCI_VERSION_1_1)
+ eventType |= SCI_EVENT_KEYBOARD;
+
+ for (int i = 0; i < 9; i++) {
+ if (keyToDirMap[i].key == message) {
+ writeSelectorValue(segMan, obj, SELECTOR(type), eventType);
+ writeSelectorValue(segMan, obj, SELECTOR(message), keyToDirMap[i].direction);
+ return TRUE_REG; // direction mapped
+ }
}
- if (mover >= 0) {
- if (g_sci->getEventManager()->getUsesNewKeyboardDirectionType())
- writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD | SCI_EVENT_DIRECTION);
- else
- writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_DIRECTION);
- writeSelectorValue(segMan, obj, SELECTOR(message), mover);
- return make_reg(0, 1);
- } else
- return NULL_REG;
+ return NULL_REG; // unknown direction
}
- return s->r_acc;
+ return s->r_acc; // no keyboard event to map, leave accumulator unchanged
}
reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) {
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index f6dec5da64..82522a6e77 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -253,6 +253,7 @@ reg_t kFGets(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelFile, "kFGets(%d, %d)", handle, maxsize);
int readBytes = fgets_wrapper(s, buf, maxsize, handle);
s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize);
+ delete[] buf;
return readBytes ? argv[0] : NULL_REG;
}
@@ -1155,15 +1156,14 @@ reg_t kCD(EngineState *s, int argc, reg_t *argv) {
reg_t kSave(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
- case 0: // Called by kq7 when starting chapters
+ case 0:
return kSaveGame(s, argc - 1,argv + 1);
- case 2: // GetSaveDir
- // Yay! Reusing the old kernel function!
+ case 1:
+ return kRestoreGame(s, argc - 1,argv + 1);
+ case 2:
return kGetSaveDir(s, argc - 1, argv + 1);
case 5:
- // TODO
- // 3 parameters: game ID, a string and an array
- return s->r_acc;
+ return kGetSaveFiles(s, argc - 1, argv + 1);
case 8:
// TODO
// This is a timer callback, with 1 parameter: the timer object
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 8730724d68..c7a2a26c3d 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -58,6 +58,17 @@
namespace Sci {
+static int16 adjustGraphColor(int16 color) {
+ // WORKAROUND: SCI1 EGA and Amiga games can set invalid colors (above 0 - 15).
+ // Colors above 15 are all white in SCI1 EGA games, which is why this was never
+ // observed. We clip them all to (0, 15) instead, as colors above 15 are used
+ // for the undithering algorithm in EGA games - bug #3048908.
+ if (getSciVersion() >= SCI_VERSION_1_EARLY && g_sci->getResMan()->getViewType() == kViewEga)
+ return color & 0x0F; // 0 - 15
+ else
+ return color;
+}
+
void showScummVMDialog(const Common::String &message) {
GUI::MessageDialog dialog(message, "OK");
dialog.runModal();
@@ -242,23 +253,14 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
}
reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isAmiga32color())
- return make_reg(0, 32);
- return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
+ return make_reg(0, g_sci->_gfxPalette->getTotalColorCount());
}
reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) {
- int16 color = argv[4].toSint16();
+ int16 color = adjustGraphColor(argv[4].toSint16());
int16 priority = (argc > 5) ? argv[5].toSint16() : -1;
int16 control = (argc > 6) ? argv[6].toSint16() : -1;
- // WORKAROUND: SCI1 EGA games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY)
- color &= 0x0F;
-
g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control);
return s->r_acc;
}
@@ -290,17 +292,10 @@ reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv) {
reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) {
Common::Rect rect = getGraphRect(argv);
int16 colorMask = argv[4].toUint16();
- int16 color = argv[5].toSint16();
+ int16 color = adjustGraphColor(argv[5].toSint16());
int16 priority = argv[6].toSint16(); // yes, we may read from stack sometimes here
int16 control = argv[7].toSint16(); // sierra did the same
- // WORKAROUND: SCI1 EGA games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY)
- color &= 0x0F;
-
g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
return s->r_acc;
}
@@ -364,6 +359,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
if (!g_sci->_gfxText16) {
// TODO: Implement this
textWidth = 0; textHeight = 0;
+ warning("TODO: implement kTextSize for SCI32");
} else
#endif
g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
@@ -553,8 +549,6 @@ reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-// we are called on EGA/amiga games as well, this doesnt make sense.
-// doing this would actually break the system EGA/amiga palette
reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
if (!s)
return make_reg(0, getSciVersion());
@@ -562,86 +556,85 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
}
reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- GuiResourceId resourceId = argv[0].toUint16();
- bool force = false;
- if (argc == 2)
- force = argv[1].toUint16() == 2 ? true : false;
- g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
- }
+ GuiResourceId resourceId = argv[0].toUint16();
+ bool force = false;
+ if (argc == 2)
+ force = argv[1].toUint16() == 2 ? true : false;
+
+ // Non-VGA games don't use palette resources.
+ // This has been changed to 64 colors because Longbow Amiga does have
+ // one palette (palette 999).
+ if (g_sci->_gfxPalette->getTotalColorCount() < 64)
+ return s->r_acc;
+
+ g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
return s->r_acc;
}
reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 flags = argv[2].toUint16();
- g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags);
- }
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 flags = argv[2].toUint16();
+ g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags);
return s->r_acc;
}
reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 flags = argv[2].toUint16();
- g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags);
- }
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 flags = argv[2].toUint16();
+ g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags);
return s->r_acc;
}
reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 intensity = argv[2].toUint16();
- bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false;
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 intensity = argv[2].toUint16();
+ bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false;
- g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
- }
+ // Palette intensity in non-VGA SCI1 games has been removed
+ if (g_sci->_gfxPalette->getTotalColorCount() < 256)
+ return s->r_acc;
+
+ g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
return s->r_acc;
}
reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 r = argv[0].toUint16();
- uint16 g = argv[1].toUint16();
- uint16 b = argv[2].toUint16();
- return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b));
- }
- return NULL_REG;
+ uint16 r = argv[0].toUint16();
+ uint16 g = argv[1].toUint16();
+ uint16 b = argv[2].toUint16();
+ return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b));
}
reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- int16 argNr;
- bool paletteChanged = false;
- for (argNr = 0; argNr < argc; argNr += 3) {
- uint16 fromColor = argv[argNr].toUint16();
- uint16 toColor = argv[argNr + 1].toUint16();
- int16 speed = argv[argNr + 2].toSint16();
- if (g_sci->_gfxPalette->kernelAnimate(fromColor, toColor, speed))
- paletteChanged = true;
- }
- if (paletteChanged)
- g_sci->_gfxPalette->kernelAnimateSet();
+ int16 argNr;
+ bool paletteChanged = false;
+
+ // Palette animation in non-VGA SCI1 games has been removed
+ if (g_sci->_gfxPalette->getTotalColorCount() < 256)
+ return s->r_acc;
+
+ for (argNr = 0; argNr < argc; argNr += 3) {
+ uint16 fromColor = argv[argNr].toUint16();
+ uint16 toColor = argv[argNr + 1].toUint16();
+ int16 speed = argv[argNr + 2].toSint16();
+ if (g_sci->_gfxPalette->kernelAnimate(fromColor, toColor, speed))
+ paletteChanged = true;
}
+ if (paletteChanged)
+ g_sci->_gfxPalette->kernelAnimateSet();
+
return s->r_acc;
}
reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- return g_sci->_gfxPalette->kernelSave();
- }
- return NULL_REG;
+ return g_sci->_gfxPalette->kernelSave();
}
reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- g_sci->_gfxPalette->kernelRestore(argv[0]);
- }
+ g_sci->_gfxPalette->kernelRestore(argv[0]);
return argv[0];
}
@@ -1082,22 +1075,11 @@ reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) {
int argextra = argc >= 13 ? 4 : 0; // Triggers in PQ3 and SCI1.1 games, argc 13 for DOS argc 15 for mac
int style = argv[5 + argextra].toSint16();
int priority = (argc > 6 + argextra) ? argv[6 + argextra].toSint16() : -1;
- int colorPen = (argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0;
- int colorBack = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255;
+ int colorPen = adjustGraphColor((argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0);
+ int colorBack = adjustGraphColor((argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255);
- // WORKAROUND: SCI1 EGA games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY) {
- colorPen &= 0x0F;
- colorBack &= 0x0F;
- }
-
- // const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL;
- if (argc>=13) {
+ if (argc >= 13)
rect2 = Common::Rect (argv[5].toSint16(), argv[4].toSint16(), argv[7].toSint16(), argv[6].toSint16());
- }
Common::String title;
if (argv[4 + argextra].segment) {
@@ -1201,14 +1183,12 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) {
}
reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
- // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now
- kStub(s, argc, argv);
-
uint16 operation = argv[0].toUint16();
switch (operation) {
- case 0: { // Initialize remapping to base. 0 turns remapping off.
- //int16 unk1 = (argc >= 2) ? argv[1].toSint16() : 0;
+ case 0: { // Set remapping to base. 0 turns remapping off.
+ int16 base = (argc >= 2) ? argv[1].toSint16() : 0;
+ warning("kRemapColors: Set remapping to base %d", base);
}
break;
case 1: { // unknown
@@ -1218,18 +1198,32 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
//int16 unk3 = argv[3].toSint16();
//uint16 unk4 = argv[4].toUint16();
//uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0;
+ kStub(s, argc, argv);
}
break;
case 2: { // remap by percent
- //int16 unk1 = argv[1].toSint16();
- //uint16 percent = argv[2].toUint16();
- //uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
+ // This adjusts the alpha value of a specific color, and it operates on
+ // an RGBA palette. Since we're operating on an RGB palette, we just
+ // modify the color intensity instead
+ // TODO: From what I understand, palette remapping should be placed
+ // separately, so that it can be reset by case 0 above. Thus, we
+ // should adjust the functionality of the Palette class accordingly.
+ int16 color = argv[1].toSint16();
+ if (color >= 10)
+ color -= 10;
+ uint16 percent = argv[2].toUint16(); // 0 - 100
+ if (argc >= 4)
+ warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
+ g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false);
}
break;
case 3: { // remap to gray
- //int16 unk1 = argv[1].toSint16();
- //int16 percent = argv[2].toSint16(); // 0 - 100
- //uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
+ // NOTE: This adjusts the alpha value of a specific color, and it operates on
+ // an RGBA palette
+ int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10
+ int16 percent = argv[2].toSint16(); // 0 - 100
+ uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
+ warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3);
}
break;
case 4: { // unknown
@@ -1237,11 +1231,13 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
//uint16 unk2 = argv[2].toUint16();
//uint16 unk3 = argv[3].toUint16();
//uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0;
+ kStub(s, argc, argv);
}
break;
case 5: { // increment color
//int16 unk1 = argv[1].toSint16();
//uint16 unk2 = argv[2].toUint16();
+ kStub(s, argc, argv);
}
break;
default:
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp
index f90a5b4353..9baf9f5a54 100644
--- a/engines/sci/engine/kmath.cpp
+++ b/engines/sci/engine/kmath.cpp
@@ -117,7 +117,7 @@ reg_t kGetDistance(EngineState *s, int argc, reg_t *argv) {
int xdiff = (argc > 3) ? argv[3].toSint16() : 0;
int ydiff = (argc > 2) ? argv[2].toSint16() : 0;
int angle = (argc > 5) ? argv[5].toSint16() : 0;
- int xrel = (int)(((float) argv[1].toSint16() - xdiff) / cos(angle * PI / 180.0)); // This works because cos(0)==1
+ int xrel = (int)(((float) argv[1].toSint16() - xdiff) / cos(angle * M_PI / 180.0)); // This works because cos(0)==1
int yrel = argv[0].toSint16() - ydiff;
return make_reg(0, (int16)sqrt((float) xrel*xrel + yrel*yrel));
}
@@ -126,20 +126,20 @@ reg_t kTimesSin(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int factor = argv[1].toSint16();
- return make_reg(0, (int16)(factor * sin(angle * PI / 180.0)));
+ return make_reg(0, (int16)(factor * sin(angle * M_PI / 180.0)));
}
reg_t kTimesCos(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int factor = argv[1].toSint16();
- return make_reg(0, (int16)(factor * cos(angle * PI / 180.0)));
+ return make_reg(0, (int16)(factor * cos(angle * M_PI / 180.0)));
}
reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int value = argv[1].toSint16();
- double cosval = cos(angle * PI / 180.0);
+ double cosval = cos(angle * M_PI / 180.0);
if ((cosval < 0.0001) && (cosval > -0.0001)) {
error("kCosDiv: Attempted division by zero");
@@ -151,7 +151,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) {
reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int value = argv[1].toSint16();
- double sinval = sin(angle * PI / 180.0);
+ double sinval = sin(angle * M_PI / 180.0);
if ((sinval < 0.0001) && (sinval > -0.0001)) {
error("kSinDiv: Attempted division by zero");
@@ -169,7 +169,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) {
error("kTimesTan: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
- return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale));
+ return make_reg(0, (int16) - (tan(param * M_PI / 180.0) * scale));
}
reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) {
@@ -180,7 +180,7 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) {
error("kTimesCot: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
- return make_reg(0, (int16)(tan(param * PI / 180.0) * scale));
+ return make_reg(0, (int16)(tan(param * M_PI / 180.0) * scale));
}
#ifdef ENABLE_SCI32
diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp
index 428c27ca73..3986966a71 100644
--- a/engines/sci/engine/kmenu.cpp
+++ b/engines/sci/engine/kmenu.cpp
@@ -29,6 +29,7 @@
#include "sci/engine/kernel.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/menu.h"
+#include "sci/graphics/screen.h"
namespace Sci {
@@ -71,7 +72,7 @@ reg_t kDrawStatus(EngineState *s, int argc, reg_t *argv) {
reg_t textReference = argv[0];
Common::String text;
int16 colorPen = (argc > 1) ? argv[1].toSint16() : 0;
- int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->getResMan()->isVGA() ? 255 : 15;
+ int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->_gfxScreen->getColorWhite();
if (!textReference.isNull()) {
// Sometimes this is called without giving text, if thats the case dont process it.
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 6e961f72f3..907e0ba2e4 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -151,8 +151,13 @@ reg_t kMemorySegment(EngineState *s, int argc, reg_t *argv) {
if (!size)
size = s->_segMan->strlen(argv[1]) + 1;
- if (size > EngineState::kMemorySegmentMax)
- size = EngineState::kMemorySegmentMax;
+ if (size > EngineState::kMemorySegmentMax) {
+ // This was set to cut the block to 256 bytes. This should be an
+ // error, as we won't restore the full block that the game scripts
+ // request, thus error out instead.
+ //size = EngineState::kMemorySegmentMax;
+ error("kMemorySegment: Requested to save more than 256 bytes (%d)", size);
+ }
s->_memorySegmentSize = size;
@@ -298,12 +303,9 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
error("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
return s->r_acc;
}
- if (ref.isRaw) {
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- return make_reg(0, (int16)READ_BE_UINT16(ref.raw)); // Amiga versions are BE
- else
- return make_reg(0, (int16)READ_LE_UINT16(ref.raw));
- } else {
+ if (ref.isRaw)
+ return make_reg(0, (int16)READ_SCIENDIAN_UINT16(ref.raw));
+ else {
if (ref.skipByte)
error("Attempt to peek memory at odd offset %04X:%04X", PRINT_REG(argv[1]));
return *(ref.reg);
@@ -323,10 +325,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
error("Attempt to poke memory reference %04x:%04x to %04x:%04x", PRINT_REG(argv[2]), PRINT_REG(argv[1]));
return s->r_acc;
}
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- WRITE_BE_UINT16(ref.raw, argv[2].offset); // Amiga versions are BE
- else
- WRITE_LE_UINT16(ref.raw, argv[2].offset);
+ WRITE_SCIENDIAN_UINT16(ref.raw, argv[2].offset); // Amiga versions are BE
} else {
if (ref.skipByte)
error("Attempt to poke memory at odd offset %04X:%04X", PRINT_REG(argv[1]));
@@ -362,22 +361,32 @@ reg_t kIconBar(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
switch (argv[0].toUint16()) {
- case 0:
- // Add the icons
+ case 0: // InitIconBar
for (int i = 0; i < argv[1].toUint16(); i++)
g_sci->_gfxMacIconBar->addIcon(argv[i + 2]);
-
- g_sci->_gfxMacIconBar->drawIcons();
break;
- case 2:
- case 3:
- case 4:
- // TODO: Other calls seem to handle selecting/deselecting them
+ case 1: // DisposeIconBar
+ warning("kIconBar(Dispose)");
+ break;
+ case 2: // EnableIconBar (-1 = all)
+ debug(0, "kIconBar(Enable, %i)", argv[1].toSint16());
+ g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), true);
+ break;
+ case 3: // DisableIconBar (-1 = all)
+ debug(0, "kIconBar(Disable, %i)", argv[1].toSint16());
+ g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), false);
+ break;
+ case 4: // SetIconBarIcon
+ debug(0, "kIconBar(SetIcon, %d, %d)", argv[1].toUint16(), argv[2].toUint16());
+ if (argv[2].toSint16() == -1)
+ g_sci->_gfxMacIconBar->setInventoryIcon(argv[2].toSint16());
break;
default:
- warning("Unknown kIconBar subop %d", argv[0].toUint16());
+ error("Unknown kIconBar(%d)", argv[0].toUint16());
}
+ g_sci->_gfxMacIconBar->drawIcons();
+
return NULL_REG;
}
@@ -389,23 +398,28 @@ reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
case 0:
- // Set Mac cursor remap
- g_sci->_gfxCursor->setMacCursorRemapList(argc - 1, argv + 1);
- break;
- case 1:
- // Unknown
+ // Subop 0 has changed a few times
+ // In SCI1, its usage is still unknown
+ // In SCI1.1, it's NOP
+ // In SCI32, it's used for remapping cursor ID's
+ if (getSciVersion() >= SCI_VERSION_2_1) // Set Mac cursor remap
+ g_sci->_gfxCursor->setMacCursorRemapList(argc - 1, argv + 1);
+ else if (getSciVersion() != SCI_VERSION_1_1)
+ warning("Unknown SCI1 kMacPlatform(0) call");
break;
- case 2:
- // Unknown
- break;
- case 3:
- // Unknown
- break;
- case 4:
- // Handle icon bar code
+ case 4: // Handle icon bar code
return kIconBar(s, argc - 1, argv + 1);
+ case 7: // Unknown, but always return -1
+ return SIGNAL_REG;
+ case 1: // Unknown, calls QuickDraw region functions (KQ5, QFG1VGA)
+ case 2: // Unknown, "UseNextWaitEvent" (Various)
+ case 3: // Unknown, "ProcessOpenDocuments" (Various)
+ case 5: // Unknown, plays a sound (KQ7)
+ case 6: // Unknown, menu-related (Unused?)
+ warning("Unhandled kMacPlatform(%d)", argv[0].toUint16());
+ break;
default:
- warning("Unknown kMacPlatform subop %d", argv[0].toUint16());
+ error("Unknown kMacPlatform(%d)", argv[0].toUint16());
}
return s->r_acc;
@@ -455,7 +469,8 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) {
warning("STUB: kPlatform(CDCheck)");
break;
case kPlatformUnk0:
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1 && argc > 1)
+ // For Mac versions, kPlatform(0) with other args has more functionality
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && argc > 1)
return kMacPlatform(s, argc - 1, argv + 1);
// Otherwise, fall through
case kPlatformGetPlatform:
@@ -486,7 +501,7 @@ reg_t kStub(EngineState *s, int argc, reg_t *argv) {
Kernel *kernel = g_sci->getKernel();
int kernelCallNr = -1;
- Common::List<ExecStack>::iterator callIterator = s->_executionStack.end();
+ Common::List<ExecStack>::const_iterator callIterator = s->_executionStack.end();
if (callIterator != s->_executionStack.begin()) {
callIterator--;
ExecStack lastCall = *callIterator;
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index 3c516f63f2..f93a6716b9 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -166,17 +166,6 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-// TODO/FIXME: There is a notable regression with the new kInitBresed/kDoBresen
-// functions below in a death scene of LB1 - the shower scene, room 215 (bug
-// #3122075). There is a hack to get around this bug by modifying the actor's
-// position for that scene in kScriptID. The actual bug should be found, but
-// since only this death scene has an issue, it's not really worth the effort.
-// The new kInitBresen/kDoBresen functions have been enabled in r52467. The
-// old ones are based on observations, so there are many differences in the
-// way that they behave. Check the hack in kScriptID for more info. Note that
-// the actual issue might not be with kInitBresen/kDoBresen, and there might
-// be another underlying problem here.
-
reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
reg_t mover = argv[0];
@@ -275,7 +264,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
bool completed = false;
bool handleMoveCount = g_sci->_features->handleMoveCount();
- if (getSciVersion() >= SCI_VERSION_1_EGA) {
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) {
uint client_signal = readSelectorValue(segMan, client, SELECTOR(signal));
writeSelectorValue(segMan, client, SELECTOR(signal), client_signal & ~kSignalHitObstacle);
}
@@ -292,8 +281,6 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
mover_moveCnt = 0;
int16 client_x = readSelectorValue(segMan, client, SELECTOR(x));
int16 client_y = readSelectorValue(segMan, client, SELECTOR(y));
- int16 client_org_x = client_x;
- int16 client_org_y = client_y;
int16 mover_x = readSelectorValue(segMan, mover, SELECTOR(x));
int16 mover_y = readSelectorValue(segMan, mover, SELECTOR(y));
int16 mover_xAxis = readSelectorValue(segMan, mover, SELECTOR(b_xAxis));
@@ -307,12 +294,19 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
int16 mover_org_i2 = mover_i2;
int16 mover_org_di = mover_di;
- if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
+ if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) {
// save current position into mover
writeSelectorValue(segMan, mover, SELECTOR(xLast), client_x);
writeSelectorValue(segMan, mover, SELECTOR(yLast), client_y);
}
- // sierra sci saves full client selector variables here
+
+ // Store backups of all client selector variables. We will restore them
+ // in case of a collision.
+ Object* clientObject = segMan->getObject(client);
+ uint clientVarNum = clientObject->getVarCount();
+ reg_t* clientBackup = new reg_t[clientVarNum];
+ for (uint i = 0; i < clientVarNum; ++i)
+ clientBackup[i] = clientObject->getVariable(i);
if (mover_xAxis) {
if (ABS(mover_x - client_x) < ABS(mover_dx))
@@ -360,9 +354,10 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
}
if (collision) {
- // sierra restores full client variables here, seems that restoring x/y is enough
- writeSelectorValue(segMan, client, SELECTOR(x), client_org_x);
- writeSelectorValue(segMan, client, SELECTOR(y), client_org_y);
+ // We restore the backup of the client variables
+ for (uint i = 0; i < clientVarNum; ++i)
+ clientObject->getVariableRef(i) = clientBackup[i];
+
mover_i1 = mover_org_i1;
mover_i2 = mover_org_i2;
mover_di = mover_org_di;
@@ -370,30 +365,29 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
uint16 client_signal = readSelectorValue(segMan, client, SELECTOR(signal));
writeSelectorValue(segMan, client, SELECTOR(signal), client_signal | kSignalHitObstacle);
}
+ delete[] clientBackup;
+
writeSelectorValue(segMan, mover, SELECTOR(b_i1), mover_i1);
writeSelectorValue(segMan, mover, SELECTOR(b_i2), mover_i2);
writeSelectorValue(segMan, mover, SELECTOR(b_di), mover_di);
- if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
- // this calling code here was right before the last return in
- // sci1ega and got changed to this position since sci1early
- // this was an uninitialized issue in sierra sci
- if ((handleMoveCount) && (getSciVersion() >= SCI_VERSION_1_EARLY))
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) {
+ // In sci1egaonly this block of code was outside of the main if,
+ // but client_x/client_y aren't set there, so it was an
+ // uninitialized read in SSCI. (This issue was fixed in sci1early.)
+ if (handleMoveCount)
writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
// We need to compare directly in here, complete may have happened during
// the current move
if ((client_x == mover_x) && (client_y == mover_y))
invokeSelector(s, mover, SELECTOR(moveDone), argc, argv);
- if (getSciVersion() >= SCI_VERSION_1_EARLY)
- return s->r_acc;
+ return s->r_acc;
}
}
- if (handleMoveCount) {
- if (getSciVersion() <= SCI_VERSION_1_EGA)
- writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
- else
- writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), client_moveSpeed);
- }
+
+ if (handleMoveCount)
+ writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
+
return s->r_acc;
}
@@ -575,8 +569,8 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelBresen, " avoider %04x:%04x", PRINT_REG(avoider));
for (moves = 0; moves < 8; moves++) {
- int move_x = (int)(sin(angle * PI / 180.0) * (xstep));
- int move_y = (int)(-cos(angle * PI / 180.0) * (ystep));
+ int move_x = (int)(sin(angle * M_PI / 180.0) * (xstep));
+ int move_y = (int)(-cos(angle * M_PI / 180.0) * (ystep));
writeSelectorValue(segMan, client, SELECTOR(x), oldx + move_x);
writeSelectorValue(segMan, client, SELECTOR(y), oldy + move_y);
diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp
index e8f8ee7152..09cf7744b2 100644
--- a/engines/sci/engine/kparse.cpp
+++ b/engines/sci/engine/kparse.cpp
@@ -70,7 +70,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
- new_lastmatch = said(s, said_block, debug_parser);
+ new_lastmatch = said(said_block, debug_parser);
if (new_lastmatch != SAID_NO_MATCH) { /* Build and possibly display a parse tree */
#ifdef DEBUG_PARSER
@@ -169,7 +169,7 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
Vocabulary *voc = g_sci->getVocabulary();
// Only SCI0-SCI1 EGA games had a parser. In newer versions, this is a stub
- if (getSciVersion() > SCI_VERSION_1_EGA)
+ if (getSciVersion() > SCI_VERSION_1_EGA_ONLY)
return s->r_acc;
voc->clearSynonyms();
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index cb70cf91e0..7786f9b093 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -264,9 +264,9 @@ struct PathfindingState {
static Common::Point readPoint(SegmentRef list_r, int offset) {
Common::Point point;
- if (list_r.isRaw) {
- point.x = (int16)READ_LE_UINT16(list_r.raw + offset * POLY_POINT_SIZE);
- point.y = (int16)READ_LE_UINT16(list_r.raw + offset * POLY_POINT_SIZE + 2);
+ if (list_r.isRaw) { // dynmem blocks are raw
+ point.x = (int16)READ_SCIENDIAN_UINT16(list_r.raw + offset * POLY_POINT_SIZE);
+ point.y = (int16)READ_SCIENDIAN_UINT16(list_r.raw + offset * POLY_POINT_SIZE + 2);
} else {
point.x = list_r.reg[offset * 2].toUint16();
point.y = list_r.reg[offset * 2 + 1].toUint16();
@@ -275,9 +275,9 @@ static Common::Point readPoint(SegmentRef list_r, int offset) {
}
static void writePoint(SegmentRef ref, int offset, const Common::Point &point) {
- if (ref.isRaw) {
- WRITE_LE_UINT16(ref.raw + offset * POLY_POINT_SIZE, point.x);
- WRITE_LE_UINT16(ref.raw + offset * POLY_POINT_SIZE + 2, point.y);
+ if (ref.isRaw) { // dynmem blocks are raw
+ WRITE_SCIENDIAN_UINT16(ref.raw + offset * POLY_POINT_SIZE, point.x);
+ WRITE_SCIENDIAN_UINT16(ref.raw + offset * POLY_POINT_SIZE + 2, point.y);
} else {
ref.reg[offset * 2] = make_reg(0, point.x);
ref.reg[offset * 2 + 1] = make_reg(0, point.y);
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 810e8a13ee..b9baa3540a 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -56,14 +56,6 @@ reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) {
ResourceType restype = g_sci->getResMan()->convertResType(argv[0].toUint16());
reg_t resnr = argv[1];
- // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain.
- // Script 377 tries to free the hunk memory allocated for the saved area
- // (underbits) beneath the pop up window, which results in having the
- // window stay on screen even when it's closed. Ignore this request here.
- if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN &&
- s->currentRoomNumber() == 320)
- return s->r_acc;
-
if (restype == kResourceTypeMemory)
s->_segMan->freeHunkEntry(resnr);
}
@@ -257,33 +249,9 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
// is used for timing during the intro, and in the problematic version it's
// initialized to 0, whereas it's 6 in other versions. Thus, we assign it
// to 6 here, fixing the speed of the introduction. Refer to bug #3102071.
- if (g_sci->getGameId() == GID_PQ2 && script == 200) {
- if (s->variables[VAR_GLOBAL][3].isNull()) {
- warning("Fixing speed in the intro of PQ2, version 1.002.011");
- s->variables[VAR_GLOBAL][3] = make_reg(0, 6);
- }
- }
-
- // HACK: Prevent the murderer from getting stuck behind the door in
- // Colonel's Bequest, room 215. A temporary fix for bug #3122075.
- // TODO/FIXME: Add a proper fix for this. There is a regression in this
- // scene with the new kInitBresen and kDoBresen functions (r52467). Using
- // just the "old" kInitBresen works. This hack is added for now because the
- // two functions are quite complex. The "old" versions were created based
- // on observations, and not on the interpreter itself, thus they have a lot
- // of differences in the way they behave and set variables to the mover object.
- // Since this is just a death scene where Laura is supposed to die anyway,
- // figuring out the exact cause of this is just not worth the effort.
- // Differences between the new and the old kInitBresen to the MoveTo object:
- // dy: 1 (new) - 2 (old)
- // b-i1: 20 (new) - 12 (old)
- // b-di: 65526 (new) - 65516 (old)
- // Performing the changes above to MoveTo (0017:033a) allows the killer to
- // move. Note that the actual issue might not be with kInitBresen/kDoBresen,
- // and there might be another underlying problem here.
- if (g_sci->getGameId() == GID_LAURABOW && script == 215) {
- warning("Moving actor position for the shower scene of Colonel's Bequest");
- writeSelectorValue(s->_segMan, s->_segMan->findObjectByName("killer"), SELECTOR(x), 6);
+ if (g_sci->getGameId() == GID_PQ2 && script == 200 &&
+ s->variables[VAR_GLOBAL][3].isNull()) {
+ s->variables[VAR_GLOBAL][3] = make_reg(0, 6);
}
return make_reg(scriptSeg, address);
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 5c6ef06910..d9bb1c3531 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -113,7 +113,7 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) {
reg_t &tmp = dest_r.reg[offset / 2];
bool oddOffset = offset & 1;
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
+ if (g_sci->isBE())
oddOffset = !oddOffset;
if (!oddOffset) {
@@ -159,17 +159,9 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
source++;
}
while (*source) {
- if ((*source < '0') || (*source > '9')) {
- // Sierra's atoi stopped processing at anything which is not
- // a digit. Sometimes the input has a trailing space, that's
- // fine (example: lsl3)
- if (*source != ' ') {
- // TODO: this happens in lsl5 right in the intro -> we get '1' '3' 0xCD 0xCD 0xCD 0xCD 0xCD
- // find out why this happens and fix it
- warning("Invalid character in kReadNumber input");
- }
+ if ((*source < '0') || (*source > '9'))
+ // Stop if we encounter anything other than a digit (like atoi)
break;
- }
result *= 10;
result += *source - 0x30;
source++;
@@ -198,7 +190,6 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
char targetbuf[4096];
char *target = targetbuf;
reg_t position = argv[1]; /* source */
- int index = argv[2].toUint16();
int mode = 0;
int paramindex = 0; /* Next parameter to evaluate */
char xfer;
@@ -209,9 +200,16 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
if (position.segment)
startarg = 2;
- else
+ else {
+ // WORKAROUND: QFG1 VGA Mac calls this without the first parameter (dest). It then
+ // treats the source as the dest and overwrites the source string with an empty string.
+ if (argc < 3)
+ return NULL_REG;
+
startarg = 3; /* First parameter to use for formatting */
+ }
+ int index = (startarg == 3) ? argv[2].toUint16() : 0;
Common::String source_str = g_sci->getKernel()->lookupText(position, index);
const char* source = source_str.c_str();
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 0706da0d9e..6a411d8e23 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -48,8 +48,8 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) {
uint16 width = videoDecoder->getWidth();
uint16 height = videoDecoder->getHeight();
uint16 pitch = videoDecoder->getWidth() * bytesPerPixel;
- uint16 screenWidth = g_system->getWidth();
- uint16 screenHeight = g_system->getHeight();
+ uint16 screenWidth = g_sci->_gfxScreen->getDisplayWidth();
+ uint16 screenHeight = g_sci->_gfxScreen->getDisplayHeight();
videoState.fileName.toLowercase();
bool isVMD = videoState.fileName.hasSuffix(".vmd");
diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp
index bc79e30129..267ba35e3c 100644
--- a/engines/sci/engine/object.cpp
+++ b/engines/sci/engine/object.cpp
@@ -172,11 +172,73 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas
const Object *baseObj = segMan->getObject(getSpeciesSelector());
if (baseObj) {
- _variables.resize(baseObj->getVarCount());
+ uint originalVarCount = _variables.size();
+
+ if (_variables.size() != baseObj->getVarCount())
+ _variables.resize(baseObj->getVarCount());
// Copy base from species class, as we need its selector IDs
_baseObj = baseObj->_baseObj;
if (doInitSuperClass)
initSuperClass(segMan, addr);
+
+ if (_variables.size() != originalVarCount) {
+ // These objects are probably broken.
+ // An example is 'witchCage' in script 200 in KQ5 (#3034714),
+ // but also 'girl' in script 216 and 'door' in script 22.
+ // In LSL3 a number of sound objects trigger this right away.
+ // SQ4-floppy's bug #3037938 also seems related.
+
+ // The effect is that a number of its method selectors may be
+ // treated as variable selectors, causing unpredictable effects.
+ int objScript = segMan->getScript(_pos.segment)->getScriptNumber();
+
+ // We have to do a little bit of work to get the name of the object
+ // before any relocations are done.
+ reg_t nameReg = getNameSelector();
+ const char *name;
+ if (nameReg.isNull()) {
+ name = "<no name>";
+ } else {
+ nameReg.segment = _pos.segment;
+ name = segMan->derefString(nameReg);
+ if (!name)
+ name = "<invalid name>";
+ }
+
+ warning("Object %04x:%04x (name %s, script %d) varnum doesn't "
+ "match baseObj's: obj %d, base %d", PRINT_REG(_pos),
+ name, objScript, originalVarCount, baseObj->getVarCount());
+
+#if 0
+ // We enumerate the methods selectors which could be hidden here
+ if (getSciVersion() <= SCI_VERSION_2_1) {
+ const SegmentRef objRef = segMan->dereference(baseObj->_pos);
+ assert(objRef.isRaw);
+ uint segBound = objRef.maxSize/2 - baseObj->getVarCount();
+ const byte* buf = (const byte *)baseObj->_baseVars;
+ if (!buf) {
+ // While loading this may happen due to objects being loaded
+ // out of order, and we can't proceed then, unfortunately.
+ segBound = 0;
+ }
+ for (uint i = baseObj->getVarCount();
+ i < originalVarCount && i < segBound; ++i) {
+ uint16 slc = READ_SCI11ENDIAN_UINT16(buf + 2*i);
+ // Skip any numbers which happen to be varselectors too
+ bool found = false;
+ for (uint j = 0; j < baseObj->getVarCount() && !found; ++j)
+ found = READ_SCI11ENDIAN_UINT16(buf + 2*j) == slc;
+ if (found) continue;
+ // Skip any selectors which aren't method selectors,
+ // so couldn't be mistaken for varselectors
+ if (lookupSelector(segMan, _pos, slc, 0, 0) != kSelectorMethod) continue;
+ warning(" Possibly affected selector: %02x (%s)", slc,
+ g_sci->getKernel()->getSelectorName(slc).c_str());
+ }
+ }
+#endif
+ }
+
return true;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index a59d4c000b..43d00ebc15 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -47,6 +47,10 @@
#include "sci/sound/audio.h"
#include "sci/sound/music.h"
+#ifdef ENABLE_SCI32
+#include "sci/graphics/frameout.h"
+#endif
+
namespace Sci {
@@ -130,6 +134,13 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
// Reset _scriptSegMap, to be restored below
_scriptSegMap.clear();
+
+#ifdef ENABLE_SCI32
+ // Clear any planes/screen items currently showing so they
+ // don't show up after the load.
+ if (getSciVersion() >= SCI_VERSION_2)
+ g_sci->_gfxFrameout->clear();
+#endif
}
s.skip(4, VER(14), VER(18)); // OBSOLETE: Used to be _exportsAreWide
@@ -144,17 +155,15 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
SegmentType type = (s.isSaving() && mobj) ? mobj->getType() : SEG_TYPE_INVALID;
s.syncAsUint32LE(type);
- // If we were saving and mobj == 0, or if we are loading and this is an
- // entry marked as empty -> skip to next
- if (type == SEG_TYPE_INVALID)
+ if (type == SEG_TYPE_HUNK) {
+ // Don't save or load HunkTable segments
continue;
-
- // Don't save or load HunkTable segments
- if (type == SEG_TYPE_HUNK)
+ } else if (type == SEG_TYPE_INVALID) {
+ // If we were saving and mobj == 0, or if we are loading and this is an
+ // entry marked as empty -> skip to next
continue;
-
- // Don't save or load the obsolete system string segments
- if (type == 5) {
+ } else if (type == 5) {
+ // Don't save or load the obsolete system string segments
if (s.isSaving()) {
continue;
} else {
@@ -168,6 +177,14 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
_heap[i] = NULL; // set as freed
continue;
}
+#ifdef ENABLE_SCI32
+ } else if (type == SEG_TYPE_ARRAY) {
+ // Set the correct segment for SCI32 arrays
+ _arraysSegId = i;
+ } else if (type == SEG_TYPE_STRING) {
+ // Set the correct segment for SCI32 strings
+ _stringSegId = i;
+#endif
}
if (s.isLoading())
@@ -178,8 +195,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
// Let the object sync custom data
mobj->saveLoadWithSerializer(s);
-
- if (type == SEG_TYPE_SCRIPT && s.getVersion() >= 28) {
+ if (type == SEG_TYPE_SCRIPT) {
Script *scr = (Script *)mobj;
// If we are loading a script, perform some extra steps
@@ -196,7 +212,8 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
}
// Sync the script's string heap
- scr->syncStringHeap(s);
+ if (s.getVersion() >= 28)
+ scr->syncStringHeap(s);
}
}
@@ -311,14 +328,14 @@ void Object::saveLoadWithSerializer(Common::Serializer &s) {
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<Clone>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Clone>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer<Object>(s, obj);
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<List>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer(s, obj.first);
@@ -326,7 +343,7 @@ void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) {
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Node>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer(s, obj.pred);
@@ -337,7 +354,7 @@ void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) {
#ifdef ENABLE_SCI32
template <>
-void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciArray<reg_t> >::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
byte type = 0;
@@ -373,7 +390,7 @@ void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &o
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<SciString>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciString>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
uint32 size = 0;
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 6719b73aa5..fb96518f19 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -70,7 +70,7 @@ void Script::init(int script_nr, ResourceManager *resMan) {
Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
if (!script)
- error("Script %d not found\n", script_nr);
+ error("Script %d not found", script_nr);
_localsOffset = 0;
_localsBlock = NULL;
@@ -129,6 +129,17 @@ void Script::load(ResourceManager *resMan) {
Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0);
assert(script != 0);
+ uint extraLocalsWorkaround = 0;
+ if (g_sci->getGameId() == GID_FANMADE && _nr == 1 && script->size == 11140) {
+ // WORKAROUND: Script 1 in Ocean Battle doesn't have enough locals to
+ // fit the string showing how many shots are left (a nasty script bug,
+ // corrupting heap memory). We add 10 more locals so that it has enough
+ // space to use as the target for its kFormat operation. Fixes bug
+ // #3059871.
+ extraLocalsWorkaround = 10;
+ }
+ _bufSize += extraLocalsWorkaround * 2;
+
_buf = (byte *)malloc(_bufSize);
assert(_buf);
@@ -187,6 +198,9 @@ void Script::load(ResourceManager *resMan) {
_localsOffset = 24 + _numExports * 2;
}
+ // WORKAROUND: Increase locals, if needed (check above)
+ _localsCount += extraLocalsWorkaround;
+
if (getSciVersion() == SCI_VERSION_0_EARLY) {
// SCI0 early
// Old script block. There won't be a localvar block in this case.
@@ -202,7 +216,7 @@ void Script::load(ResourceManager *resMan) {
if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) {
error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize);
- _localsCount = (_bufSize - _localsOffset) >> 1;
+ //_localsCount = (_bufSize - _localsOffset) >> 1;
}
}
}
@@ -243,9 +257,8 @@ Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) {
if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit)
obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
- VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n");
-
- VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n");
+ if (obj_pos.offset >= _bufSize)
+ error("Attempt to initialize object beyond end of script");
// Get the object at the specified position and init it. This will
// automatically "allocate" space for it in the _objects map if necessary.
@@ -313,8 +326,9 @@ void Script::relocateSci0Sci21(reg_t block) {
heapOffset = _scriptSize;
}
- VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize,
- "Relocation block outside of script\n");
+ if (block.offset >= (uint16)heapSize ||
+ READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset >= (uint16)heapSize)
+ error("Relocation block outside of script");
int count = READ_SCI11ENDIAN_UINT16(heap + block.offset);
int exportIndex = 0;
@@ -404,7 +418,8 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) {
offset = relocateOffsetSci3(pubfunct * 2 + 22);
}
- VERIFY(offset < _bufSize, "invalid export function pointer");
+ if (offset >= _bufSize)
+ error("Invalid export function pointer");
// Check if the offset found points to a second export table (e.g. script 912
// in Camelot and script 306 in KQ4). Such offsets are usually small (i.e. < 10),
@@ -418,7 +433,8 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) {
if (secondExportTable) {
secondExportTable += 3; // skip header plus 2 bytes (secondExportTable is a uint16 pointer)
offset = READ_SCI11ENDIAN_UINT16(secondExportTable + pubfunct);
- VERIFY(offset < _bufSize, "invalid export function pointer");
+ if (offset >= _bufSize)
+ error("Invalid export function pointer");
}
}
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 5191887e47..54ae88a17e 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -60,55 +60,6 @@ struct SciScriptSignature {
// - if not EOS, an adjust offset and the actual bytes
// - rinse and repeat
-#if 0
-
-// ===========================================================================
-// Castle of Dr. Brain
-// cipher::init (script 391) is called on room 380 init. This resets the word
-// cipher puzzle. The puzzle sadly operates on some hep strings, which aren't
-// saved in our sci. So saving/restoring in this room will break the puzzle
-// Because of this issue, we just init the puzzle each time it's accessed.
-// this is not 100% sierra behaviour, in fact we will actually reset the puzzle
-// during each access which makes it impossible to cheat.
-const byte castlebrainSignatureCipherPuzzle[] = {
- 22,
- 0x35, 0x00, // ldi 00
- 0xa3, 0x26, // sal local[26]
- 0xa3, 0x25, // sal local[25]
- 0x35, 0x00, // ldi 00
- 0xa3, 0x2a, // sal local[2a] (local is not used)
- 0xa3, 0x29, // sal local[29] (local is not used)
- 0x35, 0xff, // ldi ff
- 0xa3, 0x2c, // sal local[2c]
- 0xa3, 0x2b, // sal local[2b]
- 0x35, 0x00, // ldi 00
- 0x65, 0x16, // aTop highlightedIcon
- 0
-};
-
-const uint16 castlebrainPatchCipherPuzzle[] = {
- 0x39, 0x6b, // pushi 6b (selector init)
- 0x76, // push0
- 0x55, 0x04, // self 04
- 0x35, 0x00, // ldi 00
- 0xa3, 0x25, // sal local[25]
- 0xa3, 0x26, // sal local[26]
- 0xa3, 0x29, // sal local[29]
- 0x65, 0x16, // aTop highlightedIcon
- 0x34, 0xff, 0xff, // ldi ffff
- 0xa3, 0x2b, // sal local[2b]
- 0xa3, 0x2c, // sal local[2c]
- PATCH_END
-};
-
-// script, description, magic DWORD, adjust
-const SciScriptSignature castlebrainSignatures[] = {
- { 391, "cipher puzzle save/restore break", 1, PATCH_MAGICDWORD(0xa3, 0x26, 0xa3, 0x25), -2, castlebrainSignatureCipherPuzzle, castlebrainPatchCipherPuzzle },
- SCI_SIGNATUREENTRY_TERMINATOR
-};
-
-#endif
-
// ===========================================================================
// stayAndHelp::changeState (0) is called when ego swims to the left or right
// boundaries of room 660. Normally a textbox is supposed to get on screen
@@ -355,12 +306,12 @@ const uint16 freddypharkasPatchScoreDisposal[] = {
};
// script 235 of freddy pharkas rm235::init and sEnterFrom500::changeState
-// disable icon 7+8 of iconbar (CD only). When picking up the cannister after
+// disable icon 7+8 of iconbar (CD only). When picking up the canister after
// placing it down, the scripts will disable all the other icons. This results
// in IconBar::disable doing endless loops even in sierra sci, because there
// is no enabled icon left. We remove disabling of icon 8 (which is help),
// this fixes the issue.
-const byte freddypharkasSignatureCannisterHang[] = {
+const byte freddypharkasSignatureCanisterHang[] = {
12,
0x38, 0xf1, 0x00, // pushi f1 (selector disable)
0x7a, // push2
@@ -371,7 +322,7 @@ const byte freddypharkasSignatureCannisterHang[] = {
0
};
-const uint16 freddypharkasPatchCannisterHang[] = {
+const uint16 freddypharkasPatchCanisterHang[] = {
PATCH_ADDTOOFFSET | +3,
0x78, // push1
PATCH_ADDTOOFFSET | +2,
@@ -418,7 +369,7 @@ const uint16 freddypharkasPatchLadderEvent[] = {
// script, description, magic DWORD, adjust
const SciScriptSignature freddypharkasSignatures[] = {
{ 0, "CD: score early disposal", 1, PATCH_MAGICDWORD(0x39, 0x0d, 0x43, 0x75), -3, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
- { 235, "CD: cannister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCannisterHang, freddypharkasPatchCannisterHang },
+ { 235, "CD: canister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang },
{ 320, "ladder event issue", 2, PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -497,74 +448,6 @@ const SciScriptSignature gk1Signatures[] = {
SCI_SIGNATUREENTRY_TERMINATOR
};
-#if 0
-
-// ===========================================================================
-// this here gets called on entry and when going out of game windows
-// uEvt::port will not get changed after kDisposeWindow but a bit later, so
-// we would get an invalid port handle to a kSetPort call. We just patch in
-// resetting of the port selector. We destroy the stop/fade code in there,
-// it seems it isn't used at all in the game.
-const byte hoyle4SignaturePortFix[] = {
- 28,
- 0x39, 0x09, // pushi 09
- 0x89, 0x0b, // lsg 0b
- 0x39, 0x64, // pushi 64
- 0x38, 0xc8, 0x00, // pushi 00c8
- 0x38, 0x2c, 0x01, // pushi 012c
- 0x38, 0x90, 0x01, // pushi 0190
- 0x38, 0xf4, 0x01, // pushi 01f4
- 0x38, 0x58, 0x02, // pushi 0258
- 0x38, 0xbc, 0x02, // pushi 02bc
- 0x38, 0x20, 0x03, // pushi 0320
- 0x46, // calle [xxxx] [xxxx] [xx]
- +5, 43, // [skip 5 bytes]
- 0x30, 0x27, 0x00, // bnt 0027 -> end of routine
- 0x87, 0x00, // lap 00
- 0x30, 0x19, 0x00, // bnt 0019 -> fade out
- 0x87, 0x01, // lap 01
- 0x30, 0x14, 0x00, // bnt 0014 -> fade out
- 0x38, 0xa7, 0x00, // pushi 00a7
- 0x76, // push0
- 0x80, 0x29, 0x01, // lag 0129
- 0x4a, 0x04, // send 04 - call song::stop
- 0x39, 0x27, // pushi 27
- 0x78, // push1
- 0x8f, 0x01, // lsp 01
- 0x51, 0x54, // class 54
- 0x4a, 0x06, // send 06 - call PlaySong::play
- 0x33, 0x09, // jmp 09 -> end of routine
- 0x38, 0xaa, 0x00, // pushi 00aa
- 0x76, // push0
- 0x80, 0x29, 0x01, // lag 0129
- 0x4a, 0x04, // send 04
- 0x48, // ret
- 0
-};
-
-const uint16 hoyle4PatchPortFix[] = {
- PATCH_ADDTOOFFSET | +33,
- 0x38, 0x31, 0x01, // pushi 0131 (selector curEvent)
- 0x76, // push0
- 0x80, 0x50, 0x00, // lag 0050 (global var 80h, "User")
- 0x4a, 0x04, // send 04 - read User::curEvent
-
- 0x38, 0x93, 0x00, // pushi 0093 (selector port)
- 0x78, // push1
- 0x76, // push0
- 0x4a, 0x06, // send 06 - write 0 to that object::port
- 0x48, // ret
- PATCH_END
-};
-
-// script, description, magic DWORD, adjust
-const SciScriptSignature hoyle4Signatures[] = {
- { 0, "port fix when disposing windows", PATCH_MAGICDWORD(0x64, 0x38, 0xC8, 0x00), -5, hoyle4SignaturePortFix, hoyle4PatchPortFix },
- { 0, NULL, 0, 0, NULL, NULL }
-};
-
-#endif
-
// ===========================================================================
// at least during harpy scene export 29 of script 0 is called in kq5cd and
// has an issue for those calls, where temp 3 won't get inititialized, but
@@ -615,9 +498,121 @@ const uint16 kq5PatchCdHarpyVolume[] = {
PATCH_END
};
+// This is a heap patch, and it modifies the properties of an object, instead
+// of patching script code.
+//
+// The witchCage object in script 200 is broken and claims to have 12
+// variables instead of the 8 it should have because it is a Cage.
+// Additionally its top,left,bottom,right properties are set to 0 rather
+// than the right values. We fix the object by setting the right values.
+// If they are all zero, this causes an impossible position check in
+// witch::cantBeHere and an infinite loop when entering room 22 (bug #3034714).
+//
+// This bug is accidentally not triggered in SSCI because the invalid number
+// of variables effectively hides witchCage::doit, causing this position check
+// to be bypassed entirely.
+// See also the warning+comment in Object::initBaseObject
+const byte kq5SignatureWitchCageInit[] = {
+ 16,
+ 0x00, 0x00, // top
+ 0x00, 0x00, // left
+ 0x00, 0x00, // bottom
+ 0x00, 0x00, // right
+ 0x00, 0x00, // extra property #1
+ 0x7a, 0x00, // extra property #2
+ 0xc8, 0x00, // extra property #3
+ 0xa3, 0x00, // extra property #4
+ 0
+};
+
+const uint16 kq5PatchWitchCageInit[] = {
+ 0x00, 0x00, // top
+ 0x7a, 0x00, // left
+ 0xc8, 0x00, // bottom
+ 0xa3, 0x00, // right
+ PATCH_END
+};
+
// script, description, magic DWORD, adjust
const SciScriptSignature kq5Signatures[] = {
{ 0, "CD: harpy volume change", 1, PATCH_MAGICDWORD(0x80, 0x91, 0x01, 0x18), 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
+ { 200, "CD: witch cage init", 1, PATCH_MAGICDWORD(0x7a, 0x00, 0xc8, 0x00), -10, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// When giving the milk bottle to one of the babies in the garden in KQ6 (room
+// 480), script 481 starts a looping baby cry sound. However, that particular
+// script also has an overriden check method (cryMusic::check). This method
+// explicitly restarts the sound, even if it's set to be looped, thus the same
+// sound is played twice, squelching all other sounds. We just rip the
+// unnecessary cryMusic::check method out, thereby stopping the sound from
+// constantly restarting (since it's being looped anyway), thus the normal
+// game speech can work while the baby cry sound is heard. Fixes bug #3034579.
+const byte kq6SignatureDuplicateBabyCry[] = {
+ 10,
+ 0x83, 0x00, // lal 00
+ 0x31, 0x1e, // bnt 1e [07f4]
+ 0x78, // push1
+ 0x39, 0x04, // pushi 04
+ 0x43, 0x75, 0x02, // callk DoAudio[75] 02
+ 0
+};
+
+const uint16 kq6PatchDuplicateBabyCry[] = {
+ 0x48, // ret
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature kq6Signatures[] = {
+ { 481, "duplicate baby cry", 1, PATCH_MAGICDWORD(0x83, 0x00, 0x31, 0x1e), 0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// Script 210 in the German version of Longbow handles the case where Robin
+// hands out the scroll to Marion and then types his name using the hand code.
+// The German version script contains a typo (probably a copy/paste error),
+// and the function that is used to show each letter is called twice. The
+// second time that the function is called, the second parameter passed to
+// the function is undefined, thus kStrCat() that is called inside the function
+// reads a random pointer and crashes. We patch all of the 5 function calls
+// (one for each letter typed from "R", "O", "B", "I", "N") so that they are
+// the same as the English version. Fixes bug #3048054.
+const byte longbowSignatureShowHandCode[] = {
+ 3,
+ 0x78, // push1
+ 0x78, // push1
+ 0x72, // lofsa
+ +2, 2, // skip 2 bytes, offset of lofsa (the letter typed)
+ 0x36, // push
+ 0x40, // call
+ +2, 3, // skip 2 bytes, offset of call
+ 0x02, // perform the call above with 2 parameters
+ 0x36, // push
+ 0x40, // call
+ +2, 8, // skip 2 bytes, offset of call
+ 0x02, // perform the call above with 2 parameters
+ 0x38, 0x1c, 0x01, // pushi 011c (setMotion)
+ 0x39, 0x04, // pushi 04 (x)
+ 0x51, 0x1e, // class MoveTo
+ 0
+};
+
+const uint16 longbowPatchShowHandCode[] = {
+ 0x39, 0x01, // pushi 1 (combine the two push1's in one, like in the English version)
+ PATCH_ADDTOOFFSET | +3, // leave the lofsa call untouched
+ // The following will remove the duplicate call
+ 0x32, 0x02, 0x00, // jmp 02 - skip 2 bytes (the remainder of the first call)
+ 0x48, // ret (dummy, should never be reached)
+ 0x48, // ret (dummy, should never be reached)
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature longbowSignatures[] = {
+ { 210, "hand code crash", 5, PATCH_MAGICDWORD(0x02, 0x38, 0x1c, 0x01), -14, longbowSignatureShowHandCode, longbowPatchShowHandCode },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -673,7 +668,7 @@ const SciScriptSignature larry6Signatures[] = {
};
// ===========================================================================
-// rm560::doit was supposed to close the painting, when heimlich enters the
+// rm560::doit was supposed to close the painting, when Heimlich enters the
// room. The code is buggy, so it actually closes the painting, when heimlich
// is not in the room. We fix that.
const byte laurabow2SignaturePaintingClosing[] = {
@@ -796,44 +791,10 @@ const uint16 qfg1vgaPatchFightEvents[] = {
PATCH_END
};
-// When QFG1VGA and QFG3 dispose of a child window. For example, when choosing
-// a spell (parent window), if the spell can't be casted, a subsequent window
-// opens, notifying that it can't be casted. When showing the child window, the
-// scripts restore the area below the parent window, draw the child window, and
-// then attempt to redraw the parent window, which leads to the background
-// picture (which has just been restored) overwriting the child window. It
-// appers that kGraph(redrawBox) is different in QFG1VGA and QFG3. However, we
-// can just remove the window redraw and update calls when the window is
-// supposed to be disposed, and the window is disposed of correctly. Fixes bug
-// #3053093.
-const byte qfg1vgaWindowDispose[] = {
- 17,
- 0x39, 0x05, // pushi 05
- 0x39, 0x0d, // pushi 0d
- 0x67, 0x2e, // pTos 2e
- 0x67, 0x30, // pTos 30
- 0x67, 0x32, // pTos 32
- 0x67, 0x34, // pTos 34
- 0x43, 0x6c, 0x0a, // callk kGraph 10
- 0x39, 0x06, // pushi 06
- 0
-};
-
-const uint16 qfg1vgaPatchWindowDispose[] = {
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x33, 0x3e, // jmp 0x3e (skip 62 bytes - this skips the subsequent 2 kGraph(update) calls, before kDisposeWindow is invoked)
- PATCH_END
-};
-
// script, description, magic DWORD, adjust
const SciScriptSignature qfg1vgaSignatures[] = {
{ 215, "fight event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
{ 216, "weapon master event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
- { 559, "window dispose", 1, PATCH_MAGICDWORD(0x39, 0x05, 0x39, 0x0d), 0, qfg1vgaWindowDispose, qfg1vgaPatchWindowDispose },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -897,40 +858,25 @@ const uint16 qfg3PatchImportDialog[] = {
PATCH_END
};
-// When QFG1VGA and QFG3 dispose of a child window. For example, when choosing
-// a spell (parent window), if the spell can't be casted, a subsequent window
-// opens, notifying that it can't be casted. When showing the child window, the
-// scripts restore the area below the parent window, draw the child window, and
-// then attempt to redraw the parent window, which leads to the background
-// picture (which has just been restored) overwriting the child window. It
-// appers that kGraph(redrawBox) is different in QFG1VGA and QFG3. However, we
-// can just remove the window redraw and update calls when the window is
-// supposed to be disposed, and the window is disposed of correctly. Fixes bug
-// #3053093.
-const byte qfg3WindowDispose[] = {
- 15,
- 0x39, 0x05, // pushi 05
- 0x39, 0x0d, // pushi 0d
- 0x67, 0x2e, // pTos 2e
- 0x67, 0x30, // pTos 30
- 0x67, 0x32, // pTos 32
- 0x67, 0x34, // pTos 34
- 0x43, 0x6c, 0x0a, // callk kGraph 10
- 0
+// 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
};
-const uint16 qfg3PatchWindowDispose[] = {
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
+const uint16 qfg3PatchDialogCrash[] = {
+ 0x34, 0xe7, 0x03, // ldi 3e7 (999)
+ 0x22, // lt?
+ 0x31, // bnt [back]
PATCH_END
};
// script, description, magic DWORD, adjust
const SciScriptSignature qfg3Signatures[] = {
- { 22, "window dispose", 1, PATCH_MAGICDWORD(0x39, 0x05, 0x39, 0x0d), 0, qfg3WindowDispose, qfg3PatchWindowDispose },
+ { 23, "dialog crash", 1, PATCH_MAGICDWORD(0xe7, 0x03, 0x22, 0x33), -1, qfg3DialogCrash, qfg3PatchDialogCrash },
{ 944, "import dialog continuous calls", 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a), -1, qfg3SignatureImportDialog, qfg3PatchImportDialog },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -1048,54 +994,52 @@ const SciScriptSignature sq4Signatures[] = {
SCI_SIGNATUREENTRY_TERMINATOR
};
-// ===========================================================================
-// It seems to scripts warp ego outside the screen somehow (or maybe kDoBresen?)
-// ego::mover is set to 0 and rm119::doit will crash in that case. This here
-// fixes part of the problem and actually checks ego::mover to be 0 and skips
-// TODO: this should get further investigated by waltervn and maybe properly
-// patched. For now ego will shortly disappear and reappear a bit after
-// this isn't good, but sierra sci also "crashed" (endless looped) so this
-// is at least better than the original code
-const byte sq5SignatureScrubbing[] = {
- 19,
- 0x18, // not
- 0x31, 0x37, // bnt 37
- 0x78, // push1 (selector x)
+const byte sq1vgaSignatureEgoShowsCard[] = {
+ 25,
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
+ 0x78, // push1
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to get timesShownID)
0x76, // push0
- 0x39, 0x38, // pushi 38 (selector mover)
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x04, // send 0x04 (get timesShownID)
+ 0x36, // push
+ 0x35, 0x01, // ldi 1
+ 0x02, // add
+ 0x36, // push
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x06, // send 0x06 (set timesShownID)
+ 0x36, // push (wrong, acc clobbered by class, above)
+ 0x35, 0x03, // ldi 0x03
+ 0x22, // lt?
+ 0};
+
+// Note that this script patch is merely a reordering of the
+// instructions in the original script.
+const uint16 sq1vgaPatchEgoShowsCard[] = {
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to get timesShownID)
0x76, // push0
- 0x81, 0x00, // lag 00
- 0x4a, 0x04, // send 04 - read ego::mover
- 0x4a, 0x04, // send 04 - read ego::mover::x
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x04, // send 0x04 (get timesShownID)
0x36, // push
- 0x34, 0xa0, 0x00, // ldi 00a0
- 0x1c, // ne?
- 0
-};
+ 0x35, 0x01, // ldi 1
+ 0x02, // add
+ 0x36, // push (this push corresponds to the wrong one above)
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
+ 0x78, // push1
+ 0x36, // push
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x06, // send 0x06 (set timesShownID)
+ 0x35, 0x03, // ldi 0x03
+ 0x22, // lt?
+ PATCH_END};
-const uint16 sq5PatchScrubbing[] = {
- 0x18, // not
- 0x31, 0x37, // bnt 37
-// 0x2f, 0x38, // bt 37 (would save another byte, isn't needed
- 0x39, 0x38, // pushi 38 (selector mover)
- 0x76, // push0
- 0x81, 0x00, // lag 00
- 0x4a, 0x04, // send 04 - read ego::mover
- 0x31, 0x2e, // bnt 2e (jump if ego::mover is 0)
- 0x78, // push1 (selector x)
- 0x76, // push0
- 0x4a, 0x04, // send 04 - read ego::mover::x
- 0x39, 0xa0, // pushi a0 (saving 2 bytes)
- 0x1c, // ne?
- PATCH_END
-};
// script, description, magic DWORD, adjust
-const SciScriptSignature sq5Signatures[] = {
- { 119, "scrubbing send crash", 1, PATCH_MAGICDWORD(0x18, 0x31, 0x37, 0x78), 0, sq5SignatureScrubbing, sq5PatchScrubbing },
- SCI_SIGNATUREENTRY_TERMINATOR
-};
+const SciScriptSignature sq1vgaSignatures[] = {
+ { 58, "Sarien armory droid zapping ego first time", 1, PATCH_MAGICDWORD( 0x72, 0x88, 0x15, 0x36 ), -70,
+ sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
+ SCI_SIGNATUREENTRY_TERMINATOR};
// will actually patch previously found signature area
void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset) {
@@ -1189,12 +1133,6 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
const SciScriptSignature *signatureTable = NULL;
switch (g_sci->getGameId()) {
- // Dr. Brain now works because we properly maintain the state of the string heap in savegames
-#if 0
- case GID_CASTLEBRAIN:
- signatureTable = castlebrainSignatures;
- break;
-#endif
case GID_ECOQUEST:
signatureTable = ecoquest1Signatures;
break;
@@ -1210,18 +1148,18 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
case GID_GK1:
signatureTable = gk1Signatures;
break;
- // hoyle4 now works due to workaround inside GfxPorts
-#if 0
- case GID_HOYLE4:
- signatureTable = hoyle4Signatures;
- break;
-#endif
case GID_KQ5:
signatureTable = kq5Signatures;
break;
+ case GID_KQ6:
+ signatureTable = kq6Signatures;
+ break;
case GID_LAURABOW2:
signatureTable = laurabow2Signatures;
break;
+ case GID_LONGBOW:
+ signatureTable = longbowSignatures;
+ break;
case GID_LSL6:
signatureTable = larry6Signatures;
break;
@@ -1237,12 +1175,12 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
case GID_QFG3:
signatureTable = qfg3Signatures;
break;
+ case GID_SQ1:
+ signatureTable = sq1vgaSignatures;
+ break;
case GID_SQ4:
signatureTable = sq4Signatures;
break;
- case GID_SQ5:
- signatureTable = sq5Signatures;
- break;
default:
break;
}
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 184f81bb99..596494d61b 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -208,12 +208,12 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode
if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode
if (opcode == op_callk) {
- int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjust);
+ int stackframe = (scr[pos.offset + 2] >> 1) + (s->r_rest);
int argc = ((s->xs->sp)[- stackframe - 1]).offset;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
if (!oldScriptHeader)
- argc += (s->restAdjust);
+ argc += (s->r_rest);
debugN(" Kernel params: (");
@@ -224,7 +224,7 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode
}
debugN(")\n");
} else if ((opcode == op_send) || (opcode == op_self)) {
- int restmod = s->restAdjust;
+ int restmod = s->r_rest;
int stackframe = (scr[pos.offset + 1] >> 1) + restmod;
reg_t *sb = s->xs->sp;
uint16 selector;
@@ -281,6 +281,34 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode
return retval;
}
+bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) {
+ SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT);
+ if (!mobj)
+ return false;
+ Script *script_entity = (Script *)mobj;
+
+ const byte *scr = script_entity->getBuf();
+ int scr_size = script_entity->getBufSize();
+
+ if (pos.offset >= scr_size)
+ return false;
+
+ int16 opparams[4];
+ byte opsize;
+ int bytecount = readPMachineInstruction(scr + pos.offset, opsize, opparams);
+ const byte opcode = opsize >> 1;
+
+ switch (opcode) {
+ case op_bt:
+ case op_bnt:
+ case op_jmp:
+ jumpTarget = pos + bytecount + opparams[0];
+ return true;
+ default:
+ return false;
+ }
+}
+
void SciEngine::scriptDebug() {
EngineState *s = _gamestate;
@@ -542,4 +570,187 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
debugN("Script ends without terminator\n");
}
+bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) {
+ Common::String methodName = _gamestate->_segMan->getObjectName(send_obj);
+ methodName += ("::" + getKernel()->getSelectorName(selector));
+
+ Common::List<Breakpoint>::const_iterator bpIter;
+ for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) {
+ if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) {
+ _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj));
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
+ if (_debugState._activeBreakpointTypes & BREAK_EXPORT) {
+ uint32 bpaddress = (script << 16 | pubfunct);
+
+ Common::List<Breakpoint>::const_iterator bp;
+ for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
+ if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
+ _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType) {
+ int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes;
+ const char *objectName = segMan->getObjectName(send_obj);
+ const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str();
+ Console *con = g_sci->getSciDebugger();
+
+#ifdef VM_DEBUG_SEND
+ debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),
+ s->_segMan->getObjectName(send_obj), selector,
+ g_sci->getKernel()->getSelectorName(selector).c_str());
+#endif // VM_DEBUG_SEND
+
+ switch (selectorType) {
+ case kSelectorNone:
+ break;
+ case kSelectorVariable:
+#ifdef VM_DEBUG_SEND
+ if (argc)
+ debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1]));
+ else
+ debugN("Varselector: Read\n");
+#endif // VM_DEBUG_SEND
+
+ // argc == 0: read selector
+ // argc == 1: write selector
+ // argc can be bigger than 1 in some cases, because of a script bug.
+ // Usually, these aren't fatal.
+ if ((activeBreakpointTypes & BREAK_SELECTORREAD) ||
+ (activeBreakpointTypes & BREAK_SELECTORWRITE) ||
+ argc > 1) {
+
+ reg_t selectorValue = *varp.getPointer(segMan);
+ if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector))
+ con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n",
+ objectName, selectorName,
+ PRINT_REG(selectorValue));
+ } else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector))
+ con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n",
+ objectName, selectorName,
+ PRINT_REG(selectorValue), PRINT_REG(argp[1]));
+ }
+
+ if (argc > 1)
+ debug(kDebugLevelScripts, "Write to selector (%s:%s): change %04x:%04x to %04x:%04x, argc == %d\n",
+ objectName, selectorName,
+ PRINT_REG(selectorValue), PRINT_REG(argp[1]), argc);
+ }
+ break;
+ case kSelectorMethod:
+#ifndef VM_DEBUG_SEND
+ if (activeBreakpointTypes & BREAK_SELECTOREXEC) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) {
+#else
+ if (true) {
+ if (true) {
+#endif
+ con->DebugPrintf("%s::%s(", objectName, selectorName);
+ for (int i = 0; i < argc; i++) {
+ con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1]));
+ if (i + 1 < argc)
+ con->DebugPrintf(", ");
+ }
+ con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp));
+ }
+ }
+ break;
+ } // switch
+}
+
+void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) {
+ Kernel *kernel = g_sci->getKernel();
+ if (!kernelSubCall) {
+ debugN("k%s: ", kernelCall->name);
+ } else {
+ int callNameLen = strlen(kernelCall->name);
+ if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) {
+ const char *subCallName = kernelSubCall->name + callNameLen;
+ debugN("k%s(%s): ", kernelCall->name, subCallName);
+ } else {
+ debugN("k%s(%s): ", kernelCall->name, kernelSubCall->name);
+ }
+ }
+ for (int parmNr = 0; parmNr < argc; parmNr++) {
+ if (parmNr)
+ debugN(", ");
+ uint16 regType = kernel->findRegType(argv[parmNr]);
+ if (regType & SIG_TYPE_NULL)
+ debugN("0");
+ else if (regType & SIG_TYPE_UNINITIALIZED)
+ debugN("UNINIT");
+ else if (regType & SIG_IS_INVALID)
+ debugN("INVALID");
+ else if (regType & SIG_TYPE_INTEGER)
+ debugN("%d", argv[parmNr].offset);
+ else {
+ debugN("%04x:%04x", PRINT_REG(argv[parmNr]));
+ switch (regType) {
+ case SIG_TYPE_OBJECT:
+ debugN(" (%s)", s->_segMan->getObjectName(argv[parmNr]));
+ break;
+ case SIG_TYPE_REFERENCE:
+ {
+ SegmentObj *mobj = s->_segMan->getSegmentObj(argv[parmNr].segment);
+ switch (mobj->getType()) {
+ case SEG_TYPE_HUNK:
+ {
+ HunkTable *ht = (HunkTable*)mobj;
+ int index = argv[parmNr].offset;
+ if (ht->isValidEntry(index)) {
+ // NOTE: This ", deleted" isn't as useful as it could
+ // be because it prints the status _after_ the kernel
+ // call.
+ debugN(" ('%s' hunk%s)", ht->_table[index].type, ht->_table[index].mem ? "" : ", deleted");
+ } else
+ debugN(" (INVALID hunk ref)");
+ break;
+ }
+ default:
+ // TODO: Any other segment types which could
+ // use special handling?
+
+ if (kernelCall->function == kSaid) {
+ SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]);
+ if (saidSpec.isRaw) {
+ debugN(" ('");
+ g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw);
+ debugN("')");
+ } else {
+ debugN(" (non-raw said-spec)");
+ }
+ } else {
+ debugN(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str());
+ }
+ break;
+ }
+ }
+ default:
+ break;
+ }
+ }
+ }
+ if (result.isPointer())
+ debugN(" = %04x:%04x\n", PRINT_REG(result));
+ else
+ debugN(" = %d\n", result.offset);
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index ffc81f0fde..0dc245a991 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -63,7 +63,7 @@ void SegManager::resetSegMan() {
// Free memory
for (uint i = 0; i < _heap.size(); i++) {
if (_heap[i])
- deallocate(i, false);
+ deallocate(i);
}
_heap.clear();
@@ -151,16 +151,17 @@ Script *SegManager::allocateScript(int script_nr, SegmentId *segid) {
return (Script *)mem;
}
-void SegManager::deallocate(SegmentId seg, bool recursive) {
- VERIFY(check(seg), "invalid seg id");
+void SegManager::deallocate(SegmentId seg) {
+ if (!check(seg))
+ error("SegManager::deallocate(): invalid segment ID");
SegmentObj *mobj = _heap[seg];
if (mobj->getType() == SEG_TYPE_SCRIPT) {
Script *scr = (Script *)mobj;
_scriptSegMap.erase(scr->getScriptNumber());
- if (recursive && scr->_localsSegment)
- deallocate(scr->_localsSegment, recursive);
+ if (scr->_localsSegment)
+ deallocate(scr->_localsSegment);
}
delete mobj;
@@ -176,8 +177,7 @@ bool SegManager::isHeapObject(reg_t pos) const {
}
void SegManager::deallocateScript(int script_nr) {
- SegmentId seg = getScriptSegment(script_nr);
- deallocate(seg, true);
+ deallocate(getScriptSegment(script_nr));
}
Script *SegManager::getScript(const SegmentId seg) {
@@ -360,9 +360,8 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr) {
if (scr->_localsSegment) {
locals = (LocalVariables *)_heap[scr->_localsSegment];
- VERIFY(locals != NULL, "Re-used locals segment was NULL'd out");
- VERIFY(locals->getType() == SEG_TYPE_LOCALS, "Re-used locals segment did not consist of local variables");
- VERIFY(locals->script_id == scr->getScriptNumber(), "Re-used locals segment belonged to other script");
+ if (!locals || locals->getType() != SEG_TYPE_LOCALS || locals->script_id != scr->getScriptNumber())
+ error("Invalid script locals segment while allocating locals");
} else
locals = (LocalVariables *)allocSegment(new LocalVariables(), &scr->_localsSegment);
@@ -403,7 +402,7 @@ void SegManager::freeHunkEntry(reg_t addr) {
return;
}
- ht->freeEntry(addr.offset);
+ ht->freeEntryContents(addr.offset);
}
reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
@@ -602,13 +601,13 @@ static inline char getChar(const SegmentRef &ref, uint offset) {
warning("Attempt to read character from non-raw data");
bool oddOffset = offset & 1;
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- oddOffset = !oddOffset; // Amiga versions are BE
+ if (g_sci->isBE())
+ oddOffset = !oddOffset;
return (oddOffset ? val.offset >> 8 : val.offset & 0xff);
}
-static inline void setChar(const SegmentRef &ref, uint offset, char value) {
+static inline void setChar(const SegmentRef &ref, uint offset, byte value) {
if (ref.skipByte)
offset++;
@@ -617,8 +616,8 @@ static inline void setChar(const SegmentRef &ref, uint offset, char value) {
val->segment = 0;
bool oddOffset = offset & 1;
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- oddOffset = !oddOffset; // Amiga versions are BE
+ if (g_sci->isBE())
+ oddOffset = !oddOffset;
if (oddOffset)
val->offset = (val->offset & 0x00ff) | (value << 8);
@@ -864,7 +863,7 @@ bool SegManager::freeDynmem(reg_t addr) {
if (addr.segment < 1 || addr.segment >= _heap.size() || !_heap[addr.segment] || _heap[addr.segment]->getType() != SEG_TYPE_DYNMEM)
return false; // error
- deallocate(addr.segment, true);
+ deallocate(addr.segment);
return true; // OK
}
@@ -1022,7 +1021,7 @@ void SegManager::uninstantiateScript(int script_nr) {
SegmentId segmentId = getScriptSegment(script_nr);
Script *scr = getScriptIfLoaded(segmentId);
- if (!scr) { // Is it already unloaded?
+ if (!scr || scr->isMarkedAsDeleted()) { // Is it already unloaded?
//warning("unloading script 0x%x requested although not loaded", script_nr);
// This is perfectly valid SCI behaviour
return;
@@ -1079,15 +1078,7 @@ void SegManager::uninstantiateScriptSci0(int script_nr) {
if (scr->getLockers())
scr->decrementLockers(); // Decrease lockers if this is us ourselves
} else {
- if (g_sci->getGameId() == GID_HOYLE3 && (superclass_script == 0 || superclass_script >= 990)) {
- // HACK for Hoyle 3: when exiting Checkers or Pachisi, scripts 0, 999 and some others
- // are deleted but are never instantiated again. We ignore deletion of these scripts
- // here for Hoyle 3 - bug #3038837
- // TODO/FIXME: find out why this happens, seems like there is a problem with the object
- // lock code
- } else {
- uninstantiateScript(superclass_script);
- }
+ uninstantiateScript(superclass_script);
}
// Recurse to assure that the superclass lockers number gets decreased
}
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 61fa2e2245..d402afbf1a 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -36,15 +36,6 @@
namespace Sci {
/**
- * Verify the the given condition is true, output the message if condition is false, and exit.
- * @param cond condition to be verified
- * @param msg the message to be printed if condition fails
- */
-#define VERIFY( cond, msg ) if (!(cond)) {\
- error("%s, line, %d, %s", __FILE__, __LINE__, msg); \
- }
-
-/**
* Parameters for getScriptSegment().
*/
enum ScriptLoadType {
@@ -477,7 +468,7 @@ private:
private:
SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid);
- void deallocate(SegmentId seg, bool recursive);
+ void deallocate(SegmentId seg);
void createClassTable();
SegmentId findFreeSegment() const;
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index 05d914cffb..2bb77c707a 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -39,7 +39,6 @@ namespace Sci {
//#define GC_DEBUG // Debug garbage collection
//#define GC_DEBUG_VERBOSE // Debug garbage verbosely
-
SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
SegmentObj *mem = 0;
switch (type) {
@@ -85,116 +84,12 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
return mem;
}
-const char *SegmentObj::getSegmentTypeName(SegmentType type) {
- switch (type) {
- case SEG_TYPE_SCRIPT:
- return "script";
- break;
- case SEG_TYPE_CLONES:
- return "clones";
- break;
- case SEG_TYPE_LOCALS:
- return "locals";
- break;
- case SEG_TYPE_STACK:
- return "stack";
- break;
- case SEG_TYPE_HUNK:
- return "hunk";
- break;
- case SEG_TYPE_LISTS:
- return "lists";
- break;
- case SEG_TYPE_NODES:
- return "nodes";
- break;
- case SEG_TYPE_DYNMEM:
- return "dynmem";
- break;
-#ifdef ENABLE_SCI32
- case SEG_TYPE_ARRAY:
- return "array";
- break;
- case SEG_TYPE_STRING:
- return "string";
- break;
-#endif
- default:
- error("Unknown SegmentObj type %d", type);
- break;
- }
- return NULL;
-}
-
SegmentRef SegmentObj::dereference(reg_t pointer) {
error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
PRINT_REG(pointer));
return SegmentRef();
}
-
-bool LocalVariables::isValidOffset(uint16 offset) const {
- return offset < _locals.size() * 2;
-}
-
-SegmentRef LocalVariables::dereference(reg_t pointer) {
- SegmentRef ret;
- ret.isRaw = false; // reg_t based data!
- ret.maxSize = (_locals.size() - pointer.offset / 2) * 2;
-
- if (pointer.offset & 1) {
- ret.maxSize -= 1;
- ret.skipByte = true;
- }
-
- if (ret.maxSize > 0) {
- ret.reg = &_locals[pointer.offset / 2];
- } else {
- if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660)
- && g_sci->getGameId() == GID_LAURABOW2) {
- // Happens in two places during the intro of LB2CD, both from kMemory(peek):
- // - room 160: Heap 160 has 83 local variables (0-82), and the game
- // asks for variables at indices 83 - 90 too.
- // - room 220: Heap 220 has 114 local variables (0-113), and the
- // game asks for variables at indices 114-120 too.
- } else {
- error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer));
- }
- ret.reg = 0;
- }
- return ret;
-}
-
-bool DataStack::isValidOffset(uint16 offset) const {
- return offset < _capacity * 2;
-}
-
-SegmentRef DataStack::dereference(reg_t pointer) {
- SegmentRef ret;
- ret.isRaw = false; // reg_t based data!
- ret.maxSize = (_capacity - pointer.offset / 2) * 2;
-
- if (pointer.offset & 1) {
- ret.maxSize -= 1;
- ret.skipByte = true;
- }
-
- ret.reg = &_entries[pointer.offset / 2];
- return ret;
-}
-
-bool DynMem::isValidOffset(uint16 offset) const {
- return offset < _size;
-}
-
-SegmentRef DynMem::dereference(reg_t pointer) {
- SegmentRef ret;
- ret.isRaw = true;
- ret.maxSize = _size - pointer.offset;
- ret.raw = _buf + pointer.offset;
- return ret;
-}
-
//-------------------- clones --------------------
Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const {
@@ -220,8 +115,6 @@ Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const {
void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
#ifdef GC_DEBUG
- // assert(addr.segment == _segId);
-
Object *victim_obj = &(_table[addr.offset]);
if (!(victim_obj->_flags & OBJECT_FLAG_FREED))
@@ -229,30 +122,54 @@ void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
#ifdef GC_DEBUG_VERBOSE
else
warning("[GC-DEBUG] Clone %04x:%04x: Freeing", PRINT_REG(addr));
+
+ warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos));
#endif
#endif
- /*
- warning("[GC] Clone %04x:%04x: Freeing", PRINT_REG(addr));
- warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos));
- */
+
freeEntry(addr.offset);
}
//-------------------- locals --------------------
+
+SegmentRef LocalVariables::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = false; // reg_t based data!
+ ret.maxSize = (_locals.size() - pointer.offset / 2) * 2;
+
+ if (pointer.offset & 1) {
+ ret.maxSize -= 1;
+ ret.skipByte = true;
+ }
+
+ if (ret.maxSize > 0) {
+ ret.reg = &_locals[pointer.offset / 2];
+ } else {
+ if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660)
+ && g_sci->getGameId() == GID_LAURABOW2) {
+ // Happens in two places during the intro of LB2CD, both from kMemory(peek):
+ // - room 160: Heap 160 has 83 local variables (0-82), and the game
+ // asks for variables at indices 83 - 90 too.
+ // - room 220: Heap 220 has 114 local variables (0-113), and the
+ // game asks for variables at indices 114-120 too.
+ } else {
+ error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer));
+ }
+ ret.reg = 0;
+ }
+ return ret;
+}
+
reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const {
// Reference the owning script
SegmentId owner_seg = segMan->getScriptSegment(script_id);
-
assert(owner_seg > 0);
-
return make_reg(owner_seg, 0);
}
Common::Array<reg_t> LocalVariables::listAllOutgoingReferences(reg_t addr) const {
Common::Array<reg_t> tmp;
-// assert(addr.segment == _segId);
-
for (uint i = 0; i < _locals.size(); i++)
tmp.push_back(_locals[i]);
@@ -261,9 +178,19 @@ Common::Array<reg_t> LocalVariables::listAllOutgoingReferences(reg_t addr) const
//-------------------- stack --------------------
-reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const {
- addr.offset = 0;
- return addr;
+
+SegmentRef DataStack::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = false; // reg_t based data!
+ ret.maxSize = (_capacity - pointer.offset / 2) * 2;
+
+ if (pointer.offset & 1) {
+ ret.maxSize -= 1;
+ ret.skipByte = true;
+ }
+
+ ret.reg = &_entries[pointer.offset / 2];
+ return ret;
}
Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const {
@@ -274,11 +201,7 @@ Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const {
return tmp;
}
-
//-------------------- lists --------------------
-void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
Common::Array<reg_t> ListTable::listAllOutgoingReferences(reg_t addr) const {
Common::Array<reg_t> tmp;
@@ -296,11 +219,7 @@ Common::Array<reg_t> ListTable::listAllOutgoingReferences(reg_t addr) const {
return tmp;
}
-
//-------------------- nodes --------------------
-void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
Common::Array<reg_t> NodeTable::listAllOutgoingReferences(reg_t addr) const {
Common::Array<reg_t> tmp;
@@ -321,14 +240,12 @@ Common::Array<reg_t> NodeTable::listAllOutgoingReferences(reg_t addr) const {
//-------------------- dynamic memory --------------------
-reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const {
- addr.offset = 0;
- return addr;
-}
-
-Common::Array<reg_t> DynMem::listAllDeallocatable(SegmentId segId) const {
- const reg_t r = make_reg(segId, 0);
- return Common::Array<reg_t>(&r, 1);
+SegmentRef DynMem::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = _size - pointer.offset;
+ ret.raw = _buf + pointer.offset;
+ return ret;
}
#ifdef ENABLE_SCI32
@@ -393,11 +310,6 @@ SegmentRef StringTable::dereference(reg_t pointer) {
return ret;
}
-void StringTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- _table[sub_addr.offset].destroy();
- freeEntry(sub_addr.offset);
-}
-
#endif
} // End of namespace Sci
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 9aaa3a4b08..947953e8c3 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -84,7 +84,6 @@ struct SegmentObj : public Common::Serializable {
public:
static SegmentObj *createSegmentObj(SegmentType type);
- static const char *getSegmentTypeName(SegmentType type);
public:
SegmentObj(SegmentType type) : _type(type) {}
@@ -150,11 +149,11 @@ struct LocalVariables : public SegmentObj {
Common::Array<reg_t> _locals;
public:
- LocalVariables(): SegmentObj(SEG_TYPE_LOCALS) {
- script_id = 0;
- }
+ LocalVariables(): SegmentObj(SEG_TYPE_LOCALS), script_id(0) { }
- virtual bool isValidOffset(uint16 offset) const;
+ virtual bool isValidOffset(uint16 offset) const {
+ return offset < _locals.size() * 2;
+ }
virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
@@ -168,18 +167,19 @@ struct DataStack : SegmentObj {
reg_t *_entries;
public:
- DataStack() : SegmentObj(SEG_TYPE_STACK) {
- _capacity = 0;
- _entries = NULL;
- }
+ DataStack() : SegmentObj(SEG_TYPE_STACK), _capacity(0), _entries(NULL) { }
~DataStack() {
free(_entries);
_entries = NULL;
}
- virtual bool isValidOffset(uint16 offset) const;
+ virtual bool isValidOffset(uint16 offset) const {
+ return offset < _capacity * 2;
+ }
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const {
+ return make_reg(addr.segment, 0);
+ }
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -211,7 +211,7 @@ struct Hunk {
};
template<typename T>
-struct Table : public SegmentObj {
+struct SegmentObjTable : public SegmentObj {
typedef T value_type;
struct Entry : public T {
int next_free; /* Only used for free entries */
@@ -225,7 +225,7 @@ struct Table : public SegmentObj {
Common::Array<Entry> _table;
public:
- Table(SegmentType type) : SegmentObj(type) {
+ SegmentObjTable(SegmentType type) : SegmentObj(type) {
initTable();
}
@@ -279,8 +279,8 @@ public:
/* CloneTable */
-struct CloneTable : public Table<Clone> {
- CloneTable() : Table<Clone>(SEG_TYPE_CLONES) {}
+struct CloneTable : public SegmentObjTable<Clone> {
+ CloneTable() : SegmentObjTable<Clone>(SEG_TYPE_CLONES) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
@@ -290,10 +290,12 @@ struct CloneTable : public Table<Clone> {
/* NodeTable */
-struct NodeTable : public Table<Node> {
- NodeTable() : Table<Node>(SEG_TYPE_NODES) {}
+struct NodeTable : public SegmentObjTable<Node> {
+ NodeTable() : SegmentObjTable<Node>(SEG_TYPE_NODES) {}
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+ }
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -301,10 +303,12 @@ struct NodeTable : public Table<Node> {
/* ListTable */
-struct ListTable : public Table<List> {
- ListTable() : Table<List>(SEG_TYPE_LISTS) {}
+struct ListTable : public SegmentObjTable<List> {
+ ListTable() : SegmentObjTable<List>(SEG_TYPE_LISTS) {}
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+ }
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -312,18 +316,29 @@ struct ListTable : public Table<List> {
/* HunkTable */
-struct HunkTable : public Table<Hunk> {
- HunkTable() : Table<Hunk>(SEG_TYPE_HUNK) {}
-
- virtual void freeEntry(int idx) {
- Table<Hunk>::freeEntry(idx);
+struct HunkTable : public SegmentObjTable<Hunk> {
+ HunkTable() : SegmentObjTable<Hunk>(SEG_TYPE_HUNK) {}
+ virtual ~HunkTable() {
+ for (uint i = 0; i < _table.size(); i++) {
+ if (isValidEntry(i))
+ freeEntryContents(i);
+ }
+ }
- if (!_table[idx].mem)
- warning("Attempt to free an already freed hunk");
+ void freeEntryContents(int idx) {
free(_table[idx].mem);
_table[idx].mem = 0;
}
+ virtual void freeEntry(int idx) {
+ SegmentObjTable<Hunk>::freeEntry(idx);
+ freeEntryContents(idx);
+ }
+
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+ }
+
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -341,10 +356,17 @@ public:
_buf = NULL;
}
- virtual bool isValidOffset(uint16 offset) const;
+ virtual bool isValidOffset(uint16 offset) const {
+ return offset < _size;
+ }
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
- virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const;
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const {
+ return make_reg(addr.segment, 0);
+ }
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const {
+ const reg_t r = make_reg(segId, 0);
+ return Common::Array<reg_t>(&r, 1);
+ }
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -354,12 +376,7 @@ public:
template <typename T>
class SciArray {
public:
- SciArray() {
- _type = -1;
- _data = NULL;
- _size = 0;
- _actualSize = 0;
- }
+ SciArray() : _type(-1), _data(NULL), _size(0), _actualSize(0) { }
SciArray(const SciArray<T> &array) {
_type = array._type;
@@ -474,8 +491,8 @@ public:
void fromString(const Common::String &string);
};
-struct ArrayTable : public Table<SciArray<reg_t> > {
- ArrayTable() : Table<SciArray<reg_t> >(SEG_TYPE_ARRAY) {}
+struct ArrayTable : public SegmentObjTable<SciArray<reg_t> > {
+ ArrayTable() : SegmentObjTable<SciArray<reg_t> >(SEG_TYPE_ARRAY) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
@@ -484,10 +501,13 @@ struct ArrayTable : public Table<SciArray<reg_t> > {
SegmentRef dereference(reg_t pointer);
};
-struct StringTable : public Table<SciString> {
- StringTable() : Table<SciString>(SEG_TYPE_STRING) {}
+struct StringTable : public SegmentObjTable<SciString> {
+ StringTable() : SegmentObjTable<SciString>(SEG_TYPE_STRING) {}
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ _table[sub_addr.offset].destroy();
+ freeEntry(sub_addr.offset);
+ }
void saveLoadWithSerializer(Common::Serializer &ser);
SegmentRef dereference(reg_t pointer);
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index 798dbf529c..957a836e3e 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -165,6 +165,7 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(vanishingX);
FIND_SELECTOR(vanishingY);
FIND_SELECTOR(iconIndex);
+ FIND_SELECTOR(select);
#ifdef ENABLE_SCI32
FIND_SELECTOR(data);
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index 6038ad0c36..8a47984204 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -130,6 +130,7 @@ struct SelectorCache {
// SCI1.1 Mac icon bar selectors
Selector iconIndex; ///< Used to index icon bar objects
+ Selector select;
#ifdef ENABLE_SCI32
Selector data; // Used by Array()/String()
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 12795adeb1..f9d6c70389 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -94,10 +94,9 @@ void EngineState::reset(bool isRestoring) {
stack_base = 0;
stack_top = 0;
- restAdjust = 0;
-
r_acc = NULL_REG;
r_prev = NULL_REG;
+ r_rest = 0;
lastWaitTime = 0;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index bba34b6b48..d91118ec1e 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -79,10 +79,6 @@ private:
};
enum {
- MAX_SAVE_DIR_SIZE = MAXPATHLEN
-};
-
-enum {
MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */
};
@@ -187,9 +183,10 @@ public:
int executionStackBase;
bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */
+ // Registers
reg_t r_acc; /**< Accumulator */
- int16 restAdjust; /**< current &rest register */
reg_t r_prev; /**< previous comparison result */
+ int16 r_rest; /**< current &rest register */
StackPtr stack_base; /**< Pointer to the least stack element */
StackPtr stack_top; /**< First invalid stack element */
@@ -230,7 +227,7 @@ public:
enum {
kMemorySegmentMax = 256
};
- uint _memorySegmentSize;
+ uint16 _memorySegmentSize;
byte _memorySegment[kMemorySegmentMax];
VideoState _videoState;
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 4bb61a0658..23241de330 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -28,6 +28,7 @@
#include "sci/engine/kernel.h"
#include "sci/engine/seg_manager.h"
+#include "sci/engine/vm.h"
namespace Sci {
@@ -118,6 +119,33 @@ static const SelectorRemap sciSelectorRemap[] = {
{ SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 }
};
+struct ClassReference {
+ int script;
+ const char *className;
+ const char *selectorName;
+ SelectorType selectorType;
+ uint selectorOffset;
+};
+
+// For variable selectors, we ignore the global selectors and start off from
+// the object's selectors (i.e. from the name selector onwards). Thus, the
+// following are not taken into consideration when calculating the indices of
+// variable selectors in this array:
+// SCI0 - SCI1: species, superClass, -info-
+// SCI1.1: -objID-, -size-, -propDict-, -methDict-, -classScript-, -script-,
+// -super-, -info-
+static const ClassReference classReferences[] = {
+ { 0, "Character", "say", kSelectorMethod, 5 }, // Crazy Nick's Soft Picks
+ { 928, "Narrator", "say", kSelectorMethod, 4 },
+ { 928, "Narrator", "startText", kSelectorMethod, 5 },
+ { 929, "Sync", "syncTime", kSelectorVariable, 1 },
+ { 929, "Sync", "syncCue", kSelectorVariable, 2 },
+ { 981, "SysWindow", "open", kSelectorMethod, 1 },
+ { 999, "Script", "init", kSelectorMethod, 0 },
+ { 999, "Script", "dispose", kSelectorMethod, 2 },
+ { 999, "Script", "changeState", kSelectorMethod, 3 }
+};
+
Common::StringArray Kernel::checkStaticSelectorNames() {
Common::StringArray names;
const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;
@@ -158,133 +186,115 @@ Common::StringArray Kernel::checkStaticSelectorNames() {
names[i] = sci11Selectors[i - count - countSci1];
}
- // Now, we need to find out selectors which keep changing place...
- // We do that by dissecting game objects, and looking for selectors at
- // specified locations.
+ findSpecificSelectors(names);
- // We need to initialize script 0 here, to make sure that it's always
- // located at segment 1.
- _segMan->instantiateScript(0);
-
- // The Actor class contains the init, xLast and yLast selectors, which
- // we reference directly. It's always in script 998, so we need to
- // explicitly load it here.
- if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) {
- _segMan->instantiateScript(998);
-
- const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
-
- if (actorClass) {
- // The init selector is always the first function
- int initSelectorPos = actorClass->getFuncSelector(0);
+#ifdef ENABLE_SCI32
+ } else {
+ // SCI2+
+ for (int i = 0; i < count; i++)
+ names[i] = sci2Selectors[i];
+#endif
+ }
- if (names.size() < (uint32)initSelectorPos + 2)
- names.resize((uint32)initSelectorPos + 2);
+ for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
+ if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
+ const uint32 slot = selectorRemap->slot;
+ if (slot >= names.size())
+ names.resize(slot + 1);
+ names[slot] = selectorRemap->name;
+ }
+ }
- names[initSelectorPos] = "init";
- // dispose comes right after init
- names[initSelectorPos + 1] = "dispose";
+ return names;
+}
- if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
- // Find the xLast and yLast selectors, used in kDoBresen
+void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) {
+ // Now, we need to find out selectors which keep changing place...
+ // We do that by dissecting game objects, and looking for selectors at
+ // specified locations.
- // xLast and yLast always come between illegalBits and xStep
- int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset); // illegalBits
- int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset); // xStep
- if (xStepSelectorPos - illegalBitsSelectorPos != 3) {
- error("illegalBits and xStep selectors aren't found in "
- "known locations. illegalBits = %d, xStep = %d",
- illegalBitsSelectorPos, xStepSelectorPos);
- }
+ // We need to initialize script 0 here, to make sure that it's always
+ // located at segment 1.
+ _segMan->instantiateScript(0);
- int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1);
- int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2);
+ // The Actor class contains the init, xLast and yLast selectors, which
+ // we reference directly. It's always in script 998, so we need to
+ // explicitly load it here.
+ if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) {
+ if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) {
+ _segMan->instantiateScript(998);
- if (names.size() < (uint32)yLastSelectorPos + 1)
- names.resize((uint32)yLastSelectorPos + 1);
+ const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
- names[xLastSelectorPos] = "xLast";
- names[yLastSelectorPos] = "yLast";
- } // if ((getSciVersion() >= SCI_VERSION_1_EGA))
+ if (actorClass) {
+ // Find the xLast and yLast selectors, used in kDoBresen
+
+ const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;
+ // xLast and yLast always come between illegalBits and xStep
+ int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset); // illegalBits
+ int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset); // xStep
+ if (xStepSelectorPos - illegalBitsSelectorPos != 3) {
+ error("illegalBits and xStep selectors aren't found in "
+ "known locations. illegalBits = %d, xStep = %d",
+ illegalBitsSelectorPos, xStepSelectorPos);
+ }
+
+ int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1);
+ int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2);
+
+ if (selectorNames.size() < (uint32)yLastSelectorPos + 1)
+ selectorNames.resize((uint32)yLastSelectorPos + 1);
+
+ selectorNames[xLastSelectorPos] = "xLast";
+ selectorNames[yLastSelectorPos] = "yLast";
} // if (actorClass)
_segMan->uninstantiateScript(998);
} // if (_resMan->testResource(ResourceId(kResourceTypeScript, 998)))
+ } // if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY))
+
+ // Find selectors from specific classes
+
+ for (int i = 0; i < ARRAYSIZE(classReferences); i++) {
+ if (!_resMan->testResource(ResourceId(kResourceTypeScript, classReferences[i].script)))
+ continue;
- if (_resMan->testResource(ResourceId(kResourceTypeScript, 981))) {
- // The SysWindow class contains the open selectors, which we
- // reference directly. It's always in script 981, so we need to
- // explicitly load it here
- _segMan->instantiateScript(981);
+ _segMan->instantiateScript(classReferences[i].script);
- const Object *sysWindowClass = _segMan->getObject(_segMan->findObjectByName("SysWindow"));
+ const Object *targetClass = _segMan->getObject(_segMan->findObjectByName(classReferences[i].className));
+ int targetSelectorPos = 0;
+ uint selectorOffset = classReferences[i].selectorOffset;
- if (sysWindowClass) {
- if (sysWindowClass->getMethodCount() < 2)
- error("The SysWindow class has less than 2 methods");
+ if (targetClass) {
+ if (classReferences[i].selectorType == kSelectorMethod) {
+ if (targetClass->getMethodCount() < selectorOffset + 1)
+ error("The %s class has less than %d methods (%d)",
+ classReferences[i].className, selectorOffset + 1,
+ targetClass->getMethodCount());
- // The open selector is always the second function
- int openSelectorPos = sysWindowClass->getFuncSelector(1);
+ targetSelectorPos = targetClass->getFuncSelector(selectorOffset);
+ } else {
+ // Add the global selectors to the selector ID
+ selectorOffset += (getSciVersion() <= SCI_VERSION_1_LATE) ? 3 : 8;
- if (names.size() < (uint32)openSelectorPos + 1)
- names.resize((uint32)openSelectorPos + 1);
+ if (targetClass->getVarCount() < selectorOffset + 1)
+ error("The %s class has less than %d variables (%d)",
+ classReferences[i].className, selectorOffset + 1,
+ targetClass->getVarCount());
- names[openSelectorPos] = "open";
+ targetSelectorPos = targetClass->getVarSelector(selectorOffset);
}
- _segMan->uninstantiateScript(981);
- } // if (_resMan->testResource(ResourceId(kResourceTypeScript, 981)))
-
- if (g_sci->getGameId() == GID_HOYLE4) {
- // The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary.
- // This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each
- // game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need
- // to set these two selectors, but we need for Hoyle...
- if (names.size() < 276)
- names.resize(276);
-
- names[274] = "syncTime";
- names[275] = "syncCue";
- } else if (g_sci->getGameId() == GID_PEPPER) {
- // Same as above for the non-interactive demo of Pepper
- if (names.size() < 539)
- names.resize(539);
-
- names[263] = "syncTime";
- names[264] = "syncCue";
- names[538] = "startText";
- } else if (g_sci->getGameId() == GID_LAURABOW2) {
- // The floppy of version needs the changeState selector set to match up with the
- // CD version's workarounds.
- if (names.size() < 251)
- names.resize(251);
-
- names[144] = "changeState";
- } else if (g_sci->getGameId() == GID_CNICK_KQ) {
- if (names.size() < 447)
- names.resize(447);
-
- names[446] = "say";
- }
+ if (selectorNames.size() < (uint32)targetSelectorPos + 1)
+ selectorNames.resize((uint32)targetSelectorPos + 1);
-#ifdef ENABLE_SCI32
- } else {
- // SCI2+
- for (int i = 0; i < count; i++)
- names[i] = sci2Selectors[i];
-#endif
- }
- for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
- if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
- const uint32 slot = selectorRemap->slot;
- if (slot >= names.size())
- names.resize(slot + 1);
- names[slot] = selectorRemap->name;
+ selectorNames[targetSelectorPos] = classReferences[i].selectorName;
}
}
- return names;
+ // Reset the segment manager
+ _segMan->resetSegMan();
}
} // End of namespace Sci
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 6d11a1ad8a..d209a0ca5b 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -47,51 +47,10 @@ const reg_t NULL_REG = {0, 0};
const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
const reg_t TRUE_REG = {0, 1};
//#define VM_DEBUG_SEND
-
-#define SCI_XS_CALLEE_LOCALS ((SegmentId)-1)
-
-/**
- * Adds an entry to the top of the execution stack.
- *
- * @param[in] s The state with which to execute
- * @param[in] pc The initial program counter
- * @param[in] sp The initial stack pointer
- * @param[in] objp Pointer to the beginning of the current object
- * @param[in] argc Number of parameters to call with
- * @param[in] argp Heap pointer to the first parameter
- * @param[in] selector The selector by which it was called or
- * NULL_SELECTOR if n.a. For debugging.
- * @param[in] exportId The exportId by which it was called or
- * -1 if n.a. For debugging.
- * @param[in] sendp Pointer to the object which the message was
- * sent to. Equal to objp for anything but super.
- * @param[in] origin Number of the execution stack element this
- * entry was created by (usually the current TOS
- * number, except for multiple sends).
- * @param[in] local_segment The segment to use for local variables,
- * or SCI_XS_CALLEE_LOCALS to use obj's segment.
- * @return A pointer to the new exec stack TOS entry
- */
-static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp,
- reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset,
- reg_t sendp, int origin, SegmentId local_segment);
-
-/**
- * Adds one varselector access to the execution stack.
- * This function is called from send_selector only.
- * @param[in] s The EngineState to use
- * @param[in] objp Pointer to the object owning the selector
- * @param[in] argc 1 for writing, 0 for reading
- * @param[in] argp Pointer to the address of the data to write -2
- * @param[in] selector Selector name
- * @param[in] address Heap address of the selector
- * @param[in] origin Stack frame which the access originated from
- * @return Pointer to the new exec-TOS element
- */
-static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc,
- StackPtr argp, Selector selector, const ObjVarRef& address,
- int origin);
-
+// Enable the define below to have the VM abort on cases where a conditional
+// statement is followed by an unconditional jump (which will most likely lead
+// to an infinite loop). Aids in detecting script bugs such as #3040722.
+//#define ABORT_ON_INFINITE_LOOP
// validation functionality
@@ -114,8 +73,8 @@ static reg_t &validate_property(EngineState *s, Object *obj, int index) {
if (index < 0 || (uint)index >= obj->getVarCount()) {
// This is same way sierra does it and there are some games, that contain such scripts like
// iceman script 998 (fred::canBeHere, executed right at the start)
- debugC(kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!",
- index, obj->getVarCount());
+ debugC(kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested from object %04x:%04x (%s)",
+ index, obj->getVarCount(), PRINT_REG(obj->getPos()), s->_segMan->getObjectName(obj->getPos()));
return dummyReg;
}
@@ -125,25 +84,9 @@ static reg_t &validate_property(EngineState *s, Object *obj, int index) {
static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
if (sp >= s->stack_base && sp < s->stack_top)
return sp;
-
+ else
error("[VM] Stack index %d out of valid range [%d..%d]",
(int)(sp - s->stack_base), 0, (int)(s->stack_top - s->stack_base - 1));
- return 0;
-}
-
-static int validate_arithmetic(reg_t reg) {
- if (reg.segment) {
- // The results of this are likely unpredictable... It most likely means that a kernel function is returning something wrong.
- // If such an error occurs, we usually need to find the last kernel function called and check its return value.
- error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg));
- return 0;
- }
-
- return reg.offset;
-}
-
-static int signed_validate_arithmetic(reg_t reg) {
- return (int16)validate_arithmetic(reg);
}
static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index) {
@@ -176,37 +119,11 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in
return true;
}
-static bool validate_unsignedInteger(reg_t reg, uint16 &integer) {
- if (reg.segment)
- return false;
- integer = reg.offset;
- return true;
-}
-
-static bool validate_signedInteger(reg_t reg, int16 &integer) {
- if (reg.segment)
- return false;
- integer = (int16)reg.offset;
- return true;
-}
-
extern const char *opcodeNames[]; // from scriptdebug.cpp
-static reg_t arithmetic_lookForWorkaround(const byte opcode, const SciWorkaroundEntry *workaroundList, reg_t value1, reg_t value2) {
- SciTrackOriginReply originReply;
- SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, workaroundList, &originReply);
- if (solution.type == WORKAROUND_NONE)
- error("%s on non-integer (%04x:%04x, %04x:%04x) from method %s::%s (script %d, room %d, localCall %x)",
- opcodeNames[opcode], PRINT_REG(value1), PRINT_REG(value2), originReply.objectName.c_str(),
- originReply.methodName.c_str(), originReply.scriptNr, g_sci->getEngineState()->currentRoomNumber(),
- originReply.localCallOffset);
- assert(solution.type == WORKAROUND_FAKE);
- return make_reg(0, solution.value);
-}
-
-static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) {
- if (validate_variable(r, stack_base, type, max, index)) {
- if (r[index].segment == 0xffff) {
+static reg_t read_var(EngineState *s, int type, int index) {
+ if (validate_variable(s->variables[type], s->stack_base, type, s->variablesMax[type], index)) {
+ if (s->variables[type][index].segment == 0xffff) {
switch (type) {
case VAR_TEMP: {
// Uninitialized read on a temp
@@ -220,7 +137,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr,
g_sci->getEngineState()->currentRoomNumber(), originReply.localCallOffset);
- r[index] = NULL_REG;
+ s->variables[type][index] = NULL_REG;
break;
#else
error("Uninitialized read for temp %d from method %s::%s (script %d, room %d, localCall %x)",
@@ -229,7 +146,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
#endif
}
assert(solution.type == WORKAROUND_FAKE);
- r[index] = make_reg(0, solution.value);
+ s->variables[type][index] = make_reg(0, solution.value);
break;
}
case VAR_PARAM:
@@ -241,13 +158,13 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
break;
}
}
- return r[index];
+ return s->variables[type][index];
} else
- return default_value;
+ return s->r_acc;
}
-static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t value, SegManager *segMan, Kernel *kernel) {
- if (validate_variable(r, stack_base, type, max, index)) {
+static void write_var(EngineState *s, int type, int index, reg_t value) {
+ if (validate_variable(s->variables[type], s->stack_base, type, s->variablesMax[type], index)) {
// WORKAROUND: This code is needed to work around a probable script bug, or a
// limitation of the original SCI engine, which can be observed in LSL5.
@@ -267,12 +184,12 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
// done, ego's movement will not be updated properly, so the result is
// unpredictable (for example in LSL5, Patti spins around instead of walking).
if (index == 0 && type == VAR_GLOBAL && getSciVersion() > SCI_VERSION_0_EARLY) { // global 0 is ego
- reg_t stopGroopPos = segMan->findObjectByName("stopGroop");
+ reg_t stopGroopPos = s->_segMan->findObjectByName("stopGroop");
if (!stopGroopPos.isNull()) { // does the game have a stopGroop object?
// Find the "client" member variable of the stopGroop object, and update it
ObjVarRef varp;
- if (lookupSelector(segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) {
- reg_t *clientVar = varp.getPointer(segMan);
+ if (lookupSelector(s->_segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) {
+ reg_t *clientVar = varp.getPointer(s->_segMan);
*clientVar = value;
}
}
@@ -285,7 +202,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
if (type == VAR_TEMP && value.segment == 0xffff)
value.segment = 0;
- r[index] = value;
+ s->variables[type][index] = value;
// If the game is trying to change its speech/subtitle settings, apply the ScummVM audio
// options first, if they haven't been applied yet
@@ -296,10 +213,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
}
}
-#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, s->r_acc)
-#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, value, s->_segMan, g_sci->getKernel())
-#define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value));
-
// Operating on the stack
// 16 bit:
#define PUSH(v) PUSH32(make_reg(0, v))
@@ -307,26 +220,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
#define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a))
#define POP32() (*(validate_stack_addr(s, --(s->xs->sp))))
-bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
- if (_debugState._activeBreakpointTypes & BREAK_EXPORT) {
- uint32 bpaddress;
-
- bpaddress = (script << 16 | pubfunct);
-
- Common::List<Breakpoint>::const_iterator bp;
- for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
- if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
- _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
- return true;
- }
- }
- }
-
- return false;
-}
-
ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) {
int seg = s->_segMan->getScriptSegment(script);
Script *scr = s->_segMan->getScriptIfLoaded(seg);
@@ -356,10 +249,13 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
// Check if a breakpoint is set on this method
g_sci->checkExportBreakpoint(script, pubfunct);
- return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg);
+ ExecStack xstack(calling_obj, calling_obj, sp, argc, argp,
+ seg, make_reg(seg, temp), -1, pubfunct, -1,
+ s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL);
+ s->_executionStack.push_back(xstack);
+ return &(s->_executionStack.back());
}
-
static void _exec_varselectors(EngineState *s) {
// Executes all varselector read/write ops on the TOS
while (!s->_executionStack.empty() && s->_executionStack.back().type == EXEC_STACK_TYPE_VARSELECTOR) {
@@ -379,344 +275,82 @@ static void _exec_varselectors(EngineState *s) {
}
}
-/** This struct is used to buffer the list of send calls in send_selector() */
-struct CallsStruct {
- reg_t addr_func;
- reg_t varp_objp;
- union {
- reg_t func;
- ObjVarRef var;
- } address;
- StackPtr argp;
- int argc;
- Selector selector;
- StackPtr sp; /**< Stack pointer */
- int type; /**< Same as ExecStack.type */
-};
-
-bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) {
- Common::String methodName = _gamestate->_segMan->getObjectName(send_obj);
- methodName += ("::" + getKernel()->getSelectorName(selector));
-
- Common::List<Breakpoint>::const_iterator bpIter;
- for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) {
- if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) {
- _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj));
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
- return true;
- }
- }
- return false;
-}
+// from scriptdebug.cpp
+extern void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType);
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) {
-// send_obj and work_obj are equal for anything but 'super'
-// Returns a pointer to the TOS exec_stack element
+ // send_obj and work_obj are equal for anything but 'super'
+ // Returns a pointer to the TOS exec_stack element
assert(s);
reg_t funcp;
- int selector;
+ Selector selector;
int argc;
- int origin = s->_executionStack.size()-1; // Origin: Used for debugging
- // We return a pointer to the new active ExecStack
-
- // The selector calls we catch are stored below:
- Common::Stack<CallsStruct> sendCalls;
-
+ int origin = s->_executionStack.size() - 1; // Origin: Used for debugging
int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes;
+ ObjVarRef varp;
+
+ Common::List<ExecStack>::iterator prevElementIterator = s->_executionStack.end();
while (framesize > 0) {
- selector = validate_arithmetic(*argp++);
- argc = validate_arithmetic(*argp);
+ selector = argp->requireUint16();
+ argp++;
+ argc = argp->requireUint16();
- if (argc > 0x800) { // More arguments than the stack could possibly accomodate for
+ if (argc > 0x800) // More arguments than the stack could possibly accomodate for
error("send_selector(): More than 0x800 arguments to function call");
- }
-
-#ifdef VM_DEBUG_SEND
- debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),
- s->_segMan->getObjectName(send_obj), selector,
- g_sci->getKernel()->getSelectorName(selector).c_str());
-#endif // VM_DEBUG_SEND
- ObjVarRef varp;
- switch (lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp)) {
- case kSelectorNone:
+ SelectorType selectorType = lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp);
+ if (selectorType == kSelectorNone)
error("Send to invalid selector 0x%x of object at %04x:%04x", 0xffff & selector, PRINT_REG(send_obj));
- break;
-
- case kSelectorVariable:
-#ifdef VM_DEBUG_SEND
- if (argc)
- debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1]));
- else
- debugN("Varselector: Read\n");
-#endif // VM_DEBUG_SEND
-
- // argc == 0: read selector
- // argc != 0: write selector
- if (!argc) {
- // read selector
- if (activeBreakpointTypes & BREAK_SELECTORREAD) {
- if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector))
- debug("[read selector]\n");
- }
- } else {
- // write selector
- if (activeBreakpointTypes & BREAK_SELECTORWRITE) {
- if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) {
- reg_t oldReg = *varp.getPointer(s->_segMan);
- reg_t newReg = argp[1];
- warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",
- s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),
- PRINT_REG(oldReg), PRINT_REG(newReg));
- }
- }
- }
-
- if (argc > 1) {
- // argc can indeed be bigger than 1 in some cases, and it's usually the
- // result of a script bug. Usually these aren't fatal.
-
- const char *objectName = s->_segMan->getObjectName(send_obj);
-
- reg_t oldReg = *varp.getPointer(s->_segMan);
- reg_t newReg = argp[1];
- const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str();
- debug(2, "send_selector(): argc = %d while modifying variable selector "
- "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x",
- argc, selector, selectorName, PRINT_REG(send_obj),
- objectName, PRINT_REG(oldReg), PRINT_REG(newReg));
- }
+ ExecStackType stackType = EXEC_STACK_TYPE_VARSELECTOR;
+ StackPtr curSP = NULL;
+ reg_t curFP = NULL_REG;
+ if (selectorType == kSelectorMethod) {
+ stackType = EXEC_STACK_TYPE_CALL;
+ curSP = sp;
+ curFP = funcp;
+ sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over
+ }
- {
- CallsStruct call;
- call.address.var = varp; // register the call
- call.argp = argp;
- call.argc = argc;
- call.selector = selector;
- call.type = EXEC_STACK_TYPE_VARSELECTOR; // Register as a varselector
- sendCalls.push(call);
- }
+ if (activeBreakpointTypes || DebugMan.isDebugChannelEnabled(kDebugLevelScripts))
+ debugSelectorCall(send_obj, selector, argc, argp, varp, funcp, s->_segMan, selectorType);
- break;
+ ExecStack xstack(work_obj, send_obj, curSP, argc, argp,
+ 0xFFFF, curFP, selector, -1, -1,
+ origin, stackType);
- case kSelectorMethod:
-
-#ifndef VM_DEBUG_SEND
- if (activeBreakpointTypes & BREAK_SELECTOREXEC) {
- if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) {
- debugN("[execute selector]");
-
- int displaySize = 0;
- for (int argNr = 1; argNr <= argc; argNr++) {
- if (argNr == 1)
- debugN(" - ");
- reg_t curParam = argp[argNr];
- if (curParam.segment) {
- debugN("[%04x:%04x] ", PRINT_REG(curParam));
- displaySize += 12;
- } else {
- debugN("[%04x] ", curParam.offset);
- displaySize += 7;
- }
- if (displaySize > 50) {
- if (argNr < argc)
- debugN("...");
- break;
- }
- }
- debugN("\n");
- }
- }
-#else // VM_DEBUG_SEND
- if (activeBreakpointTypes & BREAK_SELECTOREXEC)
- g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector);
- debugN("Funcselector(");
- for (int i = 0; i < argc; i++) {
- debugN("%04x:%04x", PRINT_REG(argp[i+1]));
- if (i + 1 < argc)
- debugN(", ");
- }
- debugN(") at %04x:%04x\n", PRINT_REG(funcp));
-#endif // VM_DEBUG_SEND
-
- {
- CallsStruct call;
- call.address.func = funcp; // register call
- call.argp = argp;
- call.argc = argc;
- call.selector = selector;
- call.type = EXEC_STACK_TYPE_CALL;
- call.sp = sp;
- sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over
- sendCalls.push(call);
- }
+ if (selectorType == kSelectorVariable)
+ xstack.addr.varp = varp;
- break;
- } // switch (lookupSelector())
+ // The new stack entries should be put on the stack in reverse order
+ // so that the first one is executed first
+ s->_executionStack.insert(prevElementIterator, xstack);
+ // Decrement the stack end pointer so that it points to our recently
+ // added element, so that the next insert() places it before this one.
+ --prevElementIterator;
framesize -= (2 + argc);
argp += argc + 1;
- }
-
- // Iterate over all registered calls in the reverse order. This way, the first call is
- // placed on the TOS; as soon as it returns, it will cause the second call to be executed.
- while (!sendCalls.empty()) {
- CallsStruct call = sendCalls.pop();
- if (call.type == EXEC_STACK_TYPE_VARSELECTOR) // Write/read variable?
- add_exec_stack_varselector(s->_executionStack, work_obj, call.argc, call.argp,
- call.selector, call.address.var, origin);
- else
- add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj,
- call.argc, call.argp,
- call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS);
- }
+ } // while (framesize > 0)
_exec_varselectors(s);
return s->_executionStack.empty() ? NULL : &(s->_executionStack.back());
}
-static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) {
- ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS);
- // Store selector address in sp
-
- xstack->addr.varp = address;
- xstack->type = EXEC_STACK_TYPE_VARSELECTOR;
-
- return xstack;
-}
-
-static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc,
- StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) {
- // Returns new TOS element for the execution stack
- // _localsSegment may be -1 if derived from the called object
-
- //debug("Exec stack: [%d/%d], origin %d, at %p", s->execution_stack_pos, s->_executionStack.size(), origin, s->execution_stack);
-
- ExecStack xstack;
-
- xstack.objp = objp;
- if (_localsSegment != SCI_XS_CALLEE_LOCALS)
- xstack.local_segment = _localsSegment;
- else
- xstack.local_segment = pc.segment;
-
- xstack.sendp = sendp;
- xstack.addr.pc = pc;
- xstack.fp = xstack.sp = sp;
- xstack.argc = argc;
-
- xstack.variables_argp = argp; // Parameters
-
- *argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc
-
- // Additional debug information
- xstack.debugSelector = selector;
- xstack.debugExportId = exportId;
- xstack.debugLocalCallOffset = localCallOffset;
- xstack.debugOrigin = origin;
-
- xstack.type = EXEC_STACK_TYPE_CALL; // Normal call
-
- execStack.push_back(xstack);
- return &(execStack.back());
-}
-
-static reg_t pointer_add(EngineState *s, reg_t base, int offset) {
- SegmentObj *mobj = s->_segMan->getSegmentObj(base.segment);
-
- if (!mobj) {
- error("[VM] Error: Attempt to add %d to invalid pointer %04x:%04x", offset, PRINT_REG(base));
- return NULL_REG;
- }
-
- switch (mobj->getType()) {
-
- case SEG_TYPE_LOCALS:
- case SEG_TYPE_SCRIPT:
- case SEG_TYPE_STACK:
- case SEG_TYPE_DYNMEM:
- base.offset += offset;
- return base;
- default:
- // FIXME: Changed this to warning, because iceman does this during dancing with girl.
- // Investigate why that is so and either fix the underlying issue or implement a more
- // specialized workaround!
- warning("[VM] Error: Attempt to add %d to pointer %04x:%04x, type %d: Pointer arithmetics of this type unsupported", offset, PRINT_REG(base), mobj->getType());
- return NULL_REG;
-
- }
-}
-
static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, reg_t *argv) {
// Add stack frame to indicate we're executing a callk.
// This is useful in debugger backtraces if this
// kernel function calls a script itself.
- ExecStack *xstack;
- xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,
- s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
- xstack->debugSelector = kernelCallNr;
- xstack->type = EXEC_STACK_TYPE_KERNEL;
+ ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, NULL_REG,
+ kernelCallNr, -1, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_KERNEL);
+ s->_executionStack.push_back(xstack);
}
-static void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) {
- Kernel *kernel = g_sci->getKernel();
- if (!kernelSubCall) {
- debugN("k%s: ", kernelCall->name);
- } else {
- int callNameLen = strlen(kernelCall->name);
- if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) {
- const char *subCallName = kernelSubCall->name + callNameLen;
- debugN("k%s(%s): ", kernelCall->name, subCallName);
- } else {
- debugN("k%s(%s): ", kernelCall->name, kernelSubCall->name);
- }
- }
- for (int parmNr = 0; parmNr < argc; parmNr++) {
- if (parmNr)
- debugN(", ");
- uint16 regType = kernel->findRegType(argv[parmNr]);
- if (regType & SIG_TYPE_NULL)
- debugN("0");
- else if (regType & SIG_TYPE_UNINITIALIZED)
- debugN("UNINIT");
- else if (regType & SIG_IS_INVALID)
- debugN("INVALID");
- else if (regType & SIG_TYPE_INTEGER)
- debugN("%d", argv[parmNr].offset);
- else {
- debugN("%04x:%04x", PRINT_REG(argv[parmNr]));
- switch (regType) {
- case SIG_TYPE_OBJECT:
- debugN(" (%s)", s->_segMan->getObjectName(argv[parmNr]));
- break;
- case SIG_TYPE_REFERENCE:
- if (kernelCall->function == kSaid) {
- SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]);
- if (saidSpec.isRaw) {
- debugN(" ('");
- g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw);
- debugN("')");
- } else {
- debugN(" (non-raw said-spec)");
- }
- } else {
- debugN(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str());
- }
- default:
- break;
- }
- }
- }
- if (result.segment)
- debugN(" = %04x:%04x\n", PRINT_REG(result));
- else
- debugN(" = %d\n", result.offset);
-}
+// from scriptdebug.cpp
+extern void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result);
static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
Kernel *kernel = g_sci->getKernel();
@@ -767,15 +401,15 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
} else {
// Sub-functions available, check signature and call that one directly
if (argc < 1)
- error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr);
- if (argv[0].segment)
- error("[VM] k%s[%x]: given subfunction-id is actually a pointer", kernelCall.name, kernelCallNr);
+ error("[VM] k%s[%x]: no subfunction ID parameter given", kernelCall.name, kernelCallNr);
+ if (argv[0].isPointer())
+ error("[VM] k%s[%x]: given subfunction ID is actually a pointer", kernelCall.name, kernelCallNr);
const uint16 subId = argv[0].toUint16();
// Skip over subfunction-id
argc--;
argv++;
if (subId >= kernelCall.subFunctionCount)
- error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
+ error("[VM] k%s: subfunction ID %d requested, but not available", kernelCall.name, subId);
const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId];
if (kernelSubCall.signature && !kernel->signatureMatch(kernelSubCall.signature, argc, argv)) {
// Signature mismatch
@@ -808,7 +442,7 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
}
}
if (!kernelSubCall.function)
- error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
+ error("[VM] k%s: subfunction ID %d requested, but not available", kernelCall.name, subId);
addKernelCallToExecStack(s, kernelCallNr, argc, argv);
s->r_acc = kernelSubCall.function(s, argc, argv);
@@ -826,13 +460,6 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
s->_executionStack.pop_back();
}
-static void gcCountDown(EngineState *s) {
- if (s->gcCountDown-- <= 0) {
- s->gcCountDown = s->scriptGCInterval;
- run_gc(s);
- }
-}
-
int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) {
uint offset = 0;
extOpcode = src[offset++]; // Get "extended" opcode (lower bit has special meaning)
@@ -925,7 +552,7 @@ void run_vm(EngineState *s) {
StackPtr s_temp; // Temporary stack pointer
int16 opparams[4]; // opcode parameters
- s->restAdjust = 0; // &rest adjusts the parameter count by this value
+ s->r_rest = 0; // &rest adjusts the parameter count by this value
// Current execution data:
s->xs = &(s->_executionStack.back());
ExecStack *xs_new = NULL;
@@ -945,6 +572,10 @@ void run_vm(EngineState *s) {
s->_executionStackPosChanged = true; // Force initialization
+#ifdef ABORT_ON_INFINITE_LOOP
+ byte prevOpcode = 0xFF;
+#endif
+
while (1) {
int var_type; // See description below
int var_number;
@@ -1009,191 +640,77 @@ void run_vm(EngineState *s) {
byte extOpcode;
s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams);
const byte opcode = extOpcode >> 1;
+ //debug("%s: %d, %d, %d, %d, acc = %04x:%04x, script %d, local script %d", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc), scr->getScriptNumber(), local_script->getScriptNumber());
+
+#ifdef ABORT_ON_INFINITE_LOOP
+ if (prevOpcode != 0xFF) {
+ if (prevOpcode == op_eq_ || prevOpcode == op_ne_ ||
+ prevOpcode == op_gt_ || prevOpcode == op_ge_ ||
+ prevOpcode == op_lt_ || prevOpcode == op_le_ ||
+ prevOpcode == op_ugt_ || prevOpcode == op_uge_ ||
+ prevOpcode == op_ult_ || prevOpcode == op_ule_) {
+ if (opcode == op_jmp)
+ error("Infinite loop detected in script %d", scr->getScriptNumber());
+ }
+ }
+
+ prevOpcode = opcode;
+#endif
switch (opcode) {
- case op_bnot: { // 0x00 (00)
+ case op_bnot: // 0x00 (00)
// Binary not
- int16 value;
- if (validate_signedInteger(s->r_acc, value))
- s->r_acc = make_reg(0, 0xffff ^ value);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, NULL_REG);
+ s->r_acc = make_reg(0, 0xffff ^ s->r_acc.requireUint16());
break;
- }
case op_add: // 0x01 (01)
- r_temp = POP32();
-
- // Happens in SQ1, room 28, when throwing the water at Orat
- if (s->r_acc.segment == 0xFFFF) {
- // WORKAROUND: init uninitialized variable to 0
- warning("op_add: attempt to write to uninitialized variable");
- s->r_acc = NULL_REG;
- }
-
- if (r_temp.segment || s->r_acc.segment) {
- reg_t r_ptr = NULL_REG;
- int offset;
- // Pointer arithmetics!
- if (s->r_acc.segment) {
- if (r_temp.segment) {
- error("Attempt to add two pointers, stack=%04x:%04x and acc=%04x:%04x",
- PRINT_REG(r_temp), PRINT_REG(s->r_acc));
- offset = 0;
- } else {
- r_ptr = s->r_acc;
- offset = r_temp.offset;
- }
- } else {
- r_ptr = r_temp;
- offset = s->r_acc.offset;
- }
-
- s->r_acc = pointer_add(s, r_ptr, offset);
-
- } else
- s->r_acc = make_reg(0, r_temp.offset + s->r_acc.offset);
+ s->r_acc = POP32() + s->r_acc;
break;
case op_sub: // 0x02 (02)
- r_temp = POP32();
- if (r_temp.segment != s->r_acc.segment) {
- reg_t r_ptr = NULL_REG;
- int offset;
- // Pointer arithmetics!
- if (s->r_acc.segment) {
- if (r_temp.segment) {
- error("Attempt to subtract two pointers, stack=%04x:%04x and acc=%04x:%04x",
- PRINT_REG(r_temp), PRINT_REG(s->r_acc));
- offset = 0;
- } else {
- r_ptr = s->r_acc;
- offset = r_temp.offset;
- }
- } else {
- r_ptr = r_temp;
- offset = s->r_acc.offset;
- }
-
- s->r_acc = pointer_add(s, r_ptr, -offset);
-
- } else {
- // We can subtract numbers, or pointers with the same segment,
- // an operation which will yield a number like in C
- s->r_acc = make_reg(0, r_temp.offset - s->r_acc.offset);
- }
+ s->r_acc = POP32() - s->r_acc;
break;
- case op_mul: { // 0x03 (03)
- r_temp = POP32();
- int16 value1, value2;
- if (validate_signedInteger(s->r_acc, value1) && validate_signedInteger(r_temp, value2))
- s->r_acc = make_reg(0, value1 * value2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeMulWorkarounds, s->r_acc, r_temp);
+ case op_mul: // 0x03 (03)
+ s->r_acc = POP32() * s->r_acc;
break;
- }
- case op_div: { // 0x04 (04)
- r_temp = POP32();
- int16 divisor, dividend;
- if (validate_signedInteger(s->r_acc, divisor) && validate_signedInteger(r_temp, dividend))
- s->r_acc = make_reg(0, (divisor != 0 ? dividend / divisor : 0));
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeDivWorkarounds, s->r_acc, r_temp);
+ case op_div: // 0x04 (04)
+ // we check for division by 0 inside the custom reg_t division operator
+ s->r_acc = POP32() / s->r_acc;
break;
- }
-
- case op_mod: { // 0x05 (05)
- r_temp = POP32();
- if (getSciVersion() <= SCI_VERSION_0_LATE) {
- uint16 modulo, value;
- if (validate_unsignedInteger(s->r_acc, modulo) && validate_unsignedInteger(r_temp, value))
- s->r_acc = make_reg(0, (modulo != 0 ? value % modulo : 0));
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp);
- } else {
- // In Iceman (and perhaps from SCI0 0.000.685 onwards in general),
- // handling for negative numbers was added. Since Iceman doesn't
- // seem to have issues with the older code, we exclude it for now
- // for simplicity's sake and use the new code for SCI01 and newer
- // games. Fixes the battlecruiser mini game in SQ5 (room 850),
- // bug #3035755
- int16 modulo, value, result;
- if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) {
- modulo = ABS(modulo);
- result = (modulo != 0 ? value % modulo : 0);
- if (result < 0)
- result += modulo;
- s->r_acc = make_reg(0, result);
- } else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp);
- }
+ case op_mod: // 0x05 (05)
+ // we check for division by 0 inside the custom reg_t modulo operator
+ s->r_acc = POP32() % s->r_acc;
break;
- }
- case op_shr: { // 0x06 (06)
+ case op_shr: // 0x06 (06)
// Shift right logical
- r_temp = POP32();
- uint16 value, shiftCount;
- if (validate_unsignedInteger(r_temp, value) && validate_unsignedInteger(s->r_acc, shiftCount))
- s->r_acc = make_reg(0, value >> shiftCount);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ s->r_acc = POP32() >> s->r_acc;
break;
- }
- case op_shl: { // 0x07 (07)
+ case op_shl: // 0x07 (07)
// Shift left logical
- r_temp = POP32();
- uint16 value, shiftCount;
- if (validate_unsignedInteger(r_temp, value) && validate_unsignedInteger(s->r_acc, shiftCount))
- s->r_acc = make_reg(0, value << shiftCount);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ s->r_acc = POP32() << s->r_acc;
break;
- }
- case op_xor: { // 0x08 (08)
- r_temp = POP32();
- uint16 value1, value2;
- if (validate_unsignedInteger(r_temp, value1) && validate_unsignedInteger(s->r_acc, value2))
- s->r_acc = make_reg(0, value1 ^ value2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
+ case op_xor: // 0x08 (08)
+ s->r_acc = POP32() ^ s->r_acc;
break;
- }
- case op_and: { // 0x09 (09)
- r_temp = POP32();
- uint16 value1, value2;
- if (validate_unsignedInteger(r_temp, value1) && validate_unsignedInteger(s->r_acc, value2))
- s->r_acc = make_reg(0, value1 & value2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeAndWorkarounds, r_temp, s->r_acc);
+ case op_and: // 0x09 (09)
+ s->r_acc = POP32() & s->r_acc;
break;
- }
- case op_or: { // 0x0a (10)
- r_temp = POP32();
- uint16 value1, value2;
- if (validate_unsignedInteger(r_temp, value1) && validate_unsignedInteger(s->r_acc, value2))
- s->r_acc = make_reg(0, value1 | value2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeOrWorkarounds, r_temp, s->r_acc);
+ case op_or: // 0x0a (10)
+ s->r_acc = POP32() | s->r_acc;
break;
- }
- case op_neg: { // 0x0b (11)
- int16 value;
- if (validate_signedInteger(s->r_acc, value))
- s->r_acc = make_reg(0, -value);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, NULL_REG);
+ case op_neg: // 0x0b (11)
+ s->r_acc = make_reg(0, -s->r_acc.requireSint16());
break;
- }
case op_not: // 0x0c (12)
s->r_acc = make_reg(0, !(s->r_acc.offset || s->r_acc.segment));
@@ -1201,186 +718,57 @@ void run_vm(EngineState *s) {
break;
case op_eq_: // 0x0d (13)
- // ==
s->r_prev = s->r_acc;
- r_temp = POP32();
- s->r_acc = make_reg(0, r_temp == s->r_acc);
- // Explicitly allow pointers to be compared
+ s->r_acc = make_reg(0, POP32() == s->r_acc);
break;
case op_ne_: // 0x0e (14)
- // !=
s->r_prev = s->r_acc;
- r_temp = POP32();
- s->r_acc = make_reg(0, r_temp != s->r_acc);
- // Explicitly allow pointers to be compared
+ s->r_acc = make_reg(0, POP32() != s->r_acc);
break;
case op_gt_: // 0x0f (15)
- // >
s->r_prev = s->r_acc;
- r_temp = POP32();
- if (r_temp.segment && s->r_acc.segment) {
- // Signed pointer comparison. We do unsigned comparison instead, as that is probably what was intended.
- if (r_temp.segment != s->r_acc.segment)
- warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset);
- } else if (r_temp.segment && !s->r_acc.segment) {
- if (s->r_acc.offset >= 1000)
- error("[VM] op_gt: comparison between a pointer and number");
- // Pseudo-WORKAROUND: Sierra allows any pointer <-> value comparison
- // Happens in SQ1, room 28, when throwing the water at Orat
- s->r_acc = make_reg(0, 1);
- } else {
- int16 compare1, compare2;
- if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 > compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32() > s->r_acc);
break;
case op_ge_: // 0x10 (16)
- // >=
s->r_prev = s->r_acc;
- r_temp = POP32();
- if (r_temp.segment && s->r_acc.segment) {
- if (r_temp.segment != s->r_acc.segment)
- warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset >= s->r_acc.offset);
- } else {
- int16 compare1, compare2;
- if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 >= compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeGeWorkarounds, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32() >= s->r_acc);
break;
case op_lt_: // 0x11 (17)
- // <
s->r_prev = s->r_acc;
- r_temp = POP32();
- if (r_temp.segment && s->r_acc.segment) {
- if (r_temp.segment != s->r_acc.segment)
- warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
- } else if (r_temp.segment && !s->r_acc.segment) {
- if (s->r_acc.offset >= 1000)
- error("[VM] op_lt: comparison between a pointer and number");
- // Pseudo-WORKAROUND: Sierra allows any pointer <-> value comparison
- // Happens in SQ1, room 58, when giving id-card to robot
- s->r_acc = make_reg(0, 1);
- } else {
- int16 compare1, compare2;
- if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 < compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32() < s->r_acc);
break;
case op_le_: // 0x12 (18)
- // <=
s->r_prev = s->r_acc;
- r_temp = POP32();
- if (r_temp.segment && s->r_acc.segment) {
- if (r_temp.segment != s->r_acc.segment)
- warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset <= s->r_acc.offset);
- } else {
- int16 compare1, compare2;
- if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 <= compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeLeWorkarounds, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32() <= s->r_acc);
break;
case op_ugt_: // 0x13 (19)
// > (unsigned)
s->r_prev = s->r_acc;
- r_temp = POP32();
-
- // SCI0/SCI1 scripts use this to check whether a
- // parameter is a pointer or a far text
- // reference. It is used e.g. by the standard library
- // Print function to distinguish two ways of calling it:
- //
- // (Print "foo") // Pointer to a string
- // (Print 420 5) // Reference to the fifth message in text resource 420
-
- // It works because in those games, the maximum resource number is 999,
- // so any parameter value above that threshold must be a pointer.
- if (r_temp.segment && (s->r_acc == make_reg(0, 1000)))
- s->r_acc = make_reg(0, 1);
- else if (r_temp.segment && s->r_acc.segment)
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset);
- else {
- uint16 compare1, compare2;
- if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 > compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32().gtU(s->r_acc));
break;
case op_uge_: // 0x14 (20)
// >= (unsigned)
s->r_prev = s->r_acc;
- r_temp = POP32();
-
- // See above
- if (r_temp.segment && (s->r_acc == make_reg(0, 1000)))
- s->r_acc = make_reg(0, 1);
- else if (r_temp.segment && s->r_acc.segment)
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset >= s->r_acc.offset);
- else {
- uint16 compare1, compare2;
- if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 >= compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32().geU(s->r_acc));
break;
case op_ult_: // 0x15 (21)
// < (unsigned)
s->r_prev = s->r_acc;
- r_temp = POP32();
-
- // See above
- // PQ2 japanese compares pointers to 2000 to find out if its a pointer or a resourceid
- if (r_temp.segment && (s->r_acc == make_reg(0, 1000) || (s->r_acc == make_reg(0, 2000))))
- s->r_acc = NULL_REG;
- else if (r_temp.segment && s->r_acc.segment)
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
- else {
- uint16 compare1, compare2;
- if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 < compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeUltWorkarounds, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32().ltU(s->r_acc));
break;
case op_ule_: // 0x16 (22)
// <= (unsigned)
s->r_prev = s->r_acc;
- r_temp = POP32();
-
- // See above
- if (r_temp.segment && (s->r_acc == make_reg(0, 1000)))
- s->r_acc = NULL_REG;
- else if (r_temp.segment && s->r_acc.segment)
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset <= s->r_acc.offset);
- else {
- uint16 compare1, compare2;
- if (validate_unsignedInteger(r_temp, compare1) && validate_unsignedInteger(s->r_acc, compare2))
- s->r_acc = make_reg(0, compare1 <= compare2);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc);
- }
+ s->r_acc = make_reg(0, POP32().leU(s->r_acc));
break;
case op_bt: // 0x17 (23)
@@ -1437,19 +825,22 @@ void run_vm(EngineState *s) {
case op_call: { // 0x20 (32)
// Call a script subroutine
int argc = (opparams[1] >> 1) // Given as offset, but we need count
- + 1 + s->restAdjust;
+ + 1 + s->r_rest;
StackPtr call_base = s->xs->sp - argc;
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0];
- xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment,
- localCallOffset),
- s->xs->sp, s->xs->objp,
- (validate_arithmetic(*call_base)) + s->restAdjust,
- call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp,
- s->_executionStack.size()-1, s->xs->local_segment);
- s->restAdjust = 0; // Used up the &rest adjustment
+ ExecStack xstack(s->xs->objp, s->xs->objp, s->xs->sp,
+ (call_base->requireUint16()) + s->r_rest, call_base,
+ s->xs->local_segment, make_reg(s->xs->addr.pc.segment, localCallOffset),
+ NULL_SELECTOR, -1, localCallOffset, s->_executionStack.size() - 1,
+ EXEC_STACK_TYPE_CALL);
+
+ s->_executionStack.push_back(xstack);
+ xs_new = &(s->_executionStack.back());
+
+ s->r_rest = 0; // Used up the &rest adjustment
s->xs->sp = call_base;
s->_executionStackPosChanged = true;
@@ -1457,24 +848,28 @@ void run_vm(EngineState *s) {
}
case op_callk: { // 0x21 (33)
- // Call kernel function
- gcCountDown(s);
+ // Run the garbage collector, if needed
+ if (s->gcCountDown-- <= 0) {
+ s->gcCountDown = s->scriptGCInterval;
+ run_gc(s);
+ }
+ // Call kernel function
s->xs->sp -= (opparams[1] >> 1) + 1;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
if (!oldScriptHeader)
- s->xs->sp -= s->restAdjust;
+ s->xs->sp -= s->r_rest;
- int argc = validate_arithmetic(s->xs->sp[0]);
+ int argc = s->xs->sp[0].requireUint16();
if (!oldScriptHeader)
- argc += s->restAdjust;
+ argc += s->r_rest;
callKernelFunc(s, opparams[0], argc);
if (!oldScriptHeader)
- s->restAdjust = 0;
+ s->r_rest = 0;
// Calculate xs again: The kernel function might
// have spawned a new VM
@@ -1491,28 +886,28 @@ void run_vm(EngineState *s) {
case op_callb: // 0x22 (34)
// Call base script
- temp = ((opparams[1] >> 1) + s->restAdjust + 1);
+ temp = ((opparams[1] >> 1) + s->r_rest + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
- s->xs->sp[0].offset += s->restAdjust;
+ s->xs->sp[0].offset += s->r_rest;
xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp,
s->xs->sp[0].offset, s->xs->sp);
- s->restAdjust = 0; // Used up the &rest adjustment
+ s->r_rest = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
break;
case op_calle: // 0x23 (35)
// Call external script
- temp = ((opparams[2] >> 1) + s->restAdjust + 1);
+ temp = ((opparams[2] >> 1) + s->r_rest + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
- s->xs->sp[0].offset += s->restAdjust;
+ s->xs->sp[0].offset += s->r_rest;
xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp,
s->xs->sp[0].offset, s->xs->sp);
- s->restAdjust = 0; // Used up the &rest adjustment
+ s->r_rest = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
@@ -1564,16 +959,16 @@ void run_vm(EngineState *s) {
case op_send: // 0x25 (37)
// Send for one or more selectors
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
+ s->xs->sp -= ((opparams[0] >> 1) + s->r_rest); // Adjust stack
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp,
- (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp);
+ (int)(opparams[0] >> 1) + (uint16)s->r_rest, s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjust = 0;
+ s->r_rest = 0;
break;
@@ -1607,38 +1002,38 @@ void run_vm(EngineState *s) {
case op_self: // 0x2a (42)
// Send to self
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
+ s->xs->sp -= ((opparams[0] >> 1) + s->r_rest); // Adjust stack
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
xs_new = send_selector(s, s->xs->objp, s->xs->objp,
- s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjust,
+ s_temp, (int)(opparams[0] >> 1) + (uint16)s->r_rest,
s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjust = 0;
+ s->r_rest = 0;
break;
case op_super: // 0x2b (43)
// Send to any class
r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc);
- if (!r_temp.segment)
+ if (!r_temp.isPointer())
error("[VM]: Invalid superclass in object");
else {
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[1] >> 1) + s->restAdjust); // Adjust stack
+ s->xs->sp -= ((opparams[1] >> 1) + s->r_rest); // Adjust stack
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
xs_new = send_selector(s, r_temp, s->xs->objp, s_temp,
- (int)(opparams[1] >> 1) + (uint16)s->restAdjust,
+ (int)(opparams[1] >> 1) + (uint16)s->r_rest,
s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjust = 0;
+ s->r_rest = 0;
}
break;
@@ -1646,7 +1041,7 @@ void run_vm(EngineState *s) {
case op_rest: // 0x2c (44)
// Pushes all or part of the parameter variable list on the stack
temp = (uint16) opparams[0]; // First argument
- s->restAdjust = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
+ s->r_rest = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
for (; temp <= s->xs->argc; temp++)
PUSH32(s->xs->variables_argp[temp]);
@@ -1663,7 +1058,7 @@ void run_vm(EngineState *s) {
r_temp.offset = s->variables[var_number] - s->variablesBase[var_number];
if (temp & 0x08) // Add accumulator offset if requested
- r_temp.offset += signed_validate_arithmetic(s->r_acc);
+ r_temp.offset += s->r_acc.requireSint16();
r_temp.offset += opparams[1]; // Add index
r_temp.offset *= 2; // variables are 16 bit
@@ -1707,87 +1102,29 @@ void run_vm(EngineState *s) {
validate_property(s, obj, opparams[0]) = POP32();
break;
- case op_ipToa: { // 0x35 (53)
- // Increment Property and copy To Accumulator
- reg_t &opProperty = validate_property(s, obj, opparams[0]);
- uint16 valueProperty;
- if (validate_unsignedInteger(opProperty, valueProperty))
- s->r_acc = make_reg(0, valueProperty + 1);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, opProperty, NULL_REG);
- opProperty = s->r_acc;
- break;
- }
-
- case op_dpToa: { // 0x36 (54)
- // Decrement Property and copy To Accumulator
- reg_t &opProperty = validate_property(s, obj, opparams[0]);
- uint16 valueProperty;
- if (validate_unsignedInteger(opProperty, valueProperty))
- s->r_acc = make_reg(0, valueProperty - 1);
- else
- s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeDptoaWorkarounds, opProperty, NULL_REG);
- opProperty = s->r_acc;
- break;
- }
-
- case op_ipTos: { // 0x37 (55)
- // Increment Property and push to Stack
+ case op_ipToa: // 0x35 (53)
+ case op_dpToa: // 0x36 (54)
+ case op_ipTos: // 0x37 (55)
+ case op_dpTos: // 0x38 (56)
+ {
+ // Increment/decrement a property and copy to accumulator,
+ // or push to stack
reg_t &opProperty = validate_property(s, obj, opparams[0]);
- uint16 valueProperty;
- if (validate_unsignedInteger(opProperty, valueProperty))
- valueProperty++;
+ if (opcode & 1)
+ opProperty += 1;
else
- valueProperty = arithmetic_lookForWorkaround(opcode, NULL, opProperty, NULL_REG).offset;
- opProperty = make_reg(0, valueProperty);
- PUSH(valueProperty);
- break;
- }
+ opProperty -= 1;
- case op_dpTos: { // 0x38 (56)
- // Decrement Property and push to Stack
- reg_t &opProperty = validate_property(s, obj, opparams[0]);
- uint16 valueProperty;
- if (validate_unsignedInteger(opProperty, valueProperty))
- valueProperty--;
+ if (opcode == op_ipToa || opcode == op_dpToa)
+ s->r_acc = opProperty;
else
- valueProperty = arithmetic_lookForWorkaround(opcode, NULL, opProperty, NULL_REG).offset;
- opProperty = make_reg(0, valueProperty);
- PUSH(valueProperty);
+ PUSH32(opProperty);
break;
}
case op_lofsa: // 0x39 (57)
- // Load Offset to Accumulator
- s->r_acc.segment = s->xs->addr.pc.segment;
-
- switch (g_sci->_features->detectLofsType()) {
- case SCI_VERSION_0_EARLY:
- s->r_acc.offset = s->xs->addr.pc.offset + opparams[0];
- break;
- case SCI_VERSION_1_MIDDLE:
- s->r_acc.offset = opparams[0];
- break;
- case SCI_VERSION_1_1:
- s->r_acc.offset = opparams[0] + local_script->getScriptSize();
- break;
- case SCI_VERSION_3:
- // In theory this can break if the variant with a one-byte argument is
- // used. For now, assume it doesn't happen.
- s->r_acc.offset = local_script->relocateOffsetSci3(s->xs->addr.pc.offset-2);
- break;
- default:
- error("Unknown lofs type");
- }
-
- if (s->r_acc.offset >= scr->getBufSize()) {
- error("VM: lofsa operation overflowed: %04x:%04x beyond end"
- " of script (at %04x)", PRINT_REG(s->r_acc), scr->getBufSize());
- }
- break;
-
case op_lofss: // 0x3a (58)
- // Load Offset to Stack
+ // Load offset to accumulator or push to stack
r_temp.segment = s->xs->addr.pc.segment;
switch (g_sci->_features->detectLofsType()) {
@@ -1801,17 +1138,22 @@ void run_vm(EngineState *s) {
r_temp.offset = opparams[0] + local_script->getScriptSize();
break;
case SCI_VERSION_3:
- r_temp.offset = opparams[0];
+ // In theory this can break if the variant with a one-byte argument is
+ // used. For now, assume it doesn't happen.
+ r_temp.offset = local_script->relocateOffsetSci3(s->xs->addr.pc.offset-2);
break;
default:
error("Unknown lofs type");
}
- if (r_temp.offset >= scr->getBufSize()) {
- error("VM: lofss operation overflowed: %04x:%04x beyond end"
+ if (r_temp.offset >= scr->getBufSize())
+ error("VM: lofsa/lofss operation overflowed: %04x:%04x beyond end"
" of script (at %04x)", PRINT_REG(r_temp), scr->getBufSize());
- }
- PUSH32(r_temp);
+
+ if (opcode == op_lofsa)
+ s->r_acc = r_temp;
+ else
+ PUSH32(r_temp);
break;
case op_push0: // 0x3b (59)
@@ -1849,9 +1191,15 @@ void run_vm(EngineState *s) {
case op_lat: // 0x42 (66)
case op_lap: // 0x43 (67)
// Load global, local, temp or param variable into the accumulator
+ case op_lagi: // 0x48 (72)
+ case op_lali: // 0x49 (73)
+ case op_lati: // 0x4a (74)
+ case op_lapi: // 0x4b (75)
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- s->r_acc = READ_VAR(var_type, var_number);
+ var_number = opparams[0] + (opcode >= op_lagi ? s->r_acc.requireSint16() : 0);
+ s->r_acc = read_var(s, var_type, var_number);
break;
case op_lsg: // 0x44 (68)
@@ -1859,86 +1207,49 @@ void run_vm(EngineState *s) {
case op_lst: // 0x46 (70)
case op_lsp: // 0x47 (71)
// Load global, local, temp or param variable into the stack
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- PUSH32(READ_VAR(var_type, var_number));
- break;
-
- case op_lagi: // 0x48 (72)
- case op_lali: // 0x49 (73)
- case op_lati: // 0x4a (74)
- case op_lapi: { // 0x4b (75)
- // Load global, local, temp or param variable into the accumulator,
- // using the accumulator as an additional index
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- int16 value;
- if (!validate_signedInteger(s->r_acc, value))
- value = arithmetic_lookForWorkaround(opcode, opcodeLaiWorkarounds, s->r_acc, NULL_REG).offset;
- var_number = opparams[0] + value;
- s->r_acc = READ_VAR(var_type, var_number);
- break;
- }
-
case op_lsgi: // 0x4c (76)
case op_lsli: // 0x4d (77)
case op_lsti: // 0x4e (78)
- case op_lspi: { // 0x4f (79)
- // Load global, local, temp or param variable into the stack,
- // using the accumulator as an additional index
+ case op_lspi: // 0x4f (79)
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- int16 value;
- if (!validate_signedInteger(s->r_acc, value))
- value = arithmetic_lookForWorkaround(opcode, opcodeLsiWorkarounds, s->r_acc, NULL_REG).offset;
- var_number = opparams[0] + value;
- PUSH32(READ_VAR(var_type, var_number));
+ var_number = opparams[0] + (opcode >= op_lsgi ? s->r_acc.requireSint16() : 0);
+ PUSH32(read_var(s, var_type, var_number));
break;
- }
case op_sag: // 0x50 (80)
case op_sal: // 0x51 (81)
case op_sat: // 0x52 (82)
case op_sap: // 0x53 (83)
// Save the accumulator into the global, local, temp or param variable
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- WRITE_VAR(var_type, var_number, s->r_acc);
- break;
-
- case op_ssg: // 0x54 (84)
- case op_ssl: // 0x55 (85)
- case op_sst: // 0x56 (86)
- case op_ssp: // 0x57 (87)
- // Save the stack into the global, local, temp or param variable
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- WRITE_VAR(var_type, var_number, POP32());
- break;
-
case op_sagi: // 0x58 (88)
case op_sali: // 0x59 (89)
case op_sati: // 0x5a (90)
case op_sapi: // 0x5b (91)
// Save the accumulator into the global, local, temp or param variable,
// using the accumulator as an additional index
-
- // Special semantics because it wouldn't really make a whole lot
- // of sense otherwise, with acc being used for two things
- // simultaneously...
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- s->r_acc = POP32();
- WRITE_VAR(var_type, var_number, s->r_acc);
+ var_number = opparams[0] + (opcode >= op_sagi ? s->r_acc.requireSint16() : 0);
+ if (opcode >= op_sagi) // load the actual value to store in the accumulator
+ s->r_acc = POP32();
+ write_var(s, var_type, var_number, s->r_acc);
break;
+ case op_ssg: // 0x54 (84)
+ case op_ssl: // 0x55 (85)
+ case op_sst: // 0x56 (86)
+ case op_ssp: // 0x57 (87)
+ // Save the stack into the global, local, temp or param variable
case op_ssgi: // 0x5c (92)
case op_ssli: // 0x5d (93)
case op_ssti: // 0x5e (94)
case op_sspi: // 0x5f (95)
- // Save the stack into the global, local, temp or param variable,
- // using the accumulator as an additional index
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- WRITE_VAR(var_type, var_number, POP32());
+ var_number = opparams[0] + (opcode >= op_ssgi ? s->r_acc.requireSint16() : 0);
+ write_var(s, var_type, var_number, POP32());
break;
case op_plusag: // 0x60 (96)
@@ -1947,15 +1258,16 @@ void run_vm(EngineState *s) {
case op_plusap: // 0x63 (99)
// Increment the global, local, temp or param variable and save it
// to the accumulator
+ case op_plusagi: // 0x68 (104)
+ case op_plusali: // 0x69 (105)
+ case op_plusati: // 0x6a (106)
+ case op_plusapi: // 0x6b (107)
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- s->r_acc = pointer_add(s, r_temp, 1);
- } else
- s->r_acc = make_reg(0, r_temp.offset + 1);
- WRITE_VAR(var_type, var_number, s->r_acc);
+ var_number = opparams[0] + (opcode >= op_plusagi ? s->r_acc.requireSint16() : 0);
+ s->r_acc = read_var(s, var_type, var_number) + 1;
+ write_var(s, var_type, var_number, s->r_acc);
break;
case op_plussg: // 0x64 (100)
@@ -1964,51 +1276,17 @@ void run_vm(EngineState *s) {
case op_plussp: // 0x67 (103)
// Increment the global, local, temp or param variable and save it
// to the stack
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- r_temp = pointer_add(s, r_temp, 1);
- } else
- r_temp = make_reg(0, r_temp.offset + 1);
- PUSH32(r_temp);
- WRITE_VAR(var_type, var_number, r_temp);
- break;
-
- case op_plusagi: // 0x68 (104)
- case op_plusali: // 0x69 (105)
- case op_plusati: // 0x6a (106)
- case op_plusapi: // 0x6b (107)
- // Increment the global, local, temp or param variable and save it
- // to the accumulator, using the accumulator as an additional index
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- s->r_acc = pointer_add(s, r_temp, 1);
- } else
- s->r_acc = make_reg(0, r_temp.offset + 1);
- WRITE_VAR(var_type, var_number, s->r_acc);
- break;
-
case op_plussgi: // 0x6c (108)
case op_plussli: // 0x6d (109)
case op_plussti: // 0x6e (110)
case op_plusspi: // 0x6f (111)
- // Increment the global, local, temp or param variable and save it
- // to the stack, using the accumulator as an additional index
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- r_temp = pointer_add(s, r_temp, 1);
- } else
- r_temp = make_reg(0, r_temp.offset + 1);
+ var_number = opparams[0] + (opcode >= op_plussgi ? s->r_acc.requireSint16() : 0);
+ r_temp = read_var(s, var_type, var_number) + 1;
PUSH32(r_temp);
- WRITE_VAR(var_type, var_number, r_temp);
+ write_var(s, var_type, var_number, r_temp);
break;
case op_minusag: // 0x70 (112)
@@ -2017,15 +1295,16 @@ void run_vm(EngineState *s) {
case op_minusap: // 0x73 (115)
// Decrement the global, local, temp or param variable and save it
// to the accumulator
+ case op_minusagi: // 0x78 (120)
+ case op_minusali: // 0x79 (121)
+ case op_minusati: // 0x7a (122)
+ case op_minusapi: // 0x7b (123)
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- s->r_acc = pointer_add(s, r_temp, -1);
- } else
- s->r_acc = make_reg(0, r_temp.offset - 1);
- WRITE_VAR(var_type, var_number, s->r_acc);
+ var_number = opparams[0] + (opcode >= op_minusagi ? s->r_acc.requireSint16() : 0);
+ s->r_acc = read_var(s, var_type, var_number) - 1;
+ write_var(s, var_type, var_number, s->r_acc);
break;
case op_minussg: // 0x74 (116)
@@ -2034,51 +1313,17 @@ void run_vm(EngineState *s) {
case op_minussp: // 0x77 (119)
// Decrement the global, local, temp or param variable and save it
// to the stack
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0];
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- r_temp = pointer_add(s, r_temp, -1);
- } else
- r_temp = make_reg(0, r_temp.offset - 1);
- PUSH32(r_temp);
- WRITE_VAR(var_type, var_number, r_temp);
- break;
-
- case op_minusagi: // 0x78 (120)
- case op_minusali: // 0x79 (121)
- case op_minusati: // 0x7a (122)
- case op_minusapi: // 0x7b (123)
- // Decrement the global, local, temp or param variable and save it
- // to the accumulator, using the accumulator as an additional index
- var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- s->r_acc = pointer_add(s, r_temp, -1);
- } else
- s->r_acc = make_reg(0, r_temp.offset - 1);
- WRITE_VAR(var_type, var_number, s->r_acc);
- break;
-
case op_minussgi: // 0x7c (124)
case op_minussli: // 0x7d (125)
case op_minussti: // 0x7e (126)
case op_minusspi: // 0x7f (127)
- // Decrement the global, local, temp or param variable and save it
- // to the stack, using the accumulator as an additional index
+ // Same as the 4 ones above, except that the accumulator is used as
+ // an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
- var_number = opparams[0] + signed_validate_arithmetic(s->r_acc);
- r_temp = READ_VAR(var_type, var_number);
- if (r_temp.segment) {
- // Pointer arithmetics!
- r_temp = pointer_add(s, r_temp, -1);
- } else
- r_temp = make_reg(0, r_temp.offset - 1);
+ var_number = opparams[0] + (opcode >= op_minussgi ? s->r_acc.requireSint16() : 0);
+ r_temp = read_var(s, var_type, var_number) - 1;
PUSH32(r_temp);
- WRITE_VAR(var_type, var_number, r_temp);
+ write_var(s, var_type, var_number, r_temp);
break;
default:
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index ee22e03310..5947579aa3 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -92,9 +92,10 @@ struct ExecStack {
StackPtr fp; // Frame pointer
StackPtr sp; // Stack pointer
- int argc;
+ int argc;
StackPtr variables_argp; // Argument pointer
+
SegmentId local_segment; // local variables etc
Selector debugSelector; // The selector which was used to call or -1 if not applicable
@@ -104,6 +105,29 @@ struct ExecStack {
ExecStackType type;
reg_t* getVarPointer(SegManager *segMan) const;
+
+ ExecStack(reg_t objp_, reg_t sendp_, StackPtr sp_, int argc_, StackPtr argp_,
+ SegmentId localsSegment_, reg_t pc_, Selector debugSelector_,
+ int debugExportId_, int debugLocalCallOffset_, int debugOrigin_,
+ ExecStackType type_) {
+ objp = objp_;
+ sendp = sendp_;
+ // varp is set separately for varselector calls
+ addr.pc = pc_;
+ fp = sp = sp_;
+ argc = argc_;
+ variables_argp = argp_;
+ *variables_argp = make_reg(0, argc); // The first argument is argc
+ if (localsSegment_ != 0xFFFF)
+ local_segment = localsSegment_;
+ else
+ local_segment = pc_.segment;
+ debugSelector = debugSelector_;
+ debugExportId = debugExportId_;
+ debugLocalCallOffset = debugLocalCallOffset_;
+ debugOrigin = debugOrigin_;
+ type = type_;
+ }
};
enum {
@@ -115,7 +139,7 @@ enum {
/** Number of kernel calls in between gcs; should be < 50000 */
enum {
- GC_INTERVAL = 32768
+ GC_INTERVAL = 0x8000
};
// Opcode formats
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
new file mode 100644
index 0000000000..e606fa1f86
--- /dev/null
+++ b/engines/sci/engine/vm_types.cpp
@@ -0,0 +1,227 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/engine/seg_manager.h"
+#include "sci/engine/vm_types.h"
+#include "sci/engine/workarounds.h"
+
+namespace Sci {
+
+reg_t reg_t::lookForWorkaround(const reg_t right) const {
+ SciTrackOriginReply originReply;
+ SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, arithmeticWorkarounds, &originReply);
+ if (solution.type == WORKAROUND_NONE)
+ error("Invalid arithmetic operation (params: %04x:%04x and %04x:%04x) from method %s::%s (script %d, room %d, localCall %x)",
+ PRINT_REG(*this), PRINT_REG(right), originReply.objectName.c_str(),
+ originReply.methodName.c_str(), originReply.scriptNr, g_sci->getEngineState()->currentRoomNumber(),
+ originReply.localCallOffset);
+ assert(solution.type == WORKAROUND_FAKE);
+ return make_reg(0, solution.value);
+}
+
+reg_t reg_t::operator+(const reg_t right) const {
+ if (isPointer() && right.isNumber()) {
+ // Pointer arithmetics. Only some pointer types make sense here
+ SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(segment);
+
+ if (!mobj)
+ error("[VM]: Attempt to add %d to invalid pointer %04x:%04x", right.offset, PRINT_REG(*this));
+
+ switch (mobj->getType()) {
+ case SEG_TYPE_LOCALS:
+ case SEG_TYPE_SCRIPT:
+ case SEG_TYPE_STACK:
+ case SEG_TYPE_DYNMEM:
+ return make_reg(segment, offset + right.toSint16());
+ default:
+ return lookForWorkaround(right);
+ }
+ } else if (isNumber() && right.isPointer()) {
+ // Adding a pointer to a number, flip the order
+ return right + *this;
+ } else if (isNumber() && right.isNumber()) {
+ // Normal arithmetics
+ return make_reg(0, toSint16() + right.toSint16());
+ } else {
+ return lookForWorkaround(right);
+ }
+}
+
+reg_t reg_t::operator-(const reg_t right) const {
+ if (segment == right.segment) {
+ // We can subtract numbers, or pointers with the same segment,
+ // an operation which will yield a number like in C
+ return make_reg(0, toSint16() - right.toSint16());
+ } else {
+ return *this + make_reg(right.segment, -right.offset);
+ }
+}
+
+reg_t reg_t::operator*(const reg_t right) const {
+ if (isNumber() && right.isNumber())
+ return make_reg(0, toSint16() * right.toSint16());
+ else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator/(const reg_t right) const {
+ if (isNumber() && right.isNumber() && !right.isNull())
+ return make_reg(0, toSint16() / right.toSint16());
+ else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator%(const reg_t right) const {
+ if (isNumber() && right.isNumber() && !right.isNull()) {
+ // Support for negative numbers was added in Iceman, and perhaps in
+ // SCI0 0.000.685 and later. Theoretically, this wasn't really used
+ // in SCI0, so the result is probably unpredictable. Such a case
+ // would indicate either a script bug, or a modulo on an unsigned
+ // integer larger than 32767. In any case, such a case should be
+ // investigated, instead of being silently accepted.
+ if (getSciVersion() <= SCI_VERSION_0_LATE && (toSint16() < 0 || right.toSint16() < 0))
+ warning("Modulo of a negative number has been requested for SCI0. This *could* lead to issues");
+ int16 value = toSint16();
+ int16 modulo = ABS(right.toSint16());
+ int16 result = value % modulo;
+ if (result < 0)
+ result += modulo;
+ return make_reg(0, result);
+ } else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator>>(const reg_t right) const {
+ if (isNumber() && right.isNumber())
+ return make_reg(0, toUint16() >> right.toUint16());
+ else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator<<(const reg_t right) const {
+ if (isNumber() && right.isNumber())
+ return make_reg(0, toUint16() << right.toUint16());
+ else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator+(int16 right) const {
+ return *this + make_reg(0, right);
+}
+
+reg_t reg_t::operator-(int16 right) const {
+ return *this - make_reg(0, right);
+}
+
+uint16 reg_t::requireUint16() const {
+ if (isNumber())
+ return toUint16();
+ else
+ // The right parameter is NULL_REG because
+ // we're not comparing *this with anything here.
+ return lookForWorkaround(NULL_REG).toUint16();
+}
+
+int16 reg_t::requireSint16() const {
+ if (isNumber())
+ return toSint16();
+ else
+ // The right parameter is NULL_REG because
+ // we're not comparing *this with anything here.
+ return lookForWorkaround(NULL_REG).toSint16();
+}
+
+reg_t reg_t::operator&(const reg_t right) const {
+ if (isNumber() && right.isNumber())
+ return make_reg(0, toUint16() & right.toUint16());
+ else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator|(const reg_t right) const {
+ if (isNumber() && right.isNumber())
+ return make_reg(0, toUint16() | right.toUint16());
+ else
+ return lookForWorkaround(right);
+}
+
+reg_t reg_t::operator^(const reg_t right) const {
+ if (isNumber() && right.isNumber())
+ return make_reg(0, toUint16() ^ right.toUint16());
+ else
+ return lookForWorkaround(right);
+}
+
+int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
+ if (segment == right.segment) { // can compare things in the same segment
+ if (treatAsUnsigned || !isNumber())
+ return toUint16() - right.toUint16();
+ else
+ return toSint16() - right.toSint16();
+ } else if (pointerComparisonWithInteger(right)) {
+ return 1;
+ } else if (right.pointerComparisonWithInteger(*this)) {
+ return -1;
+ } else
+ return lookForWorkaround(right).toSint16();
+}
+
+bool reg_t::pointerComparisonWithInteger(const reg_t right) const {
+ // This function handles the case where a script tries to compare a pointer
+ // to a number. Normally, we would not want to allow that. However, SCI0 -
+ // SCI1.1 scripts do this in order to distinguish references to
+ // external resources (which are numbers) from pointers. In
+ // our SCI implementation, such a check may seem pointless, as
+ // one can simply use the segment value to achieve this goal.
+ // But Sierra's SCI did not have the notion of segment IDs, so
+ // both pointer and numbers were simple integers.
+ //
+ // But for some things, scripts had (and have) to distinguish between
+ // numbers and pointers. Lacking the segment information, Sierra's
+ // developers resorted to a hack: If an integer is smaller than a certain
+ // bound, it can be assumed to be a number, otherwise it is assumed to be a
+ // pointer. This allowed them to implement polymorphic functions, such as
+ // the Print function, which can be called in two different ways, with a
+ // pointer or a far text reference:
+ //
+ // (Print "foo") // Pointer to a string
+ // (Print 420 5) // Reference to the fifth message in text resource 420
+ // It works because in those games, the maximum resource number is 999,
+ // so any parameter value above that threshold must be a pointer.
+ // PQ2 japanese compares pointers to 2000 to find out if its a pointer
+ // or a resource ID. Thus, we check for all integers <= 2000.
+ //
+ // Some examples where game scripts check for arbitrary numbers against
+ // pointers:
+ // Hoyle 3, Pachisi, when any opponent is about to talk
+ // SQ1, room 28, when throwing water at the Orat
+ // SQ1, room 58, when giving the ID card to the robot
+ // SQ4 CD, at the first game screen, when the narrator is about to speak
+ return (isPointer() && right.isNumber() && right.offset <= 2000 && getSciVersion() <= SCI_VERSION_1_1);
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h
index edf35a122a..b927df339e 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -37,10 +37,34 @@ struct reg_t {
SegmentId segment;
uint16 offset;
- bool isNull() const {
- return !(offset || segment);
+ inline bool isNull() const {
+ return (offset | segment) == 0;
}
+ inline uint16 toUint16() const {
+ return offset;
+ }
+
+ inline int16 toSint16() const {
+ return (int16)offset;
+ }
+
+ bool isNumber() const {
+ return segment == 0;
+ }
+
+ bool isPointer() const {
+ return segment != 0 && segment != 0xFFFF;
+ }
+
+ uint16 requireUint16() const;
+ int16 requireSint16() const;
+
+ inline bool isInitialized() const {
+ return segment != 0xFFFF;
+ }
+
+ // Comparison operators
bool operator==(const reg_t &x) const {
return (offset == x.offset) && (segment == x.segment);
}
@@ -49,13 +73,73 @@ struct reg_t {
return (offset != x.offset) || (segment != x.segment);
}
- uint16 toUint16() const {
- return offset;
+ bool operator>(const reg_t right) const {
+ return cmp(right, false) > 0;
+ }
+
+ bool operator>=(const reg_t right) const {
+ return cmp(right, false) >= 0;
+ }
+
+ bool operator<(const reg_t right) const {
+ return cmp(right, false) < 0;
+ }
+
+ bool operator<=(const reg_t right) const {
+ return cmp(right, false) <= 0;
+ }
+
+ // Same as the normal operators, but perform unsigned
+ // integer checking
+ bool gtU(const reg_t right) const {
+ return cmp(right, true) > 0;
}
- int16 toSint16() const {
- return (int16) offset;
+ bool geU(const reg_t right) const {
+ return cmp(right, true) >= 0;
}
+
+ bool ltU(const reg_t right) const {
+ return cmp(right, true) < 0;
+ }
+
+ bool leU(const reg_t right) const {
+ return cmp(right, true) <= 0;
+ }
+
+ // Arithmetic operators
+ reg_t operator+(const reg_t right) const;
+ reg_t operator-(const reg_t right) const;
+ reg_t operator*(const reg_t right) const;
+ reg_t operator/(const reg_t right) const;
+ reg_t operator%(const reg_t right) const;
+ reg_t operator>>(const reg_t right) const;
+ reg_t operator<<(const reg_t right) const;
+
+ reg_t operator+(int16 right) const;
+ reg_t operator-(int16 right) const;
+
+ void operator+=(const reg_t &right) { *this = *this + right; }
+ void operator-=(const reg_t &right) { *this = *this - right; }
+ void operator+=(int16 right) { *this = *this + right; }
+ void operator-=(int16 right) { *this = *this - right; }
+
+ // Boolean operators
+ reg_t operator&(const reg_t right) const;
+ reg_t operator|(const reg_t right) const;
+ reg_t operator^(const reg_t right) const;
+
+private:
+ /**
+ * Compares two reg_t's.
+ * Returns:
+ * - a positive number if *this > right
+ * - 0 if *this == right
+ * - a negative number if *this < right
+ */
+ int cmp(const reg_t right, bool treatAsUnsigned) const;
+ reg_t lookForWorkaround(const reg_t right) const;
+ bool pointerComparisonWithInteger(const reg_t right) const;
};
static inline reg_t make_reg(SegmentId segment, uint16 offset) {
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 7adb0b4e04..0fba7a59e3 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -34,69 +34,17 @@
namespace Sci {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeDivWorkarounds[] = {
- { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // when entering inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call, index, workaround
-const SciWorkaroundEntry opcodeDptoaWorkarounds[] = {
- { GID_LSL6, 360, 938, 0, "ROsc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking through tile in the shower room initial cycles get set to an object instead of 2, we fix this by setting 1 after decrease
- { GID_LSL6HIRES, 360,64938, 0, "ROsc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking through tile in the shower room initial cycles get set to an object instead of 2, we fix this by setting 1 after decrease
- { GID_SQ5, 200, 939, 0, "Osc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // when going back to bridge the crew is goofing off, we get an object as cycle count
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeGeWorkarounds[] = {
- { GID_HOYLE1, 5, 213, 0, "", "export 0", -1, 0, { WORKAROUND_FAKE, 1 } }, // happens sometimes during cribbage - bug #3038433
- { GID_MOTHERGOOSE256, 4, 998, 0, "door", "setCel", -1, 0, { WORKAROUND_FAKE, 1 } }, // after giving the king his pipe back, listening to his song and leaving the castle - bug #3051475
- { GID_PQ3, 31, 31, 0, "rm031", "init", -1, 0, { WORKAROUND_FAKE, 1 } }, // pq3 english: when exiting the car, while morales is making phonecalls - bug #3037565
- { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue.
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeLeWorkarounds[] = {
- { GID_PEPPER, 370, 23, 0, "eastExitFeature", "onMe", -1, 0, { WORKAROUND_FAKE, 1 } }, // Pugh's office, when trying to use either the left or right exits, gets called on an integer and a pointer - bug #3040142
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeUltWorkarounds[] = {
- { GID_HOYLE3, 400, 0, 1, "Character", "say", -1, 0, { WORKAROUND_FAKE, 0 } }, // While playing Pachisi, when any character starts to talk - bug #3038837
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeLaiWorkarounds[] = {
- { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, 0, { WORKAROUND_FAKE, 0 } }, // during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #3044734
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeLsiWorkarounds[] = {
- { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // when getting asked for your name by the astrologer bug #3039879
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeMulWorkarounds[] = {
- { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeAndWorkarounds[] = {
- { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // constantly during the game
- // ^^ TODO: which of the mother goose versions is affected by this? EGA? SCI1? SCI1.1?
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry opcodeOrWorkarounds[] = {
- { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464
- { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // when going north and reaching the castle (rooms 4 and 37) - bug #3038228
+const SciWorkaroundEntry arithmeticWorkarounds[] = {
+ { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #3044734
+ { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464
+ { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913
+ { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl
+ { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version)
+ { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #3038228
+ { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue.
+ { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object
+ { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer bug #3039879
+ { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -136,13 +84,14 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
// ^^ shouldn't be needed anymore, we got a script patch instead (kq5PatchCdHarpyVolume)
{ GID_KQ5, 25, 25, 0, "rm025", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is
{ GID_KQ5, 55, 55, 0, "helpScript", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // when giving the tambourine to the monster in the labyrinth (only happens at one of the locations) - bug #3041262
+ { GID_KQ5, -1, 755, 0, "gcWin", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu in the FM-Towns version
{ GID_KQ6, -1, 30, 0, "rats", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #3034597, #3035495, #3035824
{ GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", -1, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #3034565
{ GID_KQ6, 500, 500, 0, "rm500", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast
{ GID_KQ6, 520, 520, 0, "rm520", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle
{ GID_KQ6, -1, 903, 0, "controlWin", "open", -1, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc)
{ GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #3059544
- { GID_KQ7, 30, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key
+ { GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key
{ GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs (bug #3037694)
{ GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up (initial bug #3034985)
{ GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
@@ -165,11 +114,13 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game
{ GID_MOTHERGOOSE256, -1, 0, 0, "MG", "doit", -1, 5, { WORKAROUND_FAKE, 0 } }, // SCI1.1: When moving the cursor all the way to the left during the game (bug #3043955)
{ GID_MOTHERGOOSE256, -1, 992, 0, "AIPath", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // Happens in the demo and full version. In the demo, it happens when walking two screens from mother goose's house to the north. In the full version, it happens in rooms 7 and 23 - bug #3049146
+ { GID_MOTHERGOOSE256, 90, 90, 0, "introScript", "changeState", -1, 65, { WORKAROUND_FAKE, 0 } }, // SCI1(CD): At the very end, after the game is completed and restarted - bug #3268076
{ GID_MOTHERGOOSE256, 94, 94, 0, "sunrise", "changeState", -1, 367, { WORKAROUND_FAKE, 0 } }, // At the very end, after the game is completed - bug #3051163
{ GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later
{ GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // see above
{ GID_PEPPER, -1, 894, 0, "Package", "doVerb", -1, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #3040012
{ GID_PEPPER, 150, 928, 0, "Narrator", "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper
+ { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning
{ GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbd0, 0, { WORKAROUND_FAKE, 0 } }, // hq1: going to the brigands hideout
{ GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbe4, 0, { WORKAROUND_FAKE, 0 } }, // qfg1: going to the brigands hideout
{ GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #3053268
@@ -181,6 +132,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_QFG2, 260, 260, 0, "abdulS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #3039891, temps 1 and 2
{ GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #3040469, temps 1 and 2
{ GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #3148418
+ { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #3272735, #3275413
{ GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #3049435
{ GID_QFG3, 140, 140, 0, "rm140", "init", 0x1008, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #3040460
{ GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #3036390, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #3039774, temp 1)
@@ -191,7 +143,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_QFG3, 851, 32, -1, "ProjObj", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #3050122
{ GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen
{ GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu
- { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happen sometimes in fights
+ { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes
{ GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts
{ GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts
{ GID_RAMA, 12, 64950, -1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts
@@ -266,6 +218,7 @@ const SciWorkaroundEntry kDisplay_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kDirLoop_workarounds[] = {
{ GID_KQ4, 4, 992, 0, "Avoid", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the ogre catches you in front of his house, second parameter points to the same object as the first parameter, instead of being an integer (the angle) - bug #3042964
+ SCI_WORKAROUNDENTRY_TERMINATOR
};
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
@@ -322,12 +275,8 @@ const SciWorkaroundEntry kGraphSaveBox_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = {
- { GID_LSL6, -1, 85, 0, "rScroller", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring (sometimes), same as the one below
- { GID_LSL6, -1, 85, 0, "lScroller", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring (sometimes), same as the one below
- { GID_LSL6, -1, 86, 0, "LL6Inv", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time
- // ^^ TODO: check, if this is really a script error or an issue with our restore code
{ GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter
- { GID_SQ5, 850, 850, 0, "quirksTurn", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens while playing Battle Cruiser (invalid segment) - bug #3056811
+ { GID_SQ5, 850, 850, 0, NULL, "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens while playing Battle Cruiser (invalid segment) - bug #3056811
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -357,6 +306,7 @@ const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = {
{ GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #3036331
{ GID_KQ5, -1, 995, 0, "invW", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified
{ GID_KQ5, -1, 995, 0, "", "export 0", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #3039395
+ { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -364,7 +314,7 @@ const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = {
const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = {
{ GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function
{ GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
- { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
+ { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -378,7 +328,7 @@ const SciWorkaroundEntry kIsObject_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kMemory_workarounds[] = {
- { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train, talking to Mr. Augustini, etc. - bug #3034490
+ { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #3034490
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -409,7 +359,7 @@ const SciWorkaroundEntry kSetCursor_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kSetPort_workarounds[] = {
{ GID_LSL6, 740, 740, 0, "rm740", "drawPic", -1, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters
- { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, bug #3040844
+ { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, gets called with 4 parameters (bug #3040844)
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -421,12 +371,6 @@ const SciWorkaroundEntry kStrAt_workarounds[] = {
};
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry kStrCat_workarounds[] = {
- { GID_LONGBOW, 210, 210, 0, "giveScroll", "changeState",0x3294, 0, { WORKAROUND_FAKE, 0 } }, // German version, when handing the scroll with the druid hand code to Marion - bug #3048054
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kStrLen_workarounds[] = {
{ GID_QFG2, 210, 2, 0, "", "export 21", 0xdeb, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #3100292
SCI_WORKAROUNDENTRY_TERMINATOR
@@ -434,23 +378,13 @@ const SciWorkaroundEntry kStrLen_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kUnLoad_workarounds[] = {
- { GID_CAMELOT, 921, 921, 1, "Script", "changeState", 0x36, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: While showing Camelot (and other places), the reference is invalid - bug #3035000
- { GID_CAMELOT, 921, 921, 1, "Script", "init", 0x36, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When being attacked by the boar (and other places), the reference is invalid - bug #3035000
- { GID_CASTLEBRAIN, 320, 377, 0, "SWord", "upDate", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after solving the cross-word-puzzle, trying to unload invalid reference
- { GID_CASTLEBRAIN, 320, 377, 0, "theWord", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // 2nd word puzzle, when exiting before solving, trying to unload invalid reference - bug #3034473
- { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after talking to the dolphin the first time
- { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room - bug #3098353
- { GID_LAURABOW2, 1, 1, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 2, 2, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 4, 4, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: inside the museum, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 6, 6, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the murder, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 7, 7, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the logo is shown, a 3rd parameter is passed by accident - bug #3034902
+ { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // CD version: after talking to the dolphin the first time, a 3rd parameter is passed by accident
+ { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room, a 3rd parameter is passed by accident - bug #3098353
+ { GID_LAURABOW2, -1, 1, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
{ GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
{ GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident
{ GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
- { GID_PQ3, 877, 998, 0, "View", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when getting run over on the freeway, the reference is invalid
{ GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error
- { GID_SQ3, 2, 998, 0, "View", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // clicking the mouse button during the intro, after the escape pod gets pulled into the garbage freighter, the reference is invalid - bug #3050856
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -464,14 +398,14 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun
return sci3IgnoreForNow;
}
- EngineState *state = g_sci->getEngineState();
+ const EngineState *state = g_sci->getEngineState();
ExecStack *lastCall = state->xs;
- Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
- int curScriptNr = local_script->getScriptNumber();
+ const Script *localScript = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
+ int curScriptNr = localScript->getScriptNumber();
if (lastCall->debugLocalCallOffset != -1) {
// if lastcall was actually a local call search back for a real call
- Common::List<ExecStack>::iterator callIterator = state->_executionStack.end();
+ Common::List<ExecStack>::const_iterator callIterator = state->_executionStack.end();
while (callIterator != state->_executionStack.begin()) {
callIterator--;
ExecStack loopCall = *callIterator;
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index 6de971d156..c7721aa787 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -68,16 +68,7 @@ struct SciWorkaroundEntry {
SciWorkaroundSolution newValue;
};
-extern const SciWorkaroundEntry opcodeDivWorkarounds[];
-extern const SciWorkaroundEntry opcodeDptoaWorkarounds[];
-extern const SciWorkaroundEntry opcodeGeWorkarounds[];
-extern const SciWorkaroundEntry opcodeLeWorkarounds[];
-extern const SciWorkaroundEntry opcodeUltWorkarounds[];
-extern const SciWorkaroundEntry opcodeLaiWorkarounds[];
-extern const SciWorkaroundEntry opcodeLsiWorkarounds[];
-extern const SciWorkaroundEntry opcodeMulWorkarounds[];
-extern const SciWorkaroundEntry opcodeAndWorkarounds[];
-extern const SciWorkaroundEntry opcodeOrWorkarounds[];
+extern const SciWorkaroundEntry arithmeticWorkarounds[];
extern const SciWorkaroundEntry uninitializedReadWorkarounds[];
extern const SciWorkaroundEntry kAbs_workarounds[];
extern const SciWorkaroundEntry kCelHigh_workarounds[];
@@ -104,7 +95,6 @@ extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[];
extern const SciWorkaroundEntry kSetCursor_workarounds[];
extern const SciWorkaroundEntry kSetPort_workarounds[];
extern const SciWorkaroundEntry kStrAt_workarounds[];
-extern const SciWorkaroundEntry kStrCat_workarounds[];
extern const SciWorkaroundEntry kStrLen_workarounds[];
extern const SciWorkaroundEntry kUnLoad_workarounds[];
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index 0c17db6028..6b5ea64fc4 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -32,35 +32,10 @@
#include "sci/console.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
+#include "sci/graphics/screen.h"
namespace Sci {
-EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) {
-
- if (getSciVersion() >= SCI_VERSION_1_MIDDLE) {
- _usesNewKeyboardDirectionType = true;
- } else if (getSciVersion() <= SCI_VERSION_01) {
- _usesNewKeyboardDirectionType = false;
- } else {
- // they changed this somewhere inbetween SCI1EGA/EARLY
- _usesNewKeyboardDirectionType = false;
-
- // We are looking if script 933 exists, that one has the PseudoMouse class in it that handles it
- // The good thing is that PseudoMouse seems to only exists in games that use the new method
- if (g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 933)))
- _usesNewKeyboardDirectionType = true;
- // Checking the keyboard driver size in here would also be a valid method, but the driver is only available
- // in PC versions of the game
- }
-}
-
-EventManager::~EventManager() {
-}
-
-bool EventManager::getUsesNewKeyboardDirectionType() {
- return _usesNewKeyboardDirectionType;
-}
-
struct ScancodeRow {
int offset;
const char *keys;
@@ -72,27 +47,6 @@ const ScancodeRow s_scancodeRows[] = {
{ 0x2c, "ZXCVBNM,./" }
};
-static int altify(int ch) {
- // Calculates a PC keyboard scancode from a character */
- int row;
- int c = toupper((char)ch);
-
- for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) {
- const char *keys = s_scancodeRows[row].keys;
- int offset = s_scancodeRows[row].offset;
-
- while (*keys) {
- if (*keys == c)
- return offset << 8;
-
- offset++;
- keys++;
- }
- }
-
- return ch;
-}
-
const byte codepagemap_88591toDOS[0x80] = {
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x9x
@@ -140,147 +94,182 @@ const SciKeyConversion keyMappings[] = {
{ Common::KEYCODE_KP_DIVIDE , '/' , '/' },
};
+struct MouseEventConversion {
+ Common::EventType commonType;
+ short sciType;
+ short data;
+};
+
+const MouseEventConversion mouseEventMappings[] = {
+ { Common::EVENT_LBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 1 },
+ { Common::EVENT_RBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 2 },
+ { Common::EVENT_MBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 3 },
+ { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 1 },
+ { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 2 },
+ { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 3 }
+};
+
+EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended) {
+}
+
+EventManager::~EventManager() {
+}
+
+static int altify(int ch) {
+ // Calculates a PC keyboard scancode from a character */
+ int row;
+ int c = toupper((char)ch);
+
+ for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) {
+ const char *keys = s_scancodeRows[row].keys;
+ int offset = s_scancodeRows[row].offset;
+
+ while (*keys) {
+ if (*keys == c)
+ return offset << 8;
+
+ offset++;
+ keys++;
+ }
+ }
+
+ return ch;
+}
+
SciEvent EventManager::getScummVMEvent() {
- SciEvent input = { SCI_EVENT_NONE, 0, 0, 0 };
+ SciEvent input = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) };
+ SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) };
Common::EventManager *em = g_system->getEventManager();
Common::Event ev;
bool found = em->pollEvent(ev);
- Common::Point p = ev.mouse;
// Don't generate events for mouse movement
- while (found && ev.type == Common::EVENT_MOUSEMOVE) {
+ while (found && ev.type == Common::EVENT_MOUSEMOVE)
found = em->pollEvent(ev);
- }
- if (found && ev.type != Common::EVENT_MOUSEMOVE) {
- int modifiers = em->getModifierState();
- bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);
-
- // We add the modifier key status to buckybits
- //TODO: SCI_EVM_INSERT
-
- input.modifiers =
- ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
- ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
- ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0) |
- ((ev.kbd.flags & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
- ((ev.kbd.flags & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |
- _modifierStates;
-
- switch (ev.type) {
- // Keyboard events
- case Common::EVENT_KEYDOWN:
- input.data = ev.kbd.keycode;
- input.character = ev.kbd.ascii;
-
- // Debug console
- if (ev.kbd.hasFlags(Common::KBD_CTRL) && ev.kbd.keycode == Common::KEYCODE_d) {
- // Open debug console
- Console *con = g_sci->getSciDebugger();
- con->attach();
-
- // Clear keyboard event
- input.type = SCI_EVENT_NONE;
- input.character = 0;
- input.data = 0;
- input.modifiers = 0;
-
- return input;
- }
+ // Save the mouse position
+ //
+ // We call getMousePos of the event manager here, since we also want to
+ // store the mouse position in case of keyboard events, which do not feature
+ // any mouse position information itself.
+ // This should be safe, since the mouse position in the event manager should
+ // only be updated when a mouse related event has been taken from the queue
+ // via pollEvent.
+ // We also adjust the position based on the scaling of the screen.
+ Common::Point mousePos = em->getMousePos();
+ g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
+
+ noEvent.mousePos = input.mousePos = mousePos;
+
+ if (!found || ev.type == Common::EVENT_MOUSEMOVE)
+ return noEvent;
+
+ if (ev.type == Common::EVENT_QUIT) {
+ input.type = SCI_EVENT_QUIT;
+ return input;
+ }
- if (!(input.data & 0xFF00)) {
- // Directly accept most common keys without conversion
- input.type = SCI_EVENT_KEYBOARD;
- if ((input.character >= 0x80) && (input.character <= 0xFF)) {
- // If there is no extended font, we will just clear the current event
- // Sierra SCI actually accepted those characters, but didn't display them inside textedit-controls
- // because the characters were missing inside the font(s)
- // We filter them out for non-multilingual games because of that
- if (!_fontIsExtended) {
- input.type = SCI_EVENT_NONE;
- input.character = 0;
- input.data = 0;
- input.modifiers = 0;
- return input;
- }
- // We get a 8859-1 character, we need dos (cp850/437) character for multilingual sci01 games
- input.character = codepagemap_88591toDOS[input.character & 0x7f];
- }
- if (input.data == Common::KEYCODE_TAB) {
- // Tab
- input.type = SCI_EVENT_KEYBOARD;
- input.data = SCI_KEY_TAB;
- if (input.modifiers & (SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT))
- input.character = SCI_KEY_SHIFT_TAB;
- else
- input.character = SCI_KEY_TAB;
- }
- if (input.data == Common::KEYCODE_DELETE) {
- // Delete key
- input.type = SCI_EVENT_KEYBOARD;
- input.data = input.character = SCI_KEY_DELETE;
- }
- } else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) {
- // F1-F10
- input.type = SCI_EVENT_KEYBOARD;
- // SCI_K_F1 == 59 << 8
- // SCI_K_SHIFT_F1 == 84 << 8
- input.data = SCI_KEY_F1 + ((input.data - Common::KEYCODE_F1)<<8);
- if (input.modifiers & (SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT))
- input.character = input.data + 0x1900;
- else
- input.character = input.data;
- } else {
- // Special keys that need conversion
- input.type = SCI_EVENT_KEYBOARD;
- for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
- if (keyMappings[i].scummVMKey == ev.kbd.keycode) {
- input.data = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
- break;
- }
- }
- input.character = input.data;
- }
- break;
+ // Handle mouse events
+ for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) {
+ if (mouseEventMappings[i].commonType == ev.type) {
+ input.type = mouseEventMappings[i].sciType;
+ input.data = mouseEventMappings[i].data;
+ return input;
+ }
+ }
- // Mouse events
- case Common::EVENT_LBUTTONDOWN:
- input.type = SCI_EVENT_MOUSE_PRESS;
- input.data = 1;
- break;
- case Common::EVENT_RBUTTONDOWN:
- input.type = SCI_EVENT_MOUSE_PRESS;
- input.data = 2;
- break;
- case Common::EVENT_MBUTTONDOWN:
- input.type = SCI_EVENT_MOUSE_PRESS;
- input.data = 3;
- break;
- case Common::EVENT_LBUTTONUP:
- input.type = SCI_EVENT_MOUSE_RELEASE;
- input.data = 1;
- break;
- case Common::EVENT_RBUTTONUP:
- input.type = SCI_EVENT_MOUSE_RELEASE;
- input.data = 2;
- break;
- case Common::EVENT_MBUTTONUP:
- input.type = SCI_EVENT_MOUSE_RELEASE;
- input.data = 3;
- break;
+ // If we reached here, make sure that it's a keydown event
+ if (ev.type != Common::EVENT_KEYDOWN)
+ return noEvent;
- // Misc events
- case Common::EVENT_QUIT:
- input.type = SCI_EVENT_QUIT;
- break;
+ // Check for Control-D (debug console)
+ if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) {
+ // Open debug console
+ Console *con = g_sci->getSciDebugger();
+ con->attach();
+ return noEvent;
+ }
- default:
- break;
+ // Process keyboard events
+
+ int modifiers = em->getModifierState();
+ bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);
+
+ input.data = ev.kbd.keycode;
+ input.character = ev.kbd.ascii;
+ input.type = SCI_EVENT_KEYBOARD;
+
+ input.modifiers =
+ ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
+ ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
+ ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);
+
+ // Caps lock and Scroll lock have been removed, cause we already handle upper
+ // case keys ad Scroll lock doesn't seem to be used anywhere
+ //((ev.kbd.flags & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
+ //((ev.kbd.flags & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |
+
+ if (!(input.data & 0xFF00)) {
+ // Directly accept most common keys without conversion
+ if ((input.character >= 0x80) && (input.character <= 0xFF)) {
+ // If there is no extended font, we will just clear the
+ // current event.
+ // Sierra SCI actually accepted those characters, but
+ // didn't display them inside text edit controls because
+ // the characters were missing inside the font(s).
+ // We filter them out for non-multilingual games because
+ // of that.
+ if (!_fontIsExtended)
+ return noEvent;
+ // Convert 8859-1 characters to DOS (cp850/437) for
+ // multilingual SCI01 games
+ input.character = codepagemap_88591toDOS[input.character & 0x7f];
+ }
+ if (input.data == Common::KEYCODE_TAB) {
+ input.character = input.data = SCI_KEY_TAB;
+ if (modifiers & Common::KBD_SHIFT)
+ input.character = SCI_KEY_SHIFT_TAB;
+ }
+ if (input.data == Common::KEYCODE_DELETE)
+ input.data = input.character = SCI_KEY_DELETE;
+ } else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) {
+ // SCI_K_F1 == 59 << 8
+ // SCI_K_SHIFT_F1 == 84 << 8
+ input.character = input.data = SCI_KEY_F1 + ((input.data - Common::KEYCODE_F1)<<8);
+ if (modifiers & Common::KBD_SHIFT)
+ input.character = input.data + 0x1900;
+ } else {
+ // Special keys that need conversion
+ for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
+ if (keyMappings[i].scummVMKey == ev.kbd.keycode) {
+ input.character = input.data = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
+ break;
+ }
}
}
+
+ // When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
+ // us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
+ // we support the other case as well
+ if ((modifiers & Common::KBD_SHIFT) && input.character > 0 && input.character < 27)
+ input.character += 96; // 0x01 -> 'a'
+
+ if (getSciVersion() <= SCI_VERSION_1_MIDDLE) {
+ // TODO: find out if altify is also not needed for sci1late+, couldnt find any game that uses those keys
+ // Scancodify if appropriate
+ if (modifiers & Common::KBD_ALT)
+ input.character = altify(input.character);
+ else if ((modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
+ input.character += 96; // 0x01 -> 'a'
+ }
+ // If no actual key was pressed (e.g. if only a modifier key was pressed),
+ // ignore the event
+ if (!input.character)
+ return noEvent;
+
return input;
}
@@ -302,8 +291,7 @@ void EventManager::updateScreen() {
}
SciEvent EventManager::getSciEvent(unsigned int mask) {
- //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 };
- SciEvent event = { 0, 0, 0, 0 };
+ SciEvent event = { 0, 0, 0, 0, Common::Point(0, 0) };
EventManager::updateScreen();
@@ -324,9 +312,8 @@ SciEvent EventManager::getSciEvent(unsigned int mask) {
event = *iter;
// If not peeking at the queue, remove the event
- if (!(mask & SCI_EVENT_PEEK)) {
+ if (!(mask & SCI_EVENT_PEEK))
_events.erase(iter);
- }
} else {
// No event found: we must return a SCI_EVT_NONE event.
@@ -334,29 +321,6 @@ SciEvent EventManager::getSciEvent(unsigned int mask) {
// there is no need to change it.
}
- if (event.type == SCI_EVENT_KEYBOARD) {
- // Do we still have to translate the key?
-
- // When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
- // us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
- // we support the other case as well
- if (event.modifiers & SCI_KEYMOD_ALT) {
- if (event.character < 27)
- event.character += 96; // 0x01 -> 'a'
- }
-
- if (getSciVersion() <= SCI_VERSION_1_MIDDLE) {
- // TODO: find out if altify is also not needed for sci1late+, couldnt find any game that uses those keys
- // Scancodify if appropriate
- if (event.modifiers & SCI_KEYMOD_ALT) {
- event.character = altify(event.character);
- } else if (event.modifiers & SCI_KEYMOD_CTRL) {
- if (event.character < 27)
- event.character += 96; // 0x01 -> 'a'
- }
- }
- }
-
return event;
}
diff --git a/engines/sci/event.h b/engines/sci/event.h
index fade7dd337..be0322f2a4 100644
--- a/engines/sci/event.h
+++ b/engines/sci/event.h
@@ -27,6 +27,7 @@
#define SCI_EVENT_H
#include "common/list.h"
+#include "common/rect.h"
namespace Sci {
@@ -46,6 +47,13 @@ struct SciEvent {
* PC keyboard scancodes.
*/
short character;
+
+ /**
+ * The mouse position at the time the event was created.
+ *
+ * These are display coordinates!
+ */
+ Common::Point mousePos;
};
/*Values for type*/
@@ -56,11 +64,8 @@ struct SciEvent {
#define SCI_EVENT_DIRECTION (1<<6)
#define SCI_EVENT_SAID (1<<7)
/*Fake values for other events*/
-#define SCI_EVENT_ERROR (1<<10)
#define SCI_EVENT_QUIT (1<<11)
#define SCI_EVENT_PEEK (1<<15)
-/* The QUIT event may be used to signal an external 'quit' command being
-** issued to the gfx driver. */
#define SCI_EVENT_ANY 0x7fff
/* Keycodes of special keys: */
@@ -116,16 +121,12 @@ public:
void updateScreen();
SciEvent getSciEvent(unsigned int mask);
- bool getUsesNewKeyboardDirectionType();
private:
SciEvent getScummVMEvent();
const bool _fontIsExtended;
- int _modifierStates;
Common::List<SciEvent> _events;
-
- bool _usesNewKeyboardDirectionType;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index 2e5e94c52a..d8f3fa09b0 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -27,6 +27,7 @@
#include "common/stack.h"
#include "graphics/primitives.h"
+#include "sci/console.h"
#include "sci/sci.h"
#include "sci/event.h"
#include "sci/engine/kernel.h"
@@ -191,11 +192,88 @@ void GfxAnimate::makeSortedList(List *list) {
Common::sort(_list.begin(), _list.end(), sortHelper);
}
-void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) {
- reg_t curObject = entry->object;
+void GfxAnimate::fill(byte &old_picNotValid) {
+ GfxView *view = NULL;
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
+
+ for (it = _list.begin(); it != end; ++it) {
+ // Get the corresponding view
+ view = _cache->getView(it->viewId);
+
+ adjustInvalidCels(view, it);
+ processViewScaling(view, it);
+ setNsRect(view, it);
+
+ //warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal);
+
+ // Calculate current priority according to y-coordinate
+ if (!(it->signal & kSignalFixedPriority)) {
+ it->priority = _ports->kernelCoordinateToPriority(it->y);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(priority), it->priority);
+ }
+
+ if (it->signal & kSignalNoUpdate) {
+ if ((it->signal & (kSignalForceUpdate | kSignalViewUpdated))
+ || (it->signal & kSignalHidden && !(it->signal & kSignalRemoveView))
+ || (!(it->signal & kSignalHidden) && it->signal & kSignalRemoveView)
+ || (it->signal & kSignalAlwaysUpdate))
+ old_picNotValid++;
+ it->signal &= ~kSignalStopUpdate;
+ } else {
+ if ((it->signal & kSignalStopUpdate) || (it->signal & kSignalAlwaysUpdate))
+ old_picNotValid++;
+ it->signal &= ~kSignalForceUpdate;
+ }
+ }
+}
+
+void GfxAnimate::adjustInvalidCels(GfxView *view, AnimateList::iterator it) {
+ // adjust loop and cel, if any of those is invalid
+ // this seems to be completely crazy code
+ // sierra sci checked signed int16 to be above or equal the counts and reseted to 0 in those cases
+ // later during view processing those are compared unsigned again and then set to maximum count - 1
+ // Games rely on this behaviour. For example laura bow 1 has a knight standing around in room 37
+ // which has cel set to 3. This cel does not exist and the actual knight is 0
+ // In kq5 on the other hand during the intro, when the trunk is opened, cel is set to some real
+ // high number, which is negative when considered signed. This actually requires to get fixed to
+ // maximum cel, otherwise the trunk would be closed.
+ int16 viewLoopCount = view->getLoopCount();
+ if (it->loopNo >= viewLoopCount) {
+ it->loopNo = 0;
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(loop), it->loopNo);
+ } else if (it->loopNo < 0) {
+ it->loopNo = viewLoopCount - 1;
+ // not setting selector is right, sierra sci didn't do it during view processing as well
+ }
+ int16 viewCelCount = view->getCelCount(it->loopNo);
+ if (it->celNo >= viewCelCount) {
+ it->celNo = 0;
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(cel), it->celNo);
+ } else if (it->celNo < 0) {
+ it->celNo = viewCelCount - 1;
+ }
+}
+
+void GfxAnimate::processViewScaling(GfxView *view, AnimateList::iterator it) {
+ if (!view->isScaleable()) {
+ // Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
+ // this "feature" was removed in later versions of SCI1.1
+ it->scaleSignal = 0;
+ it->scaleY = it->scaleX = 128;
+ } else {
+ // Process global scaling, if needed
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ if (it->scaleSignal & kScaleSignalGlobalScaling) {
+ applyGlobalScaling(it, view);
+ }
+ }
+ }
+}
+void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) {
// Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
- int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale));
+ int16 maxScale = readSelectorValue(_s->_segMan, entry->object, SELECTOR(maxScale));
int16 celHeight = view->getHeight(entry->loopNo, entry->celNo);
int16 maxCelHeight = (maxScale * celHeight) >> 7;
reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object
@@ -215,120 +293,43 @@ void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view)
entry->scaleX = entry->scaleY;
// and set objects scale selectors
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), entry->scaleX);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), entry->scaleY);
+ writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleX), entry->scaleX);
+ writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleY), entry->scaleY);
}
-void GfxAnimate::fill(byte &old_picNotValid) {
- reg_t curObject;
- uint16 signal;
- GfxView *view = NULL;
- AnimateList::iterator it;
- const AnimateList::iterator end = _list.end();
-
- for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- // Get the corresponding view
- view = _cache->getView(it->viewId);
-
- // adjust loop and cel, if any of those is invalid
- // this seems to be completely crazy code
- // sierra sci checked signed int16 to be above or equal the counts and reseted to 0 in those cases
- // later during view processing those are compared unsigned again and then set to maximum count - 1
- // Games rely on this behaviour. For example laura bow 1 has a knight standing around in room 37
- // which has cel set to 3. This cel does not exist and the actual knight is 0
- // In kq5 on the other hand during the intro, when the trunk is opened, cel is set to some real
- // high number, which is negative when considered signed. This actually requires to get fixed to
- // maximum cel, otherwise the trunk would be closed.
- int16 viewLoopCount = view->getLoopCount();
- if (it->loopNo >= viewLoopCount) {
- it->loopNo = 0;
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), it->loopNo);
- } else if (it->loopNo < 0) {
- it->loopNo = viewLoopCount - 1;
- // not setting selector is right, sierra sci didn't do it during view processing as well
- }
- int16 viewCelCount = view->getCelCount(it->loopNo);
- if (it->celNo >= viewCelCount) {
- it->celNo = 0;
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), it->celNo);
- } else if (it->celNo < 0) {
- it->celNo = viewCelCount - 1;
- }
-
- if (!view->isScaleable()) {
- // Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
- // this "feature" was removed in later versions of SCI1.1
- it->scaleSignal = 0;
- it->scaleY = it->scaleX = 128;
- } else {
- // Process global scaling, if needed
- if (it->scaleSignal & kScaleSignalDoScaling) {
- if (it->scaleSignal & kScaleSignalGlobalScaling) {
- applyGlobalScaling(it, view);
- }
- }
- }
-
- //warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal);
+void GfxAnimate::setNsRect(GfxView *view, AnimateList::iterator it) {
+ bool shouldSetNsRect = true;
- bool setNsRect = true;
-
- // Create rect according to coordinates and given cel
- if (it->scaleSignal & kScaleSignalDoScaling) {
- view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
- // when being scaled, only set nsRect, if object will get drawn
- if ((signal & kSignalHidden) && !(signal & kSignalAlwaysUpdate))
- setNsRect = false;
+ // Create rect according to coordinates and given cel
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
+ // when being scaled, only set nsRect, if object will get drawn
+ if ((it->signal & kSignalHidden) && !(it->signal & kSignalAlwaysUpdate))
+ shouldSetNsRect = false;
+ } else {
+ // This special handling is not included in the other SCI1.1 interpreters and MUST NOT be
+ // checked in those cases, otherwise we will break games (e.g. EcoQuest 2, room 200)
+ if ((g_sci->getGameId() == GID_HOYLE4) && (it->scaleSignal & kScaleSignalHoyle4SpecialHandling)) {
+ it->celRect.left = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsLeft));
+ it->celRect.top = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsTop));
+ it->celRect.right = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsRight));
+ it->celRect.bottom = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsBottom));
+ view->getCelSpecialHoyle4Rect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
+ shouldSetNsRect = false;
} else {
- // This special handling is not included in the other SCI1.1 interpreters and MUST NOT be
- // checked in those cases, otherwise we will break games (e.g. EcoQuest 2, room 200)
- if ((g_sci->getGameId() == GID_HOYLE4) && (it->scaleSignal & kScaleSignalHoyle4SpecialHandling)) {
- it->celRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft));
- it->celRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop));
- it->celRect.right = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight));
- it->celRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom));
- view->getCelSpecialHoyle4Rect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
- setNsRect = false;
- } else {
- view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
- }
- }
-
- if (setNsRect) {
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), it->celRect.right);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), it->celRect.bottom);
- }
-
- // Calculate current priority according to y-coordinate
- if (!(signal & kSignalFixedPriority)) {
- it->priority = _ports->kernelCoordinateToPriority(it->y);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), it->priority);
+ view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
}
+ }
- if (signal & kSignalNoUpdate) {
- if (signal & (kSignalForceUpdate | kSignalViewUpdated)
- || (signal & kSignalHidden && !(signal & kSignalRemoveView))
- || (!(signal & kSignalHidden) && signal & kSignalRemoveView)
- || (signal & kSignalAlwaysUpdate))
- old_picNotValid++;
- signal &= ~kSignalStopUpdate;
- } else {
- if (signal & kSignalStopUpdate || signal & kSignalAlwaysUpdate)
- old_picNotValid++;
- signal &= ~kSignalForceUpdate;
- }
- it->signal = signal;
+ if (shouldSetNsRect) {
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsBottom), it->celRect.bottom);
}
}
void GfxAnimate::update() {
- reg_t curObject;
- uint16 signal;
reg_t bitsHandle;
Common::Rect rect;
AnimateList::iterator it;
@@ -336,81 +337,66 @@ void GfxAnimate::update() {
// Remove all no-update cels, if requested
for (it = _list.reverse_begin(); it != end; --it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalNoUpdate) {
- if (!(signal & kSignalRemoveView)) {
- bitsHandle = readSelector(_s->_segMan, curObject, SELECTOR(underBits));
+ if (it->signal & kSignalNoUpdate) {
+ if (!(it->signal & kSignalRemoveView)) {
+ bitsHandle = readSelector(_s->_segMan, it->object, SELECTOR(underBits));
if (_screen->_picNotValid != 1) {
_paint16->bitsRestore(bitsHandle);
it->showBitsFlag = true;
} else {
_paint16->bitsFree(bitsHandle);
}
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0);
}
- signal &= ~kSignalForceUpdate;
- if (signal & kSignalViewUpdated)
- signal &= ~(kSignalViewUpdated | kSignalNoUpdate);
- } else if (signal & kSignalStopUpdate) {
- signal &= ~kSignalStopUpdate;
- signal |= kSignalNoUpdate;
+ it->signal &= ~kSignalForceUpdate;
+ if (it->signal & kSignalViewUpdated)
+ it->signal &= ~(kSignalViewUpdated | kSignalNoUpdate);
+ } else if (it->signal & kSignalStopUpdate) {
+ it->signal &= ~kSignalStopUpdate;
+ it->signal |= kSignalNoUpdate;
}
- it->signal = signal;
}
// Draw always-update cels
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalAlwaysUpdate) {
+ if (it->signal & kSignalAlwaysUpdate) {
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
it->showBitsFlag = true;
- signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate);
- if ((signal & kSignalIgnoreActor) == 0) {
+ it->signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate);
+ if (!(it->signal & kSignalIgnoreActor)) {
rect = it->celRect;
rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1);
_paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
- it->signal = signal;
}
}
// Saving background for all NoUpdate-cels
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalNoUpdate) {
- if (signal & kSignalHidden) {
- signal |= kSignalRemoveView;
+ if (it->signal & kSignalNoUpdate) {
+ if (it->signal & kSignalHidden) {
+ it->signal |= kSignalRemoveView;
} else {
- signal &= ~kSignalRemoveView;
- if (signal & kSignalIgnoreActor)
+ it->signal &= ~kSignalRemoveView;
+ if (it->signal & kSignalIgnoreActor)
bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY);
else
bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL);
- writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
+ writeSelector(_s->_segMan, it->object, SELECTOR(underBits), bitsHandle);
}
- it->signal = signal;
}
}
// Draw NoUpdate cels
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalNoUpdate && !(signal & kSignalHidden)) {
+ if (it->signal & kSignalNoUpdate && !(it->signal & kSignalHidden)) {
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
it->showBitsFlag = true;
- if (!(signal & kSignalIgnoreActor)) {
+ if (!(it->signal & kSignalIgnoreActor)) {
rect = it->celRect;
rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1);
_paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
@@ -420,30 +406,23 @@ void GfxAnimate::update() {
}
void GfxAnimate::drawCels() {
- reg_t curObject;
- uint16 signal;
reg_t bitsHandle;
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
_lastCastData.clear();
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (!(signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) {
+ if (!(it->signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) {
// Save background
bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL);
- writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
+ writeSelector(_s->_segMan, it->object, SELECTOR(underBits), bitsHandle);
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
it->showBitsFlag = true;
- if (signal & kSignalRemoveView) {
- signal &= ~kSignalRemoveView;
- }
- it->signal = signal;
+ if (it->signal & kSignalRemoveView)
+ it->signal &= ~kSignalRemoveView;
// Remember that entry in lastCast
_lastCastData.push_back(*it);
@@ -452,23 +431,18 @@ void GfxAnimate::drawCels() {
}
void GfxAnimate::updateScreen(byte oldPicNotValid) {
- reg_t curObject;
- uint16 signal;
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
Common::Rect lsRect;
Common::Rect workerRect;
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (it->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) ||
- (!(signal & kSignalRemoveView) && (signal & kSignalNoUpdate) && oldPicNotValid))) {
- lsRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft));
- lsRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop));
- lsRect.right = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight));
- lsRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom));
+ if (it->showBitsFlag || !(it->signal & (kSignalRemoveView | kSignalNoUpdate) ||
+ (!(it->signal & kSignalRemoveView) && (it->signal & kSignalNoUpdate) && oldPicNotValid))) {
+ lsRect.left = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft));
+ lsRect.top = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop));
+ lsRect.right = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight));
+ lsRect.bottom = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom));
workerRect = lsRect;
workerRect.clip(it->celRect);
@@ -480,17 +454,16 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) {
_paint16->bitsShow(lsRect);
workerRect = it->celRect;
}
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), it->celRect.left);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), it->celRect.top);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), it->celRect.right);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), it->celRect.bottom);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom), it->celRect.bottom);
// may get used for debugging
//_paint16->frameRect(workerRect);
_paint16->bitsShow(workerRect);
- if (signal & kSignalHidden) {
+ if (it->signal & kSignalHidden)
it->signal |= kSignalRemoveView;
- }
}
}
// use this for debug purposes
@@ -498,37 +471,30 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) {
}
void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) {
- reg_t curObject;
- uint16 signal;
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
-
// This has to be done in a separate loop. At least in sq1 some .dispose
// modifies FIXEDLOOP flag in signal for another object. In that case we
// would overwrite the new signal with our version of the old signal.
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
// Finally update signal
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(signal), it->signal);
}
for (it = _list.reverse_begin(); it != end; --it) {
- curObject = it->object;
// We read out signal here again, this is not by accident but to ensure
// that we got an up-to-date signal
- signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
+ it->signal = readSelectorValue(_s->_segMan, it->object, SELECTOR(signal));
- if ((signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
- _paint16->bitsRestore(readSelector(_s->_segMan, curObject, SELECTOR(underBits)));
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0);
+ if ((it->signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
+ _paint16->bitsRestore(readSelector(_s->_segMan, it->object, SELECTOR(underBits)));
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0);
}
- if (signal & kSignalDisposeMe) {
+ if (it->signal & kSignalDisposeMe) {
// Call .delete_ method of that object
- invokeSelector(_s, curObject, SELECTOR(delete_), argc, argv, 0);
+ invokeSelector(_s, it->object, SELECTOR(delete_), argc, argv, 0);
}
}
}
@@ -591,7 +557,7 @@ void GfxAnimate::addToPicDrawCels() {
// draw corresponding cel
_paint16->drawCel(view, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
- if ((it->signal & kSignalIgnoreActor) == 0) {
+ if (!(it->signal & kSignalIgnoreActor)) {
it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1);
_paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
@@ -665,10 +631,10 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
// beginUpdate()/endUpdate() were introduced SCI1.
// Calling those for SCI0 will work most of the time but breaks minor
// stuff like percentage bar of qfg1ega at the character skill screen.
- if (getSciVersion() >= SCI_VERSION_1_EGA)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
_ports->beginUpdate(_ports->_picWind);
update();
- if (getSciVersion() >= SCI_VERSION_1_EGA)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
_ports->endUpdate(_ports->_picWind);
}
@@ -687,6 +653,10 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
_ports->setPort(oldPort);
// Now trigger speed throttler
+ throttleSpeed();
+}
+
+void GfxAnimate::throttleSpeed() {
switch (_lastCastData.size()) {
case 0:
// No entries drawn -> no speed throttler triggering
@@ -759,4 +729,21 @@ void GfxAnimate::kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 ce
addToPicSetPicNotValid();
}
+void GfxAnimate::printAnimateList(Console *con) {
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
+
+ for (it = _list.begin(); it != end; ++it) {
+ Script *scr = _s->_segMan->getScriptIfLoaded(it->object.segment);
+ int16 scriptNo = scr ? scr->getScriptNumber() : -1;
+
+ con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, "
+ "at %d, %d, scale %d, %d / %d (z: %d, prio: %d, shown: %d, signal: %d)\n",
+ PRINT_REG(it->object), _s->_segMan->getObjectName(it->object),
+ scriptNo, it->viewId, it->loopNo, it->celNo, it->paletteNo,
+ it->x, it->y, it->scaleX, it->scaleY, it->scaleSignal,
+ it->z, it->priority, it->showBitsFlag, it->signal);
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h
index 44ffdd53af..b2aadcbead 100644
--- a/engines/sci/graphics/animate.h
+++ b/engines/sci/graphics/animate.h
@@ -77,6 +77,7 @@ struct AnimateEntry {
typedef Common::List<AnimateEntry> AnimateList;
typedef Common::Array<AnimateEntry> AnimateArray;
+class Console;
class GfxCache;
class GfxCursor;
class GfxPorts;
@@ -105,6 +106,7 @@ public:
void reAnimate(Common::Rect rect);
void addToPicDrawCels();
void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control);
+ void printAnimateList(Console *con);
virtual void kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv);
virtual void kernelAddToPicList(reg_t listReference, int argc, reg_t *argv);
@@ -115,6 +117,10 @@ private:
void addToPicSetPicNotValid();
void animateShowPic();
+ void throttleSpeed();
+ void adjustInvalidCels(GfxView *view, AnimateList::iterator it);
+ void processViewScaling(GfxView *view, AnimateList::iterator it);
+ void setNsRect(GfxView *view, AnimateList::iterator it);
EngineState *_s;
GfxCache *_cache;
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp
index 5f6aef0153..db926f2962 100644
--- a/engines/sci/graphics/compare.cpp
+++ b/engines/sci/graphics/compare.cpp
@@ -81,23 +81,14 @@ reg_t GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &
curObject = curNode->value;
if (curObject != checkObject) {
signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
- if ((signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate)) == 0) {
+ if (!(signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate))) {
curRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
curRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
curRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
curRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
// Check if curRect is within checkRect
- // TODO: This check is slightly odd, because it means that a rect is not contained
- // in itself. It may very well be that the original SCI engine did it just
- // this way, so it should not be changed lightly. However, somebody should
- // confirm whether the original engine really did it this way. Then, update
- // this comment accordingly, and, if necessary, fix the code.
- if (curRect.right > checkRect.left &&
- curRect.left < checkRect.right &&
- curRect.bottom > checkRect.top &&
- curRect.top < checkRect.bottom) {
+ if (checkRect.contains(curRect))
return curObject;
- }
}
}
curAddress = curNode->succ;
@@ -134,7 +125,7 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
#ifdef ENABLE_SCI32
if (view->isSci2Hires())
- _screen->adjustToUpscaledCoordinates(y, x);
+ view->adjustToUpscaledCoordinates(y, x);
else if (getSciVersion() == SCI_VERSION_2_1)
_coordAdjuster->fromScriptToDisplay(y, x);
#endif
@@ -143,8 +134,8 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
#ifdef ENABLE_SCI32
if (view->isSci2Hires()) {
- _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
- _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ view->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
} else if (getSciVersion() == SCI_VERSION_2_1) {
_coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
_coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
@@ -232,13 +223,13 @@ void GfxCompare::kernelBaseSetter(reg_t object) {
celRect.bottom = readSelectorValue(_segMan, object, SELECTOR(nsBottom));
} else {
if (tmpView->isSci2Hires())
- _screen->adjustToUpscaledCoordinates(y, x);
+ tmpView->adjustToUpscaledCoordinates(y, x);
tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);
if (tmpView->isSci2Hires()) {
- _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
- _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ tmpView->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ tmpView->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
}
}
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index e78d3e67cb..3b95a5c955 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -26,6 +26,7 @@
#include "common/config-manager.h"
#include "common/events.h"
#include "common/macresman.h"
+#include "common/memstream.h"
#include "common/system.h"
#include "common/util.h"
#include "graphics/cursorman.h"
@@ -38,6 +39,7 @@
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/view.h"
#include "sci/graphics/cursor.h"
+#include "sci/graphics/maciconbar.h"
namespace Sci {
@@ -434,9 +436,17 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
if (_macCursorRemap.empty()) {
// QFG1/Freddy/Hoyle4 use a straight viewNum->cursor ID mapping
- // KQ6 seems to use this mapping for its cursors
- if (g_sci->getGameId() == GID_KQ6)
- viewNum = loopNum * 1000 + celNum;
+ // KQ6 uses this mapping for its cursors
+ if (g_sci->getGameId() == GID_KQ6) {
+ if (viewNum == 990) // Inventory Cursors
+ viewNum = loopNum * 16 + celNum + 2000;
+ else if (viewNum == 998) // Regular Cursors
+ viewNum = celNum + 1000;
+ else // Unknown cursor, ignored
+ return;
+ }
+ if (g_sci->hasMacIconBar())
+ g_sci->_gfxMacIconBar->setInventoryIcon(viewNum);
} else {
// If we do have the list, we'll be using a remap based on what the
// scripts have given us.
@@ -485,10 +495,10 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
cursorBitmap[i * 8 + b] = 0; // Doesn't matter, just is transparent
}
- uint16 hotspotX = READ_BE_UINT16(data);
- uint16 hotspotY = READ_BE_UINT16(data + 2);
+ uint16 hotspotY = READ_BE_UINT16(data);
+ uint16 hotspotX = READ_BE_UINT16(data + 2);
- static const byte cursorPalette[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00 };
+ static const byte cursorPalette[] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff };
CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0);
CursorMan.replaceCursorPalette(cursorPalette, 1, 2);
@@ -498,11 +508,12 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
// Mac crsr cursor
byte *cursorBitmap, *palette;
int width, height, hotspotX, hotspotY, palSize, keycolor;
- Common::MacResManager::convertCrsrCursor(resource->data, resource->size, &cursorBitmap, &width, &height, &hotspotX, &hotspotY, &keycolor, true, &palette, &palSize);
+ Common::MemoryReadStream resStream(resource->data, resource->size);
+ Common::MacResManager::convertCrsrCursor(&resStream, &cursorBitmap, width, height, hotspotX, hotspotY, keycolor, true, &palette, palSize);
CursorMan.replaceCursor(cursorBitmap, width, height, hotspotX, hotspotY, keycolor);
CursorMan.replaceCursorPalette(palette, 0, palSize);
- free(cursorBitmap);
- free(palette);
+ delete[] cursorBitmap;
+ delete[] palette;
}
kernelShow();
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 5b690f289a..dd55b3b060 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -58,6 +58,12 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd
GfxFrameout::~GfxFrameout() {
}
+void GfxFrameout::clear() {
+ _screenItems.clear();
+ _planes.clear();
+ _planePictures.clear();
+}
+
void GfxFrameout::kernelAddPlane(reg_t object) {
PlaneEntry newPlane;
@@ -77,10 +83,12 @@ void GfxFrameout::kernelAddPlane(reg_t object) {
}
newPlane.object = object;
- newPlane.pictureId = 0xFFFF;
newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority));
newPlane.lastPriority = 0xFFFF; // hidden
newPlane.planeOffsetX = 0;
+ newPlane.pictureId = 0xFFFF;
+ newPlane.planePictureMirrored = false;
+ newPlane.planeBack = 0;
_planes.push_back(newPlane);
kernelUpdatePlane(object);
@@ -117,7 +125,10 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) {
if (it->planeRect.left < 0) {
it->planeOffsetX = -it->planeRect.left;
it->planeRect.left = 0;
+ } else {
+ it->planeOffsetX = 0;
}
+
if (it->planeRect.top < 0)
it->planeRect.top = 0;
// We get bad plane-bottom in sq6
@@ -331,6 +342,8 @@ static int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font) {
maxChars = curCharCount; // return count up to (but not including) breaking space
break;
}
+ if (width + font->getCharWidth(curChar) > maxWidth)
+ break;
width += font->getCharWidth(curChar);
curCharCount++;
}
@@ -479,8 +492,8 @@ void GfxFrameout::kernelFrameout() {
if (view->isSci2Hires()) {
int16 dummyX = 0;
- _screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
- _screen->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
+ view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
+ view->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
} else if (getSciVersion() == SCI_VERSION_2_1) {
itemEntry->y = (itemEntry->y * _screen->getHeight()) / scriptsRunningHeight;
itemEntry->x = (itemEntry->x * _screen->getWidth()) / scriptsRunningWidth;
@@ -497,8 +510,8 @@ void GfxFrameout::kernelFrameout() {
itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1;
itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1;
if (view->isSci2Hires()) {
- _screen->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
- _screen->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
+ view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
+ view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
}
itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
// TODO: maybe we should clip the cels rect with this, i'm not sure
@@ -514,8 +527,8 @@ void GfxFrameout::kernelFrameout() {
nsRect.translate(it->planeOffsetX, 0);
if (view->isSci2Hires()) {
- _screen->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
- _screen->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
+ view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
+ view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
} else if (getSciVersion() == SCI_VERSION_2_1) {
nsRect.top = (nsRect.top * scriptsRunningHeight) / _screen->getHeight();
nsRect.left = (nsRect.left * scriptsRunningWidth) / _screen->getWidth();
@@ -584,6 +597,11 @@ void GfxFrameout::kernelFrameout() {
uint16 startX = itemEntry->x + it->planeRect.left;
uint16 curY = itemEntry->y + it->planeRect.top;
const char *txt = text.c_str();
+ // HACK. The plane sometimes doesn't contain the correct width. This
+ // hack breaks the dialog options when speaking with Grace, but it's
+ // the best we got up to now. This happens because of the unimplemented
+ // kTextWidth function in SCI32.
+ // TODO: Remove this once kTextWidth has been implemented.
uint16 w = it->planeRect.width() >= 20 ? it->planeRect.width() : _screen->getWidth() - 10;
int16 charCount;
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index 93d61ba22e..347ecb9424 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -28,6 +28,8 @@
namespace Sci {
+class GfxPicture;
+
struct PlaneEntry {
reg_t object;
uint16 priority;
@@ -99,6 +101,7 @@ public:
void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX);
void deletePlanePictures(reg_t object);
+ void clear();
private:
SegManager *_segMan;
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index f6cb214a2b..343f3c7e6e 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -45,6 +45,10 @@ typedef int GuiResourceId; // is a resource-number and -1 means no parameter giv
typedef int16 TextAlignment;
+#define PORTS_FIRSTWINDOWID 2
+#define PORTS_FIRSTSCRIPTWINDOWID 3
+
+
struct Port {
uint16 id;
int16 top, left;
@@ -62,6 +66,8 @@ struct Port {
fontHeight(0), fontId(0), greyedOutput(false),
penClr(0), backClr(0xFF), penMode(0), counterTillFree(0) {
}
+
+ bool isWindow() const { return id >= PORTS_FIRSTWINDOWID && id != 0xFFFF; }
};
struct Window : public Port, public Common::Serializable {
@@ -132,12 +138,14 @@ struct PalSchedule {
uint32 schedule;
};
+// Game view types, sorted by the number of colors
enum ViewType {
- kViewUnknown,
- kViewEga,
- kViewVga,
- kViewVga11,
- kViewAmiga
+ kViewUnknown, // uninitialized, or non-SCI
+ kViewEga, // EGA SCI0/SCI1 and Amiga SCI0/SCI1 ECS 16 colors
+ kViewAmiga, // Amiga SCI1 ECS 32 colors
+ kViewAmiga64, // Amiga SCI1 AGA 64 colors (i.e. Longbow)
+ kViewVga, // VGA SCI1 256 colors
+ kViewVga11 // VGA SCI1.1 and newer 256 colors
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index 2ce17ab531..6cf4f269a7 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -27,8 +27,10 @@
#include "sci/engine/kernel.h"
#include "sci/engine/selector.h"
#include "sci/engine/state.h"
+#include "sci/event.h"
#include "sci/graphics/maciconbar.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/screen.h"
#include "common/memstream.h"
#include "common/system.h"
@@ -37,37 +39,189 @@
namespace Sci {
+GfxMacIconBar::GfxMacIconBar() {
+ _lastX = 0;
+
+ if (g_sci->getGameId() == GID_FREDDYPHARKAS)
+ _inventoryIndex = 5;
+ else
+ _inventoryIndex = 4;
+
+ _inventoryIcon = 0;
+ _allDisabled = true;
+}
+
+GfxMacIconBar::~GfxMacIconBar() {
+ if (_inventoryIcon) {
+ _inventoryIcon->free();
+ delete _inventoryIcon;
+ }
+
+ for (uint32 i = 0; i < _iconBarItems.size(); i++) {
+ if (_iconBarItems[i].nonSelectedImage) {
+ _iconBarItems[i].nonSelectedImage->free();
+ delete _iconBarItems[i].nonSelectedImage;
+ }
+
+ if (_iconBarItems[i].selectedImage) {
+ _iconBarItems[i].selectedImage->free();
+ delete _iconBarItems[i].selectedImage;
+ }
+ }
+}
+
void GfxMacIconBar::addIcon(reg_t obj) {
- _iconBarObjects.push_back(obj);
+ IconBarItem item;
+ uint32 iconIndex = readSelectorValue(g_sci->getEngineState()->_segMan, obj, SELECTOR(iconIndex));
+
+ item.object = obj;
+ item.nonSelectedImage = createImage(iconIndex, false);
+
+ if (iconIndex != _inventoryIndex)
+ item.selectedImage = createImage(iconIndex, true);
+ else
+ item.selectedImage = 0;
+
+ item.enabled = true;
+
+ // Start after the main viewing window and add a two pixel buffer
+ uint16 y = g_sci->_gfxScreen->getHeight() + 2;
+
+ if (item.nonSelectedImage)
+ item.rect = Common::Rect(_lastX, y, MIN<uint32>(_lastX + item.nonSelectedImage->w, 320), y + item.nonSelectedImage->h);
+ else
+ error("Could not find a non-selected image for icon %d", iconIndex);
+
+ _lastX += item.rect.width();
+
+ _iconBarItems.push_back(item);
}
void GfxMacIconBar::drawIcons() {
// Draw the icons to the bottom of the screen
- byte *pal = new byte[256 * 4];
- Graphics::PictDecoder *pict = new Graphics::PictDecoder(Graphics::PixelFormat::createFormatCLUT8());
- uint32 lastX = 0;
+ for (uint32 i = 0; i < _iconBarItems.size(); i++)
+ drawIcon(i, false);
+}
+
+void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) {
+ if (iconIndex >= _iconBarItems.size())
+ return;
+
+ Common::Rect rect = _iconBarItems[iconIndex].rect;
+
+ if (isIconEnabled(iconIndex)) {
+ if (selected)
+ drawEnabledImage(_iconBarItems[iconIndex].selectedImage, rect);
+ else
+ drawEnabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
+ } else
+ drawDisabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
+
+ if ((iconIndex == _inventoryIndex) && _inventoryIcon) {
+ Common::Rect invRect = Common::Rect(0, 0, _inventoryIcon->w, _inventoryIcon->h);
+ invRect.moveTo(rect.left, rect.top);
+ invRect.translate((rect.width() - invRect.width()) / 2, (rect.height() - invRect.height()) / 2);
+
+ if (isIconEnabled(iconIndex))
+ drawEnabledImage(_inventoryIcon, invRect);
+ else
+ drawDisabledImage(_inventoryIcon, invRect);
+ }
+}
+
+void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
+ if (surface)
+ g_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height());
+}
+
+void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
+ if (!surface)
+ return;
+
+ // Add a black checkboard pattern to the image before copying it to the screen
+
+ Graphics::Surface newSurf;
+ newSurf.copyFrom(*surface);
+
+ for (int i = 0; i < newSurf.h; i++) {
+ // Start at the next four byte boundary
+ int startX = 3 - ((rect.left + 3) & 3);
+
+ // Start odd rows at two bytes past that (also properly aligned)
+ if ((i + rect.top) & 1)
+ startX = (startX + 2) & 3;
+
+ for (int j = startX; j < newSurf.w; j += 4)
+ *((byte *)newSurf.getBasePtr(j, i)) = 0;
+ }
+
+ g_system->copyRectToScreen((byte *)newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height());
+ newSurf.free();
+}
+
+void GfxMacIconBar::drawSelectedImage(uint16 iconIndex) {
+ assert(iconIndex <= _iconBarItems.size());
+
+ drawEnabledImage(_iconBarItems[iconIndex].selectedImage, _iconBarItems[iconIndex].rect);
+}
- for (uint32 i = 0; i < _iconBarObjects.size(); i++) {
- uint32 iconIndex = readSelectorValue(g_sci->getEngineState()->_segMan, _iconBarObjects[i], SELECTOR(iconIndex));
- Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMacIconBarPictN, iconIndex + 1), false);
- if (!res)
- continue;
+bool GfxMacIconBar::isIconEnabled(uint16 iconIndex) const {
+ if (iconIndex >= _iconBarItems.size())
+ return false;
+
+ return !_allDisabled && _iconBarItems[iconIndex].enabled;
+}
+
+void GfxMacIconBar::setIconEnabled(int16 iconIndex, bool enabled) {
+ if (iconIndex < 0)
+ _allDisabled = !enabled;
+ else if (iconIndex < (int)_iconBarItems.size()) {
+ _iconBarItems[iconIndex].enabled = enabled;
+ }
+}
- Common::SeekableReadStream *stream = new Common::MemoryReadStream(res->data, res->size);
- Graphics::Surface *surf = pict->decodeImage(stream, pal);
- remapColors(surf, pal);
+void GfxMacIconBar::setInventoryIcon(int16 icon) {
+ Graphics::Surface *surface = 0;
- g_system->copyRectToScreen((byte *)surf->pixels, surf->pitch, lastX, 200, MIN<uint32>(surf->w, 320 - lastX), surf->h);
+ if (icon >= 0)
+ surface = loadPict(ResourceId(kResourceTypeMacPict, icon));
- lastX += surf->w;
- surf->free();
- delete surf;
- delete stream;
+ if (_inventoryIcon) {
+ // Free old inventory icon if we're removing the inventory icon
+ // or setting a new one.
+ if ((icon < 0) || surface) {
+ _inventoryIcon->free();
+ delete _inventoryIcon;
+ _inventoryIcon = 0;
+ }
}
- delete pict;
- delete[] pal;
+ if (surface)
+ _inventoryIcon = surface;
+
+ drawIcon(_inventoryIndex, false);
+}
+
+Graphics::Surface *GfxMacIconBar::loadPict(ResourceId id) {
+ Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8());
+ Resource *res = g_sci->getResMan()->findResource(id, false);
+
+ if (!res || res->size == 0)
+ return 0;
+
+ byte palette[256 * 3];
+ Common::SeekableReadStream *stream = new Common::MemoryReadStream(res->data, res->size);
+ Graphics::Surface *surface = pictDecoder.decodeImage(stream, palette);
+ remapColors(surface, palette);
+
+ delete stream;
+ return surface;
+}
+
+Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) {
+ ResourceType type = isSelected ? kResourceTypeMacIconBarPictS : kResourceTypeMacIconBarPictN;
+ return loadPict(ResourceId(type, iconIndex + 1));
}
void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
@@ -77,16 +231,67 @@ void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
for (uint16 i = 0; i < surf->w * surf->h; i++) {
byte color = *pixels;
- byte r = palette[color * 4];
- byte g = palette[color * 4 + 1];
- byte b = palette[color * 4 + 2];
+ byte r = palette[color * 3];
+ byte g = palette[color * 3 + 1];
+ byte b = palette[color * 3 + 2];
- // For black, make sure the index is 0
- if (r == 0 && g == 0 && b == 0)
- *pixels++ = 0;
- else
- *pixels++ = g_sci->_gfxPalette->kernelFindColor(r, g, b);
+ *pixels++ = g_sci->_gfxPalette->findMacIconBarColor(r, g, b);
+ }
+}
+
+bool GfxMacIconBar::pointOnIcon(uint32 iconIndex, Common::Point point) {
+ return _iconBarItems[iconIndex].rect.contains(point);
+}
+
+reg_t GfxMacIconBar::handleEvents() {
+ // Peek event queue for a mouse button press
+ EventManager *evtMgr = g_sci->getEventManager();
+ SciEvent evt = evtMgr->getSciEvent(SCI_EVENT_MOUSE_PRESS | SCI_EVENT_PEEK);
+
+ // No mouse press found
+ if (evt.type == SCI_EVENT_NONE)
+ return NULL_REG;
+
+ // If the mouse is not over the icon bar, return
+ if (evt.mousePos.y < g_sci->_gfxScreen->getHeight())
+ return NULL_REG;
+
+ // Remove event from queue
+ evtMgr->getSciEvent(SCI_EVENT_MOUSE_PRESS);
+
+ // Mouse press on the icon bar, check the icon rectangles
+ uint iconNr;
+ for (iconNr = 0; iconNr < _iconBarItems.size(); iconNr++) {
+ if (pointOnIcon(iconNr, evt.mousePos) && isIconEnabled(iconNr))
+ break;
}
+
+ // Mouse press not on an icon
+ if (iconNr == _iconBarItems.size())
+ return NULL_REG;
+
+ drawIcon(iconNr, true);
+ bool isSelected = true;
+
+ // Wait for mouse release
+ while (evt.type != SCI_EVENT_MOUSE_RELEASE) {
+ // Mimic behavior of SSCI when moving mouse with button held down
+ if (isSelected != pointOnIcon(iconNr, evt.mousePos)) {
+ isSelected = !isSelected;
+ drawIcon(iconNr, isSelected);
+ }
+
+ evt = evtMgr->getSciEvent(SCI_EVENT_MOUSE_RELEASE);
+ g_system->delayMillis(10);
+ }
+
+ drawIcon(iconNr, false);
+
+ // If user moved away from the icon, we do nothing
+ if (pointOnIcon(iconNr, evt.mousePos))
+ return _iconBarItems[iconNr].object;
+
+ return NULL_REG;
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/maciconbar.h b/engines/sci/graphics/maciconbar.h
index 71e65fcb40..3ac5475147 100644
--- a/engines/sci/graphics/maciconbar.h
+++ b/engines/sci/graphics/maciconbar.h
@@ -38,16 +38,40 @@ namespace Sci {
class GfxMacIconBar {
public:
- GfxMacIconBar() {}
- ~GfxMacIconBar() {}
+ GfxMacIconBar();
+ ~GfxMacIconBar();
void addIcon(reg_t obj);
void drawIcons();
+ void setIconEnabled(int16 index, bool enabled);
+ void setInventoryIcon(int16 icon);
+ reg_t handleEvents();
private:
- Common::Array<reg_t> _iconBarObjects;
+ struct IconBarItem {
+ reg_t object;
+ Graphics::Surface *nonSelectedImage;
+ Graphics::Surface *selectedImage;
+ Common::Rect rect;
+ bool enabled;
+ };
+ Common::Array<IconBarItem> _iconBarItems;
+ uint32 _lastX;
+ uint16 _inventoryIndex;
+ Graphics::Surface *_inventoryIcon;
+ bool _allDisabled;
+
+ Graphics::Surface *loadPict(ResourceId id);
+ Graphics::Surface *createImage(uint32 iconIndex, bool isSelected);
void remapColors(Graphics::Surface *surf, byte *palette);
+
+ void drawIcon(uint16 index, bool selected);
+ void drawSelectedImage(uint16 index);
+ bool isIconEnabled(uint16 index) const;
+ void drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect);
+ void drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect);
+ bool pointOnIcon(uint32 iconIndex, Common::Point point);
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp
index 3b9119c52f..50ba77e832 100644
--- a/engines/sci/graphics/menu.cpp
+++ b/engines/sci/graphics/menu.cpp
@@ -399,12 +399,10 @@ void GfxMenu::calculateMenuAndItemWidth() {
reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
int16 eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type));
int16 keyPress, keyModifier;
- Common::Point mousePosition;
GuiMenuItemList::iterator itemIterator = _itemList.begin();
GuiMenuItemList::iterator itemEnd = _itemList.end();
GuiMenuItemEntry *itemEntry = NULL;
bool forceClaimed = false;
- EngineState *s;
switch (eventType) {
case SCI_EVENT_KEYBOARD:
@@ -438,8 +436,6 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
break;
case SCI_EVENT_SAID:
- // HACK: should be removed as soon as said() is cleaned up
- s = g_sci->getEngineState();
while (itemIterator != itemEnd) {
itemEntry = *itemIterator;
@@ -451,7 +447,7 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
continue;
}
- if (said(s, saidSpec, 0) != SAID_NO_MATCH)
+ if (said(saidSpec, 0) != SAID_NO_MATCH)
break;
}
itemIterator++;
@@ -460,15 +456,17 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
itemEntry = NULL;
break;
- case SCI_EVENT_MOUSE_PRESS:
- mousePosition = _cursor->getPosition();
+ case SCI_EVENT_MOUSE_PRESS: {
+ Common::Point mousePosition;
+ mousePosition.x = readSelectorValue(_segMan, eventObject, SELECTOR(x));
+ mousePosition.y = readSelectorValue(_segMan, eventObject, SELECTOR(y));
if (mousePosition.y < 10) {
interactiveStart(pauseSound);
itemEntry = interactiveWithMouse();
interactiveEnd(pauseSound);
forceClaimed = true;
}
- break;
+ } break;
}
if (!_menuSaveHandle.isNull()) {
@@ -718,7 +716,6 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
uint16 newItemId = _curItemId;
GuiMenuItemEntry *curItemEntry = findItem(_curMenuId, _curItemId);
GuiMenuItemEntry *newItemEntry = curItemEntry;
- Common::Point mousePosition;
// We don't 100% follow Sierra here: we select last item instead of
// selecting first item of first menu every time. Also sierra sci didn't
@@ -796,9 +793,9 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
}
break;
- case SCI_EVENT_MOUSE_PRESS:
- mousePosition = _cursor->getPosition();
- if (_cursor->getPosition().y < 10) {
+ case SCI_EVENT_MOUSE_PRESS: {
+ Common::Point mousePosition = curEvent.mousePos;
+ if (mousePosition.y < 10) {
// Somewhere on the menubar
newMenuId = mouseFindMenuSelection(mousePosition);
if (newMenuId) {
@@ -827,7 +824,8 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
}
newItemId = curItemEntry->id;
}
- break;
+ } break;
+
case SCI_EVENT_NONE:
g_sci->sleep(2500 / 1000);
break;
@@ -843,7 +841,6 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
SciEvent curEvent;
uint16 newMenuId = 0, newItemId = 0;
uint16 curMenuId = 0, curItemId = 0;
- Common::Point mousePosition = _cursor->getPosition();
bool firstMenuChange = true;
GuiMenuItemEntry *curItemEntry = NULL;
@@ -874,7 +871,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
}
// Find out where mouse is currently pointing to
- mousePosition = _cursor->getPosition();
+ Common::Point mousePosition = curEvent.mousePos;
if (mousePosition.y < 10) {
// Somewhere on the menubar
newMenuId = mouseFindMenuSelection(mousePosition);
@@ -914,6 +911,13 @@ void GfxMenu::kernelDrawStatus(const char *text, int16 colorPen, int16 colorBack
_ports->moveTo(0, 1);
_text16->DrawStatus(text);
_paint16->bitsShow(_ports->_menuBarRect);
+ // Also draw the line under the status bar. Normally, this is never drawn,
+ // but we need it to be drawn because Dr. Brain 1 Mac draws over it when
+ // it displays the icon bar. SSCI used negative rectangles to erase the
+ // area after drawing the icon bar, but this is a much cleaner way of
+ // achieving the same effect.
+ _paint16->fillRect(_ports->_menuLine, 1, 0);
+ _paint16->bitsShow(_ports->_menuLine);
_ports->setPort(oldPort);
}
diff --git a/engines/sci/graphics/paint.cpp b/engines/sci/graphics/paint.cpp
index 50b0534ba7..c347da3c0f 100644
--- a/engines/sci/graphics/paint.cpp
+++ b/engines/sci/graphics/paint.cpp
@@ -43,9 +43,6 @@ GfxPaint::~GfxPaint() {
void GfxPaint::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) {
}
-void GfxPaint::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) {
-}
-
void GfxPaint::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) {
}
diff --git a/engines/sci/graphics/paint.h b/engines/sci/graphics/paint.h
index 994bc4e5e9..a79e8993c2 100644
--- a/engines/sci/graphics/paint.h
+++ b/engines/sci/graphics/paint.h
@@ -36,7 +36,6 @@ public:
virtual ~GfxPaint();
virtual void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo);
- virtual void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
virtual void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
};
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index 0bb3fc85c5..ff738fc3b9 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -121,11 +121,10 @@ void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common:
Common::Rect clipRectTranslated = clipRect;
_ports->offsetRect(clipRectTranslated);
- if (scaleX == 128 && scaleY == 128) {
+ if (scaleX == 128 && scaleY == 128)
view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, false);
- } else {
+ else
view->drawScaled(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, scaleX, scaleY);
- }
}
// This is used as replacement for drawCelAndShow() when hires-cels are drawn to
@@ -160,8 +159,8 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c
// adjust curPort to upscaled hires
clipRect = celRect;
curPortRect = _ports->_curPort->rect;
- _screen->adjustToUpscaledCoordinates(curPortRect.top, curPortRect.left);
- _screen->adjustToUpscaledCoordinates(curPortRect.bottom, curPortRect.right);
+ view->adjustToUpscaledCoordinates(curPortRect.top, curPortRect.left);
+ view->adjustToUpscaledCoordinates(curPortRect.bottom, curPortRect.right);
curPortRect.bottom++;
curPortRect.right++;
clipRect.clip(curPortRect);
@@ -171,7 +170,7 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c
clipRectTranslated = clipRect;
if (!upscaledHiresHack) {
curPortPos.x = _ports->_curPort->left; curPortPos.y = _ports->_curPort->top;
- _screen->adjustToUpscaledCoordinates(curPortPos.y, curPortPos.x);
+ view->adjustToUpscaledCoordinates(curPortPos.y, curPortPos.x);
clipRectTranslated.top += curPortPos.y; clipRectTranslated.bottom += curPortPos.y;
clipRectTranslated.left += curPortPos.x; clipRectTranslated.right += curPortPos.x;
}
@@ -278,9 +277,8 @@ void GfxPaint16::fillRect(const Common::Rect &rect, int16 drawFlags, byte color,
}
void GfxPaint16::frameRect(const Common::Rect &rect) {
- Common::Rect r;
+ Common::Rect r = rect;
// left
- r = rect;
r.right = rect.left + 1;
paintRect(r);
// right
@@ -362,7 +360,7 @@ void GfxPaint16::bitsRestore(reg_t memoryHandle) {
if (memoryPtr) {
_screen->bitsRestore(memoryPtr);
- _segMan->freeHunkEntry(memoryHandle);
+ bitsFree(memoryHandle);
}
}
}
@@ -534,20 +532,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
case SCI_DISPLAY_RESTOREUNDER:
bitsGetRect(argv[0], &rect);
rect.translate(-_ports->getPort()->left, -_ports->getPort()->top);
- if (g_sci->getGameId() == GID_PQ3 && g_sci->getEngineState()->currentRoomNumber() == 29) {
- // WORKAROUND: PQ3 calls this without calling the associated
- // kDisplay(SCI_DISPLAY_SAVEUNDER) call before. Theoretically,
- // this would result in no rect getting restored. However, we
- // still maintain a pointer from the previous room, resulting
- // in invalidated content being restored on screen, and causing
- // graphics glitches. Thus, we simply don't restore a rect in
- // that room. The correct fix for this would be to erase hunk
- // pointers when changing rooms, but this will suffice for now,
- // as restoring from a totally invalid pointer is very rare.
- // Fixes bug #3037945.
- } else {
- bitsRestore(argv[0]);
- }
+ bitsRestore(argv[0]);
kernelGraphRedrawBox(rect);
// finishing loop
argc = 0;
@@ -583,7 +568,10 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
// now drawing the text
_text16->Size(rect, text, -1, width);
rect.moveTo(_ports->getPort()->curLeft, _ports->getPort()->curTop);
- if (getSciVersion() >= SCI_VERSION_1_LATE) {
+ // Note: This code has been found in SCI1 middle and newer games. It was
+ // previously only for SCI1 late and newer, but the LSL1 interpreter contains
+ // this code.
+ if (getSciVersion() >= SCI_VERSION_1_MIDDLE) {
int16 leftPos = rect.right <= _screen->getWidth() ? 0 : _screen->getWidth() - rect.right;
int16 topPos = rect.bottom <= _screen->getHeight() ? 0 : _screen->getHeight() - rect.bottom;
_ports->move(leftPos, topPos);
diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h
index 4f709fd7c6..69ddf09ea6 100644
--- a/engines/sci/graphics/paint16.h
+++ b/engines/sci/graphics/paint16.h
@@ -36,7 +36,6 @@ class GfxPorts;
class GfxScreen;
class GfxPalette;
class Font;
-class SciGuiPicture;
class GfxView;
/**
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index aa3bf8dfb3..69a278eb8b 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -65,17 +65,6 @@ void GfxPaint32::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, b
delete picture;
}
-// This is "hacked" together, because its only used by debug command
-void GfxPaint32::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) {
- GfxView *view = _cache->getView(viewId);
- Common::Rect celRect(50, 50, 50, 50);
- Common::Rect translatedRect;
- celRect.bottom += view->getHeight(loopNo, celNo);
- celRect.right += view->getWidth(loopNo, celNo);
- view->draw(celRect, celRect, celRect, loopNo, celNo, 255, 0, false);
- _screen->copyRectToScreen(celRect);
-}
-
void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) {
_screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control);
}
diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h
index 3fa9d11d9b..e412bdf1c4 100644
--- a/engines/sci/graphics/paint32.h
+++ b/engines/sci/graphics/paint32.h
@@ -45,7 +45,6 @@ public:
void fillRect(Common::Rect rect, byte color);
void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo);
- void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
private:
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index b27b5f35a7..0433479a09 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -69,16 +69,39 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMergi
_useMerging = useMerging;
palVaryInit();
+
+ _macClut = 0;
+ loadMacIconBarPalette();
#ifdef ENABLE_SCI32
_clutTable = 0;
#endif
+
+ switch (_resMan->getViewType()) {
+ case kViewEga:
+ _totalScreenColors = 16;
+ break;
+ case kViewAmiga:
+ _totalScreenColors = 32;
+ break;
+ case kViewAmiga64:
+ _totalScreenColors = 64;
+ break;
+ case kViewVga:
+ case kViewVga11:
+ _totalScreenColors = 256;
+ break;
+ default:
+ error("GfxPalette: Unknown view type");
+ }
}
GfxPalette::~GfxPalette() {
if (_palVaryResourceId != -1)
palVaryRemoveTimer();
+ delete[] _macClut;
+
#ifdef ENABLE_SCI32
unloadClut();
#endif
@@ -92,7 +115,7 @@ bool GfxPalette::isMerging() {
void GfxPalette::setDefault() {
if (_resMan->getViewType() == kViewEga)
setEGA();
- else if (_resMan->isAmiga32color())
+ else if (_resMan->getViewType() == kViewAmiga)
setAmiga();
else
kernelSetFromResource(999, true);
@@ -171,39 +194,42 @@ void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut)
// Will try to set amiga palette by using "spal" file. If not found, we return false
bool GfxPalette::setAmiga() {
Common::File file;
- int curColor, byte1, byte2;
if (file.open("spal")) {
- for (curColor = 0; curColor < 32; curColor++) {
- byte1 = file.readByte();
- byte2 = file.readByte();
- if ((byte1 == EOF) || (byte2 == EOF))
+ for (int curColor = 0; curColor < 32; curColor++) {
+ byte byte1 = file.readByte();
+ byte byte2 = file.readByte();
+
+ if (file.eos())
error("Amiga palette file ends prematurely");
+
_sysPalette.colors[curColor].used = 1;
_sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11;
_sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11;
_sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11;
}
- file.close();
+
// Directly set the palette, because setOnScreen() wont do a thing for amiga
- _screen->setPalette(&_sysPalette);
+ copySysPaletteToScreen();
return true;
}
+
return false;
}
// Called from picture class, some amiga sci1 games set half of the palette
void GfxPalette::modifyAmigaPalette(byte *data) {
- int16 curColor, curPos = 0;
- byte byte1, byte2;
- for (curColor = 0; curColor < 16; curColor++) {
- byte1 = data[curPos++];
- byte2 = data[curPos++];
+ int16 curPos = 0;
+
+ for (int curColor = 0; curColor < 16; curColor++) {
+ byte byte1 = data[curPos++];
+ byte byte2 = data[curPos++];
_sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11;
_sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11;
_sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11;
}
- _screen->setPalette(&_sysPalette);
+
+ copySysPaletteToScreen();
}
static byte blendColors(byte c1, byte c2) {
@@ -297,19 +323,20 @@ bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) {
newPalette->mapping[i] = i;
}
}
+
// We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls
return paletteChanged;
}
bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
uint16 res;
- int i,j;
bool paletteChanged = false;
- // colors 0 (black) and 255 (white) are not affected by merging
- for (i = 1; i < 255; i++) {
- if (!newPalette->colors[i].used)// color is not used - so skip it
+ for (int i = 1; i < 255; i++) {
+ // skip unused colors
+ if (!newPalette->colors[i].used)
continue;
+
// forced palette merging or dest color is not used yet
if (force || (!_sysPalette.colors[i].used)) {
_sysPalette.colors[i].used = newPalette->colors[i].used;
@@ -322,6 +349,7 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
newPalette->mapping[i] = i;
continue;
}
+
// is the same color already at the same position? -> match it directly w/o lookup
// this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would
// otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes)
@@ -329,14 +357,18 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
newPalette->mapping[i] = i;
continue;
}
+
// check if exact color could be matched
res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b);
if (res & 0x8000) { // exact match was found
newPalette->mapping[i] = res & 0xFF;
continue;
}
+
+ int j = 1;
+
// no exact match - see if there is an unused color
- for (j = 1; j < 256; j++)
+ for (; j < 256; j++) {
if (!_sysPalette.colors[j].used) {
_sysPalette.colors[j].used = newPalette->colors[i].used;
_sysPalette.colors[j].r = newPalette->colors[i].r;
@@ -346,6 +378,8 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
paletteChanged = true;
break;
}
+ }
+
// if still no luck - set an approximate color
if (j == 256) {
newPalette->mapping[i] = res & 0xFF;
@@ -355,6 +389,7 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
if (!forceRealMerge)
_sysPalette.timestamp = g_system->getMillis() * 60 / 1000;
+
return paletteChanged;
}
@@ -401,14 +436,35 @@ void GfxPalette::getSys(Palette *pal) {
}
void GfxPalette::setOnScreen() {
- // We dont change palette at all times for amiga
- if (_resMan->isAmiga32color())
- return;
- _screen->setPalette(&_sysPalette);
+ copySysPaletteToScreen();
+}
+
+static byte convertMacGammaToSCIGamma(int comp) {
+ return (byte)sqrt(comp * 255.0f);
+}
- // Redraw the Mac SCI1.1 Icon bar every palette change
- if (g_sci->_gfxMacIconBar)
- g_sci->_gfxMacIconBar->drawIcons();
+void GfxPalette::copySysPaletteToScreen() {
+ // just copy palette to system
+ byte bpal[3 * 256];
+
+ // Get current palette, update it and put back
+ g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
+
+ for (int16 i = 0; i < 256; i++) {
+ if (colorIsFromMacClut(i)) {
+ // If we've got a Mac CLUT, override the SCI palette with its non-black colors
+ bpal[i * 3 ] = convertMacGammaToSCIGamma(_macClut[i * 3 ]);
+ bpal[i * 3 + 1] = convertMacGammaToSCIGamma(_macClut[i * 3 + 1]);
+ bpal[i * 3 + 2] = convertMacGammaToSCIGamma(_macClut[i * 3 + 2]);
+ } else if (_sysPalette.colors[i].used != 0) {
+ // Otherwise, copy to the screen
+ bpal[i * 3 ] = CLIP(_sysPalette.colors[i].r * _sysPalette.intensity[i] / 100, 0, 255);
+ bpal[i * 3 + 1] = CLIP(_sysPalette.colors[i].g * _sysPalette.intensity[i] / 100, 0, 255);
+ bpal[i * 3 + 2] = CLIP(_sysPalette.colors[i].b * _sysPalette.intensity[i] / 100, 0, 255);
+ }
+ }
+
+ g_system->getPaletteManager()->setPalette(bpal, 0, 256);
}
bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) {
@@ -420,6 +476,7 @@ bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) {
set(&palette, force);
return true;
}
+
return false;
}
@@ -565,7 +622,16 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) {
}
void GfxPalette::kernelSyncScreenPalette() {
- _screen->getPalette(&_sysPalette);
+ // just copy palette to system
+ byte bpal[3 * 256];
+
+ // Get current palette, update it and put back
+ g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
+ for (int16 i = 1; i < 255; i++) {
+ _sysPalette.colors[i].r = bpal[i * 3];
+ _sysPalette.colors[i].g = bpal[i * 3 + 1];
+ _sysPalette.colors[i].b = bpal[i * 3 + 2];
+ }
}
// palVary
@@ -795,6 +861,87 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) {
}
}
+static inline uint getMacColorDiff(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) {
+ // Use the difference of the top 4 bits and add together the differences
+ return ABS((r2 & 0xf0) - (r1 & 0xf0)) + ABS((g2 & 0xf0) - (g1 & 0xf0)) + ABS((b2 & 0xf0) - (b1 & 0xf0));
+}
+
+byte GfxPalette::findMacIconBarColor(byte r, byte g, byte b) {
+ // Find the best color for use with the Mac icon bar
+ // Check white, then the palette colors, and then black
+
+ // Try white first
+ byte found = 0xff;
+ uint diff = getMacColorDiff(r, g, b, 0xff, 0xff, 0xff);
+
+ if (diff == 0)
+ return found;
+
+ // Go through the main colors of the CLUT
+ for (uint16 i = 1; i < 255; i++) {
+ if (!colorIsFromMacClut(i))
+ continue;
+
+ uint cdiff = getMacColorDiff(r, g, b, _macClut[i * 3], _macClut[i * 3 + 1], _macClut[i * 3 + 2]);
+
+ if (cdiff == 0)
+ return i;
+ else if (cdiff < diff) {
+ found = i;
+ diff = cdiff;
+ }
+ }
+
+ // Also check black here
+ if (getMacColorDiff(r, g, b, 0, 0, 0) < diff)
+ return 0;
+
+ return found;
+}
+
+void GfxPalette::loadMacIconBarPalette() {
+ if (!g_sci->hasMacIconBar())
+ return;
+
+ Common::SeekableReadStream *clutStream = g_sci->getMacExecutable()->getResource(MKTAG('c','l','u','t'), 150);
+
+ if (!clutStream)
+ error("Could not find clut 150 for the Mac icon bar");
+
+ clutStream->readUint32BE(); // seed
+ clutStream->readUint16BE(); // flags
+ uint16 colorCount = clutStream->readUint16BE() + 1;
+ assert(colorCount == 256);
+
+ _macClut = new byte[256 * 3];
+
+ for (uint16 i = 0; i < colorCount; i++) {
+ clutStream->readUint16BE();
+ _macClut[i * 3 ] = clutStream->readUint16BE() >> 8;
+ _macClut[i * 3 + 1] = clutStream->readUint16BE() >> 8;
+ _macClut[i * 3 + 2] = clutStream->readUint16BE() >> 8;
+ }
+
+ // Adjust bounds on the KQ6 palette
+ // We don't use all of it for the icon bar
+ if (g_sci->getGameId() == GID_KQ6)
+ memset(_macClut + 32 * 3, 0, (256 - 32) * 3);
+
+ // Force black/white
+ _macClut[0x00 * 3 ] = 0;
+ _macClut[0x00 * 3 + 1] = 0;
+ _macClut[0x00 * 3 + 2] = 0;
+ _macClut[0xff * 3 ] = 0xff;
+ _macClut[0xff * 3 + 1] = 0xff;
+ _macClut[0xff * 3 + 2] = 0xff;
+
+ delete clutStream;
+}
+
+bool GfxPalette::colorIsFromMacClut(byte index) {
+ return index != 0 && _macClut && (_macClut[index * 3] != 0 || _macClut[index * 3 + 1] != 0 || _macClut[index * 3 + 1] != 0);
+}
+
#ifdef ENABLE_SCI32
bool GfxPalette::loadClut(uint16 clutId) {
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 84334a4a61..d2e5151d6a 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -54,8 +54,10 @@ public:
bool merge(Palette *pFrom, bool force, bool forceRealMerge);
uint16 matchColor(byte r, byte g, byte b);
void getSys(Palette *pal);
+ uint16 getTotalColorCount() const { return _totalScreenColors; }
void setOnScreen();
+ void copySysPaletteToScreen();
void drewPicture(GuiResourceId pictureId);
@@ -88,6 +90,9 @@ public:
virtual void saveLoadWithSerializer(Common::Serializer &s);
void palVarySaveLoadPalette(Common::Serializer &s, Palette *palette);
+ byte findMacIconBarColor(byte r, byte g, byte b);
+ bool colorIsFromMacClut(byte index);
+
#ifdef ENABLE_SCI32
bool loadClut(uint16 clutId);
byte matchClutColor(uint16 color);
@@ -119,6 +124,10 @@ private:
uint16 _palVaryTicks;
int _palVaryPaused;
int _palVarySignal;
+ uint16 _totalScreenColors;
+
+ void loadMacIconBarPalette();
+ byte *_macClut;
#ifdef ENABLE_SCI32
byte *_clutTable;
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index 7e71c1a258..82aae5399f 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -36,6 +36,8 @@
namespace Sci {
+//#define DEBUG_PICTURE_DRAW
+
GfxPicture::GfxPicture(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize)
: _resMan(resMan), _coordAdjuster(coordAdjuster), _ports(ports), _screen(screen), _palette(palette), _resourceId(resourceId), _EGAdrawingVisualize(EGAdrawingVisualize) {
assert(resourceId != -1);
@@ -222,19 +224,20 @@ void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictu
}
#endif
+extern void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData);
+
void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX) {
byte *celBitmap = NULL;
byte *ptr = NULL;
byte *headerPtr = inbuffer + headerPos;
byte *rlePtr = inbuffer + rlePos;
- byte *literalPtr = inbuffer + literalPos;
int16 displaceX, displaceY;
byte priority = _addToFlag ? _priority : 0;
byte clearColor;
bool compression = true;
- byte curByte, runLength;
+ byte curByte;
int16 y, lastY, x, leftX, rightX;
- int pixelNr, pixelCount;
+ int pixelCount;
uint16 width, height;
#ifdef ENABLE_SCI32
@@ -245,12 +248,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
height = READ_LE_UINT16(headerPtr + 2);
displaceX = (signed char)headerPtr[4];
displaceY = (unsigned char)headerPtr[5];
- if (_resourceType == SCI_PICTURE_TYPE_SCI11) {
+ if (_resourceType == SCI_PICTURE_TYPE_SCI11)
// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
clearColor = _screen->getColorWhite();
- } else {
+ else
clearColor = headerPtr[6];
- }
#ifdef ENABLE_SCI32
} else {
width = READ_SCI11ENDIAN_UINT16(headerPtr + 0);
@@ -266,90 +268,37 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
if (displaceX || displaceY)
error("unsupported embedded cel-data in picture");
+ // We will unpack cel-data into a temporary buffer and then plot it to screen
+ // That needs to be done cause a mirrored picture may be requested
pixelCount = width * height;
celBitmap = new byte[pixelCount];
if (!celBitmap)
error("Unable to allocate temporary memory for picture drawing");
- if (compression) {
- // We will unpack cel-data into a temporary buffer and then plot it to screen
- // That needs to be done cause a mirrored picture may be requested
- memset(celBitmap, clearColor, pixelCount);
- pixelNr = 0;
- ptr = celBitmap;
- if (literalPos == 0) {
- // decompression for data that has only one stream (vecor embedded view data)
- switch (_resMan->getViewType()) {
- case kViewEga:
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- runLength = curByte >> 4;
- memset(ptr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
- pixelNr += runLength;
- }
- break;
- case kViewVga:
- case kViewVga11:
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- runLength = curByte & 0x3F;
- switch (curByte & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNr < pixelCount)
- ptr[pixelNr++] = *rlePtr++;
- break;
- case 0x80: // fill with color
- memset(ptr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
- pixelNr += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNr += runLength;
- break;
- }
- }
- break;
- case kViewAmiga:
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- if (curByte & 0x07) { // fill with color
- runLength = curByte & 0x07;
- curByte = curByte >> 3;
- while (runLength-- && pixelNr < pixelCount) {
- ptr[pixelNr++] = curByte;
- }
- } else { // fill with transparent
- runLength = curByte >> 3;
- pixelNr += runLength;
- }
- }
- break;
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
+ // See GfxView::unpackCel() for why this black/white swap is done
+ // This picture swap is only needed in SCI32, not SCI1.1
+ if (clearColor == 0)
+ clearColor = 0xff;
+ else if (clearColor == 0xff)
+ clearColor = 0;
+ }
- default:
- error("Unsupported picture viewtype");
- }
- } else {
- // decompression for data that has two separate streams (probably SCI 1.1 picture)
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- runLength = curByte & 0x3F;
- switch (curByte & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNr < pixelCount)
- ptr[pixelNr++] = *literalPtr++;
- break;
- case 0x80: // fill with color
- memset(ptr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
- pixelNr += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNr += runLength;
- break;
- }
- }
- }
- } else {
+ if (compression)
+ unpackCelData(inbuffer, celBitmap, clearColor, pixelCount, rlePos, literalPos, _resMan->getViewType(), width, false);
+ else
// No compression (some SCI32 pictures)
memcpy(celBitmap, rlePtr, pixelCount);
+
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
+ // See GfxView::unpackCel() for why this black/white swap is done
+ // This picture swap is only needed in SCI32, not SCI1.1
+ for (int i = 0; i < pixelCount; i++) {
+ if (celBitmap[i] == 0)
+ celBitmap[i] = 0xff;
+ else if (celBitmap[i] == 0xff)
+ celBitmap[i] = 0;
+ }
}
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
@@ -377,10 +326,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
sourcePixelSkipPerRow = width - (rightX - leftX);
// Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
- // but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all)
- // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
- // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra
- if (!_addToFlag)
+ // but white and that won't matter because the screen is supposed to be already white. It seems that most (if not all)
+ // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
+ // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra.
+ // SCI32 doesn't use _addToFlag at all.
+ if (!_addToFlag && _resourceType != SCI_PICTURE_TYPE_SCI32)
clearColor = _screen->getColorWhite();
byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;
@@ -443,6 +393,7 @@ enum {
PIC_OP_OPX = 0xfe,
PIC_OP_TERMINATE = 0xff
};
+
#define PIC_OP_FIRST PIC_OP_SET_COLOR
enum {
@@ -465,6 +416,47 @@ enum {
PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT = 4
};
+#ifdef DEBUG_PICTURE_DRAW
+const char *picOpcodeNames[] = {
+ "Set color",
+ "Disable visual",
+ "Set priority",
+ "Disable priority",
+ "Short patterns",
+ "Medium lines",
+ "Long lines",
+ "Short lines",
+ "Fill",
+ "Set pattern",
+ "Absolute pattern",
+ "Set control",
+ "Disable control",
+ "Medium patterns",
+ "Extended opcode",
+ "Terminate"
+};
+
+const char *picExOpcodeNamesEGA[] = {
+ "Set palette entries",
+ "Set palette",
+ "Mono0",
+ "Mono1",
+ "Mono2",
+ "Mono3",
+ "Mono4",
+ "Embedded view",
+ "Set priority table"
+};
+
+const char *picExOpcodeNamesVGA[] = {
+ "Set palette entries",
+ "Embedded view",
+ "Set palette",
+ "Set priority table (eqdist)",
+ "Set priority table (explicit)"
+};
+#endif
+
#define PIC_EGAPALETTE_COUNT 4
#define PIC_EGAPALETTE_SIZE 40
#define PIC_EGAPALETTE_TOTALSIZE PIC_EGAPALETTE_COUNT*PIC_EGAPALETTE_SIZE
@@ -543,7 +535,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
// Drawing
while (curPos < dataSize) {
- //warning("%X at %d", data[curPos], curPos);
+#ifdef DEBUG_PICTURE_DRAW
+ debug("Picture op: %X (%s) at %d", data[curPos], picOpcodeNames[data[curPos] - 0xF0], curPos);
+#endif
switch (pic_op = data[curPos++]) {
case PIC_OP_SET_COLOR:
pic_color = data[curPos++];
@@ -681,6 +675,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
case PIC_OP_OPX: // Extended functions
if (isEGA) {
+#ifdef DEBUG_PICTURE_DRAW
+ debug("* Picture ex op: %X (%s) at %d", data[curPos], picExOpcodeNamesEGA[data[curPos]], curPos);
+#endif
switch (pic_op = data[curPos++]) {
case PIC_OPX_EGA_SET_PALETTE_ENTRIES:
while (vectorIsNonOpcode(data[curPos])) {
@@ -726,6 +723,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
error("Unsupported sci1 extended pic-operation %X", pic_op);
}
} else {
+#ifdef DEBUG_PICTURE_DRAW
+ debug("* Picture ex op: %X (%s) at %d", data[curPos], picExOpcodeNamesVGA[data[curPos]], curPos);
+#endif
switch (pic_op = data[curPos++]) {
case PIC_OPX_VGA_SET_PALETTE_ENTRIES:
while (vectorIsNonOpcode(data[curPos])) {
@@ -733,7 +733,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
}
break;
case PIC_OPX_VGA_SET_PALETTE:
- if (_resMan->isAmiga32color()) {
+ if (_resMan->getViewType() == kViewAmiga || _resMan->getViewType() == kViewAmiga64) {
if ((data[curPos] == 0x00) && (data[curPos + 1] == 0x01) && ((data[curPos + 32] & 0xF0) != 0xF0)) {
// Left-Over VGA palette, we simply ignore it
curPos += 256 + 4 + 1024;
@@ -780,7 +780,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
case GID_SQ3:
switch (_resourceId) {
case 154: // SQ3: intro, ship gets sucked in
- _screen->ditherForceMemorial(0xD0);
+ _screen->ditherForceDitheredColor(0xD0);
break;
default:
break;
@@ -866,6 +866,8 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
byte matchedMask, matchMask;
int16 w, e, a_set, b_set;
+ bool isEGA = (_resMan->getViewType() == kViewEga);
+
p.x = x + curPort->left;
p.y = y + curPort->top;
stack.push(p);
@@ -874,6 +876,18 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
byte searchPriority = _screen->getPriority(p.x, p.y);
byte searchControl = _screen->getControl(p.x, p.y);
+ if (isEGA) {
+ // In EGA games a pixel in the framebuffer is only 4 bits. We store
+ // a full byte per pixel to allow undithering, but when comparing
+ // pixels for flood-fill purposes, we should only compare the
+ // visible color of a pixel.
+
+ if ((x ^ y) & 1)
+ searchColor = (searchColor ^ (searchColor >> 4)) & 0x0F;
+ else
+ searchColor = searchColor & 0x0F;
+ }
+
// This logic was taken directly from sierra sci, floodfill will get aborted on various occations
if (screenMask & GFX_SCREEN_MASK_VISUAL) {
if ((color == _screen->getColorWhite()) || (searchColor != _screen->getColorWhite()))
@@ -913,20 +927,20 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
int b = curPort->rect.bottom + curPort->top - 1;
while (stack.size()) {
p = stack.pop();
- if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl)) == 0) // already filled
+ if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled
continue;
_screen->putPixel(p.x, p.y, screenMask, color, priority, control);
w = p.x;
e = p.x;
// moving west and east pointers as long as there is a matching color to fill
- while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
+ while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
_screen->putPixel(--w, p.y, screenMask, color, priority, control);
- while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
+ while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
_screen->putPixel(++e, p.y, screenMask, color, priority, control);
// checking lines above and below for possible flood targets
a_set = b_set = 0;
while (w <= e) {
- if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl))) { // one line above
+ if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above
if (a_set == 0) {
p1.x = w;
p1.y = p.y - 1;
@@ -936,7 +950,7 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
} else
a_set = 0;
- if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl))) { // one line below
+ if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below
if (b_set == 0) {
p1.x = w;
p1.y = p.y + 1;
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 87f0c3d6a2..cc206bd5b9 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -25,8 +25,10 @@
#include "common/util.h"
+#include "sci/console.h"
#include "sci/sci.h"
#include "sci/engine/features.h"
+#include "sci/engine/gc.h"
#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
@@ -106,7 +108,10 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
offTop = 26;
break;
default:
- offTop = 10;
+ // For Mac games running with a height of 190, we do not have a menu bar
+ // so the top offset should be 0.
+ if (_screen->getHeight() == 190)
+ offTop = 0;
break;
}
@@ -243,8 +248,10 @@ void GfxPorts::beginUpdate(Window *wnd) {
PortList::iterator it = _windowList.reverse_begin();
const PortList::iterator end = Common::find(_windowList.begin(), _windowList.end(), wnd);
while (it != end) {
- // FIXME: We also store Port objects in the window list.
- // We should add a check that we really only pass windows here...
+ // We also store Port objects in the window list, but they
+ // shouldn't be encountered during this iteration.
+ assert((*it)->isWindow());
+
updateWindow((Window *)*it);
--it;
}
@@ -260,11 +267,16 @@ void GfxPorts::endUpdate(Window *wnd) {
assert(it != end);
while (++it != end) {
- // FIXME: We also store Port objects in the window list.
- // We should add a check that we really only pass windows here...
+ // We also store Port objects in the window list, but they
+ // shouldn't be encountered during this iteration.
+ assert((*it)->isWindow());
+
updateWindow((Window *)*it);
}
+ if (getSciVersion() < SCI_VERSION_1_EGA_ONLY)
+ g_sci->_gfxPaint16->kernelGraphRedrawBox(_curPort->rect);
+
setPort(oldPort);
}
@@ -297,7 +309,14 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
}
_windowsById[id] = pwnd;
- if (style & SCI_WINDOWMGR_STYLE_TOPMOST)
+
+ // KQ1sci, KQ4, iceman, QfG2 always add windows to the back of the list.
+ // KQ5CD checks style.
+ // Hoyle3-demo also always adds to the back (#3036763).
+ bool forceToBack = (getSciVersion() <= SCI_VERSION_1_EGA_ONLY) ||
+ (g_sci->getGameId() == GID_HOYLE3 && g_sci->isDemo());
+
+ if (!forceToBack && (style & SCI_WINDOWMGR_STYLE_TOPMOST))
_windowList.push_front(pwnd);
else
_windowList.push_back(pwnd);
@@ -308,7 +327,7 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
// bit of the left dimension in their interpreter. It seems Sierra did it
// for EGA byte alignment (EGA uses 1 byte for 2 pixels) and left it in
// their interpreter even in the newer VGA games.
- r.left = r.left & 0x7FFE;
+ r.left = r.left & 0xFFFE;
if (r.width() > _screen->getWidth()) {
// We get invalid dimensions at least at the end of sq3 (script bug!).
@@ -344,25 +363,50 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
}
pwnd->dims = r;
- const Common::Rect *wmprect = &_wmgrPort->rect;
+
+ // Clip window, if needed
+ Common::Rect wmprect = _wmgrPort->rect;
+ // Handle a special case for Dr. Brain 1 Mac. When hovering the mouse cursor
+ // over the status line on top, the game scripts try to draw the game's icon
+ // bar above the current port, by specifying a negative window top, so that
+ // the end result will be drawn 10 pixels above the current port. This is a
+ // hack by Sierra, and is only limited to user style windows. Normally, we
+ // should not clip, same as what Sierra does. However, this will result in
+ // having invalid rectangles with negative coordinates. For this reason, we
+ // adjust the containing rectangle instead.
+ if (pwnd->dims.top < 0 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
+ (style & SCI_WINDOWMGR_STYLE_USER) && _wmgrPort->top + pwnd->dims.top >= 0) {
+ // Offset the final rect top by the requested pixels
+ wmprect.top += pwnd->dims.top;
+ }
+
int16 oldtop = pwnd->dims.top;
int16 oldleft = pwnd->dims.left;
- if (wmprect->top > pwnd->dims.top)
- pwnd->dims.moveTo(pwnd->dims.left, wmprect->top);
- if (wmprect->bottom < pwnd->dims.bottom)
- pwnd->dims.moveTo(pwnd->dims.left, wmprect->bottom - pwnd->dims.bottom + pwnd->dims.top);
+ if (wmprect.top > pwnd->dims.top)
+ pwnd->dims.moveTo(pwnd->dims.left, wmprect.top);
+
+ if (wmprect.bottom < pwnd->dims.bottom)
+ pwnd->dims.moveTo(pwnd->dims.left, wmprect.bottom - pwnd->dims.bottom + pwnd->dims.top);
- if (wmprect->right < pwnd->dims.right)
- pwnd->dims.moveTo(wmprect->right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top);
+ if (wmprect.right < pwnd->dims.right)
+ pwnd->dims.moveTo(wmprect.right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top);
- if (wmprect->left > pwnd->dims.left)
- pwnd->dims.moveTo(wmprect->left, pwnd->dims.top);
+ if (wmprect.left > pwnd->dims.left)
+ pwnd->dims.moveTo(wmprect.left, pwnd->dims.top);
pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop);
+
if (restoreRect == 0)
pwnd->restoreRect = pwnd->dims;
+ if (pwnd->restoreRect.top < 0 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
+ (style & SCI_WINDOWMGR_STYLE_USER) && _wmgrPort->top + pwnd->restoreRect.top >= 0) {
+ // Special case for Dr. Brain 1 Mac (check above), applied to the
+ // restore rectangle.
+ pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.top);
+ }
+
if (draw)
drawWindow(pwnd);
setPort((Port *)pwnd);
@@ -575,10 +619,6 @@ void GfxPorts::priorityBandsInit(int16 bandCount, int16 top, int16 bottom) {
int16 y;
int32 bandSize;
- // This code is for 320x200 games only
- if (_screen->getHeight() != 200)
- return;
-
if (bandCount != -1)
_priorityBandCount = bandCount;
@@ -669,4 +709,26 @@ int16 GfxPorts::kernelPriorityToCoordinate(byte priority) {
return _priorityBottom;
}
+void GfxPorts::processEngineHunkList(WorklistManager &wm) {
+ for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) {
+ if ((*it)->isWindow()) {
+ Window *wnd = ((Window *)*it);
+ wm.push(wnd->hSaved1);
+ wm.push(wnd->hSaved2);
+ }
+ }
+}
+
+void GfxPorts::printWindowList(Console *con) {
+ for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) {
+ if ((*it)->isWindow()) {
+ Window *wnd = ((Window *)*it);
+ con->DebugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n",
+ wnd->id, wnd->title.c_str(), wnd->left, wnd->top,
+ wnd->rect.left, wnd->rect.top, wnd->rect.right, wnd->rect.bottom,
+ wnd->bDrawn, wnd->wndStyle);
+ }
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h
index 21c6d31ebd..31ed671daf 100644
--- a/engines/sci/graphics/ports.h
+++ b/engines/sci/graphics/ports.h
@@ -32,13 +32,10 @@
namespace Sci {
-class SciGui;
class GfxPaint16;
class GfxScreen;
class GfxText16;
-
-#define PORTS_FIRSTWINDOWID 2
-#define PORTS_FIRSTSCRIPTWINDOWID 3
+struct WorklistManager;
// window styles
enum {
@@ -49,6 +46,9 @@ enum {
SCI_WINDOWMGR_STYLE_USER = (1 << 7)
};
+typedef Common::List<Port *> PortList;
+typedef Common::Array<Port *> PortArray;
+
/**
* Ports class, includes all port managment for SCI0->SCI1.1 games. Ports are some sort of windows in SCI
* this class also handles adjusting coordinates to a specific port
@@ -103,6 +103,8 @@ public:
void kernelGraphAdjustPriority(int top, int bottom);
byte kernelCoordinateToPriority(int16 y);
int16 kernelPriorityToCoordinate(byte priority);
+ void processEngineHunkList(WorklistManager &wm);
+ void printWindowList(Console *con);
Port *_wmgrPort;
Window *_picWind;
@@ -116,7 +118,11 @@ public:
virtual void saveLoadWithSerializer(Common::Serializer &ser);
private:
- typedef Common::List<Port *> PortList;
+ /** The list of open 'windows' (and ports), in visual order. */
+ PortList _windowList;
+
+ /** The list of all open 'windows' (and ports), ordered by their id. */
+ PortArray _windowsById;
SegManager *_segMan;
GfxPaint16 *_paint16;
@@ -130,12 +136,6 @@ private:
// counts windows that got disposed but are not freed yet
uint16 _freeCounter;
- /** The list of open 'windows' (and ports), in visual order. */
- PortList _windowList;
-
- /** The list of all open 'windows' (and ports), ordered by their id. */
- Common::Array<Port *> _windowsById;
-
Common::Rect _bounds;
// Priority Bands related variables
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 896ac0db22..32f54c7e23 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -32,6 +32,7 @@
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/graphics/screen.h"
+#include "sci/graphics/view.h"
namespace Sci {
@@ -64,7 +65,7 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_height = 480;
} else {
_width = 320;
- _height = 200;
+ _height = getLowResScreenHeight();
}
// Japanese versions of games use hi-res font on upscaled version of the game.
@@ -113,7 +114,7 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_unditherState = true;
_fontIsUpscaled = false;
- if (_resMan->isVGA() || (_resMan->isAmiga32color())) {
+ if (_resMan->getViewType() != kViewEga) {
// It is not 100% accurate to set white to be 255 for Amiga 32-color
// games. But 255 is defined as white in our SCI at all times, so it
// doesn't matter.
@@ -132,10 +133,12 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
if (g_sci->hasMacIconBar()) {
// For SCI1.1 Mac games with the custom icon bar, we need to expand the screen
// to accommodate for the icon bar. Of course, both KQ6 and QFG1 VGA differ in size.
+ // We add 2 to the height of the icon bar to add a buffer between the screen and the
+ // icon bar (as did the original interpreter).
if (g_sci->getGameId() == GID_KQ6)
- initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320);
+ initGraphics(_displayWidth, _displayHeight + 26 + 2, _displayWidth > 320);
else if (g_sci->getGameId() == GID_FREDDYPHARKAS)
- initGraphics(_displayWidth, _displayHeight + 28, _displayWidth > 320);
+ initGraphics(_displayWidth, _displayHeight + 28 + 2, _displayWidth > 320);
else
error("Unknown SCI1.1 Mac game");
} else
@@ -154,12 +157,14 @@ void GfxScreen::copyToScreen() {
}
void GfxScreen::copyFromScreen(byte *buffer) {
+ // TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
memcpy(buffer, screen->pixels, _displayPixels);
g_system->unlockScreen();
}
void GfxScreen::kernelSyncWithFramebuffer() {
+ // TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
memcpy(_displayScreen, screen->pixels, _displayPixels);
g_system->unlockScreen();
@@ -351,12 +356,30 @@ byte GfxScreen::getControl(int x, int y) {
return _controlScreen[y * _width + x];
}
-byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con) {
+byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) {
int offset = y * _width + x;
byte match = 0;
- if ((screenMask & GFX_SCREEN_MASK_VISUAL) && *(_visualScreen + offset) == t_color)
- match |= GFX_SCREEN_MASK_VISUAL;
+ // FIXME:
+ if (screenMask & GFX_SCREEN_MASK_VISUAL) {
+ if (!isEGA) {
+ if (*(_visualScreen + offset) == t_color)
+ match |= GFX_SCREEN_MASK_VISUAL;
+ } else {
+ // In EGA games a pixel in the framebuffer is only 4 bits. We store
+ // a full byte per pixel to allow undithering, but when comparing
+ // pixels for flood-fill purposes, we should only compare the
+ // visible color of a pixel.
+
+ byte c = *(_visualScreen + offset);
+ if ((x ^ y) & 1)
+ c = (c ^ (c >> 4)) & 0x0F;
+ else
+ c = c & 0x0F;
+ if (c == t_color)
+ match |= GFX_SCREEN_MASK_VISUAL;
+ }
+ }
if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == t_pri)
match |= GFX_SCREEN_MASK_PRIORITY;
if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == t_con)
@@ -509,34 +532,6 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
}
}
-void GfxScreen::getPalette(Palette *pal) {
- // just copy palette to system
- byte bpal[4 * 256];
- // Get current palette, update it and put back
- g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
- for (int16 i = 1; i < 255; i++) {
- pal->colors[i].r = bpal[i * 4];
- pal->colors[i].g = bpal[i * 4 + 1];
- pal->colors[i].b = bpal[i * 4 + 2];
- }
-}
-
-void GfxScreen::setPalette(Palette *pal) {
- // just copy palette to system
- byte bpal[4 * 256];
- // Get current palette, update it and put back
- g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
- for (int16 i = 0; i < 256; i++) {
- if (!pal->colors[i].used)
- continue;
- bpal[i * 4] = CLIP(pal->colors[i].r * pal->intensity[i] / 100, 0, 255);
- bpal[i * 4 + 1] = CLIP(pal->colors[i].g * pal->intensity[i] / 100, 0, 255);
- bpal[i * 4 + 2] = CLIP(pal->colors[i].b * pal->intensity[i] / 100, 0, 255);
- bpal[i * 4 + 3] = 100;
- }
- g_system->getPaletteManager()->setPalette(bpal, 0, 256);
-}
-
void GfxScreen::setVerticalShakePos(uint16 shakePos) {
if (!_upscaledHires)
g_system->setShakePos(shakePos);
@@ -591,7 +586,7 @@ void GfxScreen::dither(bool addToFlag) {
}
} else {
if (!addToFlag)
- memset(&_unditherMemorial, 0, sizeof(_unditherMemorial));
+ memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors));
// Do dithering on visual screen and put decoded but undithered byte onto display-screen
for (y = 0; y < _height; y++) {
for (x = 0; x < _width; x++) {
@@ -599,7 +594,7 @@ void GfxScreen::dither(bool addToFlag) {
if (color & 0xF0) {
color ^= color << 4;
// remember dither combination for cel-undithering
- _unditherMemorial[color]++;
+ _ditheredPicColors[color]++;
// if decoded color wants do dither with black on left side, we turn it around
// otherwise the normal ega color would get used for display
if (color & 0xF0) {
@@ -626,18 +621,17 @@ void GfxScreen::dither(bool addToFlag) {
}
}
-// Force a color combination into memorial
-void GfxScreen::ditherForceMemorial(byte color) {
- _unditherMemorial[color] = 256;
+void GfxScreen::ditherForceDitheredColor(byte color) {
+ _ditheredPicColors[color] = 256;
}
void GfxScreen::debugUnditherSetState(bool flag) {
_unditherState = flag;
}
-int16 *GfxScreen::unditherGetMemorial() {
+int16 *GfxScreen::unditherGetDitheredBgColors() {
if (_unditherState)
- return (int16 *)&_unditherMemorial;
+ return (int16 *)&_ditheredPicColors;
else
return NULL;
}
@@ -702,12 +696,39 @@ void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHei
}
}
-void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x) {
+struct UpScaledAdjust {
+ GfxScreenUpscaledMode gameHiresMode;
+ Sci32ViewNativeResolution viewNativeRes;
+ int numerator;
+ int denominator;
+};
+
+static const UpScaledAdjust s_upscaledAdjustTable[] = {
+ { GFX_SCREEN_UPSCALED_640x480, SCI_VIEW_NATIVERES_640x400, 5, 6 }
+};
+
+void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewNativeRes) {
x *= 2;
y = _upscaledMapping[y];
+
+ for (int i = 0; i < ARRAYSIZE(s_upscaledAdjustTable); i++) {
+ if (s_upscaledAdjustTable[i].gameHiresMode == _upscaledHires &&
+ s_upscaledAdjustTable[i].viewNativeRes == viewNativeRes) {
+ y = (y * s_upscaledAdjustTable[i].numerator) / s_upscaledAdjustTable[i].denominator;
+ break;
+ }
+ }
}
-void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x) {
+void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewNativeRes) {
+ for (int i = 0; i < ARRAYSIZE(s_upscaledAdjustTable); i++) {
+ if (s_upscaledAdjustTable[i].gameHiresMode == _upscaledHires &&
+ s_upscaledAdjustTable[i].viewNativeRes == viewNativeRes) {
+ y = (y * s_upscaledAdjustTable[i].denominator) / s_upscaledAdjustTable[i].numerator;
+ break;
+ }
+ }
+
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_640x400:
x /= 2;
@@ -743,4 +764,23 @@ int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) {
return oldPicNotValid;
}
+uint16 GfxScreen::getLowResScreenHeight() {
+ // Some Mac SCI1/1.1 games only take up 190 rows and do not
+ // have the menu bar.
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
+ switch (g_sci->getGameId()) {
+ case GID_FREDDYPHARKAS:
+ case GID_KQ5:
+ case GID_KQ6:
+ case GID_SQ1:
+ return 190;
+ default:
+ break;
+ }
+ }
+
+ // Everything else is 200
+ return 200;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index b6898b905a..89ad52e0ac 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -28,6 +28,7 @@
#include "sci/sci.h"
#include "sci/graphics/helpers.h"
+#include "sci/graphics/view.h"
#include "graphics/sjis.h"
@@ -51,7 +52,7 @@ enum GfxScreenMasks {
};
enum {
- SCI_SCREEN_UNDITHERMEMORIAL_SIZE = 256
+ DITHERED_BG_COLORS_SIZE = 256
};
/**
@@ -89,35 +90,37 @@ public:
void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control);
}
- int getUpscaledHires() const {
+
+ GfxScreenUpscaledMode getUpscaledHires() const {
return _upscaledHires;
}
+
bool getUnditherState() const {
return _unditherState;
}
+
void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
byte getVisual(int x, int y);
byte getPriority(int x, int y);
byte getControl(int x, int y);
- byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con);
+ byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
int bitsGetDataSize(Common::Rect rect, byte mask);
void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
void bitsGetRect(byte *memoryPtr, Common::Rect *destRect);
void bitsRestore(byte *memoryPtr);
- void getPalette(Palette *pal);
- void setPalette(Palette *pal);
-
void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight, byte bytesPerPixel = 1);
- void adjustToUpscaledCoordinates(int16 &y, int16 &x);
- void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
+ void adjustToUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewScalingType = SCI_VIEW_NATIVERES_NONE);
+ void adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewScalingType = SCI_VIEW_NATIVERES_NONE);
void dither(bool addToFlag);
- void ditherForceMemorial(byte color);
+
+ // Force a color combination as a dithered color
+ void ditherForceDitheredColor(byte color);
void debugUnditherSetState(bool flag);
- int16 *unditherGetMemorial();
+ int16 *unditherGetDitheredBgColors();
void debugShowMap(int mapNo);
@@ -149,7 +152,7 @@ private:
void setVerticalShakePos(uint16 shakePos);
bool _unditherState;
- int16 _unditherMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
+ int16 _ditheredPicColors[DITHERED_BG_COLORS_SIZE];
// These screens have the real resolution of the game engine (320x200 for
// SCI0/SCI1/SCI11 games, 640x480 for SCI2 games). SCI0 games will be
@@ -175,7 +178,7 @@ private:
// This variable defines, if upscaled hires is active and what upscaled mode
// is used.
- int _upscaledHires;
+ GfxScreenUpscaledMode _upscaledHires;
// This here holds a translation for vertical coordinates between native
// (visual) and actual (display) screen.
@@ -184,6 +187,8 @@ private:
// This defines whether or not the font we're drawing is already scaled
// to the screen size (and we therefore should not upscale it ourselves).
bool _fontIsUpscaled;
+
+ uint16 getLowResScreenHeight();
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 21605ccb8e..6269a58492 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -204,19 +204,24 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
maxChars = curCharCount; // return count up to (but not including) breaking space
break;
}
+ // Sometimes this can go off the screen, like for example bug #3040161.
+ // However, we only perform this for non-Japanese games, as these require
+ // special handling, done after this loop.
+ if (width + _font->getCharWidth(curChar) > maxWidth && g_sci->getLanguage() != Common::JA_JPN)
+ break;
width += _font->getCharWidth(curChar);
curCharCount++;
}
+
+ // Text without spaces, probably Kanji/Japanese
if (maxChars == 0) {
- // Text w/o space, supposingly kanji
maxChars = curCharCount;
uint16 nextChar;
// We remove the last char only, if maxWidth was actually equal width
// before adding the last char. Otherwise we won't get the same cutting
- // as in sierra pc98 sci. Note: changing the while() instead will NOT
- // WORK. it would break all sorts of regular sci games.
+ // as in sierra pc98 sci.
if (maxWidth == (width - _font->getCharWidth(curChar))) {
maxChars--;
if (curChar > 0xFF)
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index b7b2bfb38e..fb124055d6 100644
--- a/engines/sci/graphics/transitions.cpp
+++ b/engines/sci/graphics/transitions.cpp
@@ -39,8 +39,8 @@ namespace Sci {
//#define DISABLE_TRANSITIONS // uncomment to disable room transitions (for development only! helps in testing games quickly)
-GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA)
- : _screen(screen), _palette(palette), _isVGA(isVGA) {
+GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette)
+ : _screen(screen), _palette(palette) {
init();
}
@@ -124,6 +124,7 @@ void GfxTransitions::setup(int16 number, bool blackoutFlag) {
_number = SCI_TRANSITIONS_NONE;
#endif
_blackoutFlag = blackoutFlag;
+ debugC(kDebugLevelGraphics, "Transition %d, blackout %d", number, blackoutFlag);
}
}
@@ -272,8 +273,7 @@ void GfxTransitions::doTransition(int16 number, bool blackoutFlag) {
void GfxTransitions::setNewPalette(bool blackoutFlag) {
if (!blackoutFlag)
- if (_isVGA)
- _palette->setOnScreen();
+ _palette->setOnScreen();
}
void GfxTransitions::setNewScreen(bool blackoutFlag) {
@@ -303,7 +303,7 @@ void GfxTransitions::copyRectToScreen(const Common::Rect rect, bool blackoutFlag
// Note: don't do too many steps in here, otherwise cpu will crap out because of
// the load
void GfxTransitions::fadeOut() {
- byte oldPalette[4 * 256], workPalette[4 * 256];
+ byte oldPalette[3 * 256], workPalette[3 * 256];
int16 stepNr, colorNr;
// Sierra did not fade in/out color 255 for sci1.1, but they used it in
// several pictures (e.g. qfg3 demo/intro), so the fading looked weird
@@ -312,12 +312,18 @@ void GfxTransitions::fadeOut() {
g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256);
for (stepNr = 100; stepNr >= 0; stepNr -= 10) {
- for (colorNr = 1; colorNr < tillColorNr; colorNr++){
- workPalette[colorNr * 4 + 0] = oldPalette[colorNr * 4] * stepNr / 100;
- workPalette[colorNr * 4 + 1] = oldPalette[colorNr * 4 + 1] * stepNr / 100;
- workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2] * stepNr / 100;
+ for (colorNr = 1; colorNr < tillColorNr; colorNr++) {
+ if (_palette->colorIsFromMacClut(colorNr)) {
+ workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3];
+ workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1];
+ workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2];
+ } else {
+ workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100;
+ workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100;
+ workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100;
+ }
}
- g_system->getPaletteManager()->setPalette(workPalette + 4, 1, 254);
+ g_system->getPaletteManager()->setPalette(workPalette + 3, 1, 254);
g_sci->getEngineState()->wait(2);
}
}
@@ -457,7 +463,6 @@ void GfxTransitions::scrollCopyOldToScreen(Common::Rect screenRect, int16 x, int
// Scroll old screen (up/down/left/right) and insert new screen that way - works
// on _picRect area only.
void GfxTransitions::scroll(int16 number) {
- int16 screenWidth, screenHeight;
int16 stepNr = 0;
Common::Rect oldMoveRect = _picRect;
Common::Rect oldScreenRect = _picRect;
@@ -466,7 +471,6 @@ void GfxTransitions::scroll(int16 number) {
uint32 msecCount = 0;
_screen->copyFromScreen(_oldScreen);
- screenWidth = _screen->getDisplayWidth(); screenHeight = _screen->getDisplayHeight();
switch (number) {
case SCI_TRANSITIONS_SCROLL_LEFT:
@@ -510,7 +514,7 @@ void GfxTransitions::scroll(int16 number) {
newScreenRect.bottom = newScreenRect.top;
newMoveRect.top = newMoveRect.bottom;
while (oldMoveRect.top < oldMoveRect.bottom) {
- oldMoveRect.top++; oldScreenRect.top++;
+ oldMoveRect.top++; oldScreenRect.top++;
newScreenRect.bottom++; newMoveRect.top--;
msecCount += 5;
diff --git a/engines/sci/graphics/transitions.h b/engines/sci/graphics/transitions.h
index 674b7a8173..a8f0ca6f07 100644
--- a/engines/sci/graphics/transitions.h
+++ b/engines/sci/graphics/transitions.h
@@ -65,7 +65,7 @@ class Screen;
*/
class GfxTransitions {
public:
- GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA);
+ GfxTransitions(GfxScreen *screen, GfxPalette *palette);
~GfxTransitions();
void setup(int16 number, bool blackoutFlag);
@@ -97,7 +97,6 @@ private:
GfxScreen *_screen;
GfxPalette *_palette;
- bool _isVGA;
const GfxTransitionTranslateEntry *_translationTable;
int16 _number;
bool _blackoutFlag;
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index a8fc8e7f15..f31cbacb22 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -83,7 +83,7 @@ void GfxView::initData(GuiResourceId resourceId) {
_loopCount = 0;
_embeddedPal = false;
_EGAmapping = NULL;
- _isSci2Hires = false;
+ _sci2ScaleRes = SCI_VIEW_NATIVERES_NONE;
_isScaleable = true;
// we adjust inside getCelRect for SCI0EARLY (that version didn't have the +1 when calculating bottom)
@@ -104,9 +104,10 @@ void GfxView::initData(GuiResourceId resourceId) {
}
switch (curViewType) {
- case kViewEga: // View-format SCI0 (and Amiga 16 colors)
+ case kViewEga: // SCI0 (and Amiga 16 colors)
isEGA = true;
- case kViewAmiga: // View-format Amiga (32 colors)
+ case kViewAmiga: // Amiga ECS (32 colors)
+ case kViewAmiga64: // Amiga AGA (64 colors)
case kViewVga: // View-format SCI1
// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
@@ -132,7 +133,7 @@ void GfxView::initData(GuiResourceId resourceId) {
// SCI1 VGA conversion games (which will get detected as SCI1EARLY/MIDDLE/LATE) have some views
// with broken mapping tables. I guess those games won't use the mapping, so I rather disable it
// for them
- if (getSciVersion() == SCI_VERSION_1_EGA) {
+ if (getSciVersion() == SCI_VERSION_1_EGA_ONLY) {
_EGAmapping = &_resourceData[palOffset];
for (EGAmapNr = 0; EGAmapNr < SCI_VIEW_EGAMAPPING_COUNT; EGAmapNr++) {
if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE) != 0)
@@ -201,8 +202,15 @@ void GfxView::initData(GuiResourceId resourceId) {
assert(headerSize >= 16);
_loopCount = _resourceData[2];
assert(_loopCount);
- _isSci2Hires = _resourceData[5] == 1 ? true : false;
palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8);
+
+ // For SCI32, this is a scale flag
+ if (getSciVersion() >= SCI_VERSION_2) {
+ _sci2ScaleRes = (Sci32ViewNativeResolution)_resourceData[5];
+ if (_screen->getUpscaledHires() == GFX_SCREEN_UPSCALED_DISABLED)
+ _sci2ScaleRes = SCI_VIEW_NATIVERES_NONE;
+ }
+
// flags is actually a bit-mask
// it seems it was only used for some early sci1.1 games (or even just laura bow 2)
// later interpreters dont support it at all anymore
@@ -282,10 +290,10 @@ void GfxView::initData(GuiResourceId resourceId) {
}
#ifdef ENABLE_SCI32
// adjust width/height returned to scripts
- if (_isSci2Hires) {
+ if (_sci2ScaleRes != SCI_VIEW_NATIVERES_NONE) {
for (loopNo = 0; loopNo < _loopCount; loopNo++)
for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++)
- _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight);
+ _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight, _sci2ScaleRes);
} else if (getSciVersion() == SCI_VERSION_2_1) {
for (loopNo = 0; loopNo < _loopCount; loopNo++)
for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++)
@@ -329,7 +337,7 @@ Palette *GfxView::getPalette() {
}
bool GfxView::isSci2Hires() {
- return _isSci2Hires;
+ return _sci2ScaleRes > SCI_VIEW_NATIVERES_320x200;
}
bool GfxView::isScaleable() {
@@ -346,12 +354,9 @@ void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, C
void GfxView::getCelSpecialHoyle4Rect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const {
const CelInfo *celInfo = getCelInfo(loopNo, celNo);
- int16 adjustY = y - celInfo->height + celInfo->displaceY + 1;
- int16 adjustX = x - ((celInfo->width - 1) >> 1) + celInfo->displaceX;
- outRect.top += adjustY;
- outRect.bottom += adjustY;
- outRect.left += adjustX;
- outRect.right += adjustX;
+ int16 adjustY = y + celInfo->displaceY - celInfo->height + 1;
+ int16 adjustX = x + celInfo->displaceX - ((celInfo->width - 1) >> 1);
+ outRect.translate(adjustX, adjustY);
}
void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const {
@@ -373,22 +378,157 @@ void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int1
outRect.top = outRect.bottom - scaledHeight;
}
+void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData) {
+ byte *outPtr = celBitmap;
+ byte curByte, runLength;
+ byte *rlePtr = inBuffer + rlePos;
+ // The existence of a literal position pointer signifies data with two
+ // separate streams, most likely a SCI1.1 view
+ byte *literalPtr = inBuffer + literalPos;
+ int pixelNr = 0;
+
+ memset(celBitmap, clearColor, pixelCount);
+
+ // View unpacking:
+ //
+ // EGA:
+ // Each byte is like XXXXYYYY (XXXX: 0 - 15, YYYY: 0 - 15)
+ // Set the next XXXX pixels to YYYY
+ //
+ // Amiga:
+ // Each byte is like XXXXXYYY (XXXXX: 0 - 31, YYY: 0 - 7)
+ // - Case A: YYY != 0
+ // Set the next YYY pixels to XXXXX
+ // - Case B: YYY == 0
+ // Skip the next XXXXX pixels (i.e. transparency)
+ //
+ // Amiga 64:
+ // Each byte is like XXYYYYYY (XX: 0 - 3, YYYYYY: 0 - 63)
+ // - Case A: XX != 0
+ // Set the next XX pixels to YYYYYY
+ // - Case B: XX == 0
+ // Skip the next YYYYYY pixels (i.e. transparency)
+ //
+ // VGA:
+ // Each byte is like XXYYYYYY (YYYYY: 0 - 63)
+ // - Case A: XX == 00 (binary)
+ // Copy next YYYYYY bytes as-is
+ // - Case B: XX == 01 (binary)
+ // Same as above, copy YYYYYY + 64 bytes as-is
+ // - Case C: XX == 10 (binary)
+ // Set the next YYYYY pixels to the next byte value
+ // - Case D: XX == 11 (binary)
+ // Skip the next YYYYY pixels (i.e. transparency)
+
+ if (literalPos && isMacSci11ViewData) {
+ // KQ6/Freddy Pharkas use byte lengths, all others use uint16
+ // The SCI devs must have realized that a max of 255 pixels wide
+ // was not very good for 320 or 640 width games.
+ bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS);
+
+ // compression for SCI1.1+ Mac
+ while (pixelNr < pixelCount) {
+ uint32 pixelLine = pixelNr;
+
+ if (hasByteLengths) {
+ pixelNr += *rlePtr++;
+ runLength = *rlePtr++;
+ } else {
+ pixelNr += READ_BE_UINT16(rlePtr);
+ runLength = READ_BE_UINT16(rlePtr + 2);
+ rlePtr += 4;
+ }
+
+ while (runLength-- && pixelNr < pixelCount)
+ outPtr[pixelNr++] = *literalPtr++;
+
+ pixelNr = pixelLine + width;
+ }
+ return;
+ }
+
+ switch (viewType) {
+ case kViewEga:
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ runLength = curByte >> 4;
+ memset(outPtr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
+ pixelNr += runLength;
+ }
+ break;
+ case kViewAmiga:
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ if (curByte & 0x07) { // fill with color
+ runLength = curByte & 0x07;
+ curByte = curByte >> 3;
+ memset(outPtr + pixelNr, curByte, MIN<uint16>(runLength, pixelCount - pixelNr));
+ } else { // skip the next pixels (transparency)
+ runLength = curByte >> 3;
+ }
+ pixelNr += runLength;
+ }
+ break;
+ case kViewAmiga64:
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ if (curByte & 0xC0) { // fill with color
+ runLength = curByte >> 6;
+ memset(outPtr + pixelNr, curByte & 0x3F, MIN<uint16>(runLength, pixelCount - pixelNr));
+ } else { // skip the next pixels (transparency)
+ runLength = curByte & 0x3F;
+ }
+ pixelNr += runLength;
+ }
+ break;
+ case kViewVga:
+ case kViewVga11:
+ // If we have no RLE data, the image is just uncompressed
+ if (rlePos == 0) {
+ memcpy(outPtr, literalPtr, pixelCount);
+ break;
+ }
+
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ runLength = curByte & 0x3F;
+
+ switch (curByte & 0xC0) {
+ case 0x40: // copy bytes as is (In copy case, runLength can go up to 127 i.e. pixel & 0x40). Fixes bug #3135872.
+ runLength += 64;
+ case 0x00: // copy bytes as-is
+ if (!literalPos) {
+ memcpy(outPtr + pixelNr, rlePtr, MIN<uint16>(runLength, pixelCount - pixelNr));
+ rlePtr += runLength;
+ } else {
+ memcpy(outPtr + pixelNr, literalPtr, MIN<uint16>(runLength, pixelCount - pixelNr));
+ literalPtr += runLength;
+ }
+ break;
+ case 0x80: // fill with color
+ if (!literalPos)
+ memset(outPtr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
+ else
+ memset(outPtr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
+ break;
+ case 0xC0: // skip the next pixels (transparency)
+ break;
+ }
+
+ pixelNr += runLength;
+ }
+ break;
+ default:
+ error("Unsupported picture viewtype");
+ }
+}
+
void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) {
const CelInfo *celInfo = getCelInfo(loopNo, celNo);
- byte *rlePtr;
- byte *literalPtr;
- uint32 pixelNo = 0, runLength;
- byte pixel;
if (celInfo->offsetEGA) {
// decompression for EGA views
- literalPtr = _resourceData + _loop[loopNo].cel[celNo].offsetEGA;
- while (pixelNo < pixelCount) {
- pixel = *literalPtr++;
- runLength = pixel >> 4;
- memset(outPtr + pixelNo, pixel & 0x0F, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- }
+ unpackCelData(_resourceData, outPtr, 0, pixelCount, celInfo->offsetEGA, 0, _resMan->getViewType(), celInfo->width, false);
} else {
// We fill the buffer with transparent pixels, so that we can later skip
// over pixels to automatically have them transparent
@@ -411,100 +551,8 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
clearColor = 0;
}
- memset(outPtr, clearColor, pixelCount);
-
- rlePtr = _resourceData + celInfo->offsetRLE;
- if (!celInfo->offsetLiteral) { // no additional literal data
- if (_resMan->isAmiga32color()) {
- // decompression for amiga views
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- if (pixel & 0x07) { // fill with color
- runLength = pixel & 0x07;
- pixel = pixel >> 3;
- while (runLength-- && pixelNo < pixelCount) {
- outPtr[pixelNo++] = pixel;
- }
- } else { // fill with transparent
- runLength = pixel >> 3;
- pixelNo += runLength;
- }
- }
- } else {
- // decompression for data that has just one combined stream
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- runLength = pixel & 0x3F;
- switch (pixel & 0xC0) {
- case 0x40: // copy bytes as is (In copy case, runLength can go upto 127 i.e. pixel & 0x40)
- runLength += 64;
- case 0x00: // copy bytes as-is
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *rlePtr++;
- break;
- case 0x80: // fill with color
- memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNo += runLength;
- break;
- }
- }
- }
- } else {
- literalPtr = _resourceData + celInfo->offsetLiteral;
- if (celInfo->offsetRLE) {
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1) {
- // KQ6/Freddy Pharkas use byte lengths, all others use uint16
- // The SCI devs must have realized that a max of 255 pixels wide
- // was not very good for 320 or 640 width games.
- bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS);
-
- // compression for SCI1.1+ Mac
- while (pixelNo < pixelCount) {
- uint32 pixelLine = pixelNo;
-
- if (hasByteLengths) {
- pixelNo += *rlePtr++;
- runLength = *rlePtr++;
- } else {
- pixelNo += READ_BE_UINT16(rlePtr);
- runLength = READ_BE_UINT16(rlePtr + 2);
- rlePtr += 4;
- }
-
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *literalPtr++;
-
- pixelNo = pixelLine + celInfo->width;
- }
- } else {
- // decompression for data that has separate rle and literal streams
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- runLength = pixel & 0x3F;
- switch (pixel & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *literalPtr++;
- break;
- case 0x80: // fill with color
- memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNo += runLength;
- break;
- }
- }
- }
- } else {
- // literal stream only, so no compression
- memcpy(outPtr, literalPtr, pixelCount);
- pixelNo = pixelCount;
- }
- }
+ bool isMacSci11ViewData = g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1;
+ unpackCelData(_resourceData, outPtr, clearColor, pixelCount, celInfo->offsetRLE, celInfo->offsetLiteral, _resMan->getViewType(), celInfo->width, isMacSci11ViewData);
// Swap 0 and 0xff pixels for Mac SCI1.1+ games (see above)
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
@@ -534,9 +582,8 @@ const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
// unpack the actual cel bitmap data
unpackCel(loopNo, celNo, pBitmap, pixelCount);
- if (!_resMan->isVGA()) {
+ if (_resMan->getViewType() == kViewEga)
unditherBitmap(pBitmap, width, height, _loop[loopNo].cel[celNo].clearKey);
- }
// mirroring the cel if needed
if (_loop[loopNo].mirrorFlag) {
@@ -552,19 +599,15 @@ const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
* cel if the dithering in here matches dithering used by the current picture.
*/
void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) {
- int16 *unditherMemorial = _screen->unditherGetMemorial();
+ int16 *ditheredPicColors = _screen->unditherGetDitheredBgColors();
- // It makes no sense to go further, if no memorial data from current picture
- // is available
- if (!unditherMemorial)
+ // It makes no sense to go further, if there isn't any dithered color data
+ // available for the current picture
+ if (!ditheredPicColors)
return;
- // Makes no sense to process bitmaps that are 3 pixels wide or less
- if (width <= 3)
- return;
-
- // We need at least 2 pixel lines
- if (height < 2)
+ // We need at least a 4x2 bitmap for this algorithm to work
+ if (width < 4 || height < 2)
return;
// If EGA mapping is used for this view, dont do undithering as well
@@ -572,13 +615,13 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
return;
// Walk through the bitmap and remember all combinations of colors
- int16 bitmapMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
+ int16 ditheredBitmapColors[DITHERED_BG_COLORS_SIZE];
byte *curPtr;
byte color1, color2;
byte nextColor1, nextColor2;
int16 y, x;
- memset(&bitmapMemorial, 0, sizeof(bitmapMemorial));
+ memset(&ditheredBitmapColors, 0, sizeof(ditheredBitmapColors));
// Count all seemingly dithered pixel-combinations as soon as at least 4
// pixels are adjacent and check pixels in the following line as well to
@@ -597,17 +640,17 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
nextColor1 = (nextColor1 >> 4) | (nextColor2 << 4);
nextColor2 = (nextColor2 >> 4) | *nextPtr++ << 4;
if ((color1 == color2) && (color1 == nextColor1) && (color1 == nextColor2))
- bitmapMemorial[color1]++;
+ ditheredBitmapColors[color1]++;
}
}
- // Now compare both memorial tables to find out matching
- // dithering-combinations
- bool unditherTable[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
+ // Now compare both dither color tables to find out matching dithered color
+ // combinations
+ bool unditherTable[DITHERED_BG_COLORS_SIZE];
byte color, unditherCount = 0;
memset(&unditherTable, false, sizeof(unditherTable));
for (color = 0; color < 255; color++) {
- if ((bitmapMemorial[color] > 5) && (unditherMemorial[color] > 200)) {
+ if ((ditheredBitmapColors[color] > 5) && (ditheredPicColors[color] > 200)) {
// match found, check if colorKey is contained -> if so, we ignore
// of course
color1 = color & 0x0F; color2 = color >> 4;
@@ -655,10 +698,9 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const
const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
int x, y;
- if (_embeddedPal) {
+ if (_embeddedPal)
// Merge view palette in...
_palette->set(&_viewPalette, false);
- }
const int16 width = MIN(clipRect.width(), celWidth);
const int16 height = MIN(clipRect.height(), celHeight);
@@ -679,7 +721,9 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const
// UpscaledHires means view is hires and is supposed to
// get drawn onto lowres screen.
// FIXME(?): we can't read priority directly with the
- // hires coordinates. may not be needed at all in kq6
+ // hires coordinates. May not be needed at all in kq6
+ // FIXME: Handle proper aspect ratio. Some GK1 hires images
+ // are in 640x400 instead of 640x480
_screen->putPixelOnDisplay(x2, y2, palette->mapping[color]);
}
}
@@ -718,10 +762,9 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect,
int16 scaledWidth, scaledHeight;
int pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo;
- if (_embeddedPal) {
+ if (_embeddedPal)
// Merge view palette in...
_palette->set(&_viewPalette, false);
- }
scaledWidth = (celInfo->width * scaleX) >> 7;
scaledHeight = (celInfo->height * scaleY) >> 7;
@@ -788,4 +831,12 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect,
}
}
+void GfxView::adjustToUpscaledCoordinates(int16 &y, int16 &x) {
+ _screen->adjustToUpscaledCoordinates(y, x, _sci2ScaleRes);
+}
+
+void GfxView::adjustBackUpscaledCoordinates(int16 &y, int16 &x) {
+ _screen->adjustBackUpscaledCoordinates(y, x, _sci2ScaleRes);
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h
index f785e3c475..36914f916c 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -28,6 +28,13 @@
namespace Sci {
+enum Sci32ViewNativeResolution {
+ SCI_VIEW_NATIVERES_NONE = -1,
+ SCI_VIEW_NATIVERES_320x200 = 0,
+ SCI_VIEW_NATIVERES_640x480 = 1,
+ SCI_VIEW_NATIVERES_640x400 = 2
+};
+
struct CelInfo {
int16 width, height;
int16 scriptWidth, scriptHeight;
@@ -78,6 +85,9 @@ public:
bool isScaleable();
bool isSci2Hires();
+ void adjustToUpscaledCoordinates(int16 &y, int16 &x);
+ void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
+
private:
void initData(GuiResourceId resourceId);
void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount);
@@ -98,8 +108,8 @@ private:
bool _embeddedPal;
Palette _viewPalette;
- // set for SCI2 views in gk1/windows, means that views are hires and should be handled accordingly
- bool _isSci2Hires;
+ // specifies scaling resolution for SCI2 views (see gk1/windows, Wolfgang in room 720)
+ Sci32ViewNativeResolution _sci2ScaleRes;
byte *_EGAmapping;
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 005fe21cfa..2202002e2e 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -38,6 +38,7 @@ MODULE_OBJS := \
engine/state.o \
engine/static_selectors.o \
engine/vm.o \
+ engine/vm_types.o \
engine/workarounds.o \
graphics/animate.o \
graphics/cache.o \
diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp
index 8a6cd2dd4d..77db56adba 100644
--- a/engines/sci/parser/grammar.cpp
+++ b/engines/sci/parser/grammar.cpp
@@ -380,7 +380,7 @@ static ParseRuleList *_vocab_clone_rule_list_by_id(ParseRuleList *list, int id)
ParseRuleList *Vocabulary::buildGNF(bool verbose) {
int iterations = 0;
- int last_termrules, termrules = 0;
+ int termrules = 0;
int ntrules_nr;
ParseRuleList *ntlist = NULL;
ParseRuleList *tlist, *new_tlist;
@@ -405,7 +405,6 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) {
do {
ParseRuleList *new_new_tlist = NULL;
ParseRuleList *ntseeker, *tseeker;
- last_termrules = termrules;
ntseeker = ntlist;
while (ntseeker) {
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index e9c6d9847f..666a235cf9 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -1020,7 +1020,7 @@ static int augment_parse_nodes(ParseTreeNode *parseT, ParseTreeNode *saidT) {
/**** Main code ****/
/*******************/
-int said(EngineState *s, const byte *spec, bool verbose) {
+int said(const byte *spec, bool verbose) {
int retval;
Vocabulary *voc = g_sci->getVocabulary();
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 8d59df5d58..25043401cc 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -63,7 +63,7 @@ Vocabulary::Vocabulary(ResourceManager *resMan, bool foreign) : _resMan(resMan),
_resourceIdBranches += 10;
}
- if (getSciVersion() <= SCI_VERSION_1_EGA && loadParserWords()) {
+ if (getSciVersion() <= SCI_VERSION_1_EGA_ONLY && loadParserWords()) {
loadSuffixes();
if (loadBranches())
// Now build a GNF grammar out of this
diff --git a/engines/sci/parser/vocabulary.h b/engines/sci/parser/vocabulary.h
index 3d644d88f7..6d3e0b301e 100644
--- a/engines/sci/parser/vocabulary.h
+++ b/engines/sci/parser/vocabulary.h
@@ -383,12 +383,11 @@ void vocab_dump_parse_tree(const char *tree_name, ParseTreeNode *nodes);
/**
* Builds a parse tree from a spec and compares it to a parse tree.
- * @param s The affected state
* @param spec Pointer to the spec to build
* @param verbose Whether to display the parse tree after building it
* @return 1 on a match, 0 otherwise
*/
-int said(EngineState *s, const byte *spec, bool verbose);
+int said(const byte *spec, bool verbose);
} // End of namespace Sci
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 8c8bc6d512..4caa77b0ae 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -38,6 +38,7 @@ namespace Sci {
enum {
SCI0_RESMAP_ENTRIES_SIZE = 6,
SCI1_RESMAP_ENTRIES_SIZE = 6,
+ KQ5FMT_RESMAP_ENTRIES_SIZE = 7,
SCI11_RESMAP_ENTRIES_SIZE = 5
};
@@ -66,7 +67,7 @@ const char *getSciVersionDesc(SciVersion version) {
return "Late SCI0";
case SCI_VERSION_01:
return "SCI01";
- case SCI_VERSION_1_EGA:
+ case SCI_VERSION_1_EGA_ONLY:
return "SCI1 EGA";
case SCI_VERSION_1_EARLY:
return "Early SCI1";
@@ -427,10 +428,8 @@ void MacResourceForkResourceSource::loadResource(ResourceManager *resMan, Resour
stream = _macResMan->getResource(tagArray[i], res->getNumber());
}
- if (!stream)
- error("Could not get Mac resource fork resource: %s", res->_id.toString().c_str());
-
- decompressResource(stream, res);
+ if (stream)
+ decompressResource(stream, res);
}
bool MacResourceForkResourceSource::isCompressableResource(ResourceType type) const {
@@ -949,15 +948,18 @@ void ResourceManager::init(bool initFromFallbackDetector) {
case kViewEga:
debugC(1, kDebugLevelResMan, "resMan: Detected EGA graphic resources");
break;
+ case kViewAmiga:
+ debugC(1, kDebugLevelResMan, "resMan: Detected Amiga ECS graphic resources");
+ break;
+ case kViewAmiga64:
+ debugC(1, kDebugLevelResMan, "resMan: Detected Amiga AGA graphic resources");
+ break;
case kViewVga:
debugC(1, kDebugLevelResMan, "resMan: Detected VGA graphic resources");
break;
case kViewVga11:
debugC(1, kDebugLevelResMan, "resMan: Detected SCI1.1 VGA graphic resources");
break;
- case kViewAmiga:
- debugC(1, kDebugLevelResMan, "resMan: Detected Amiga graphic resources");
- break;
default:
#ifdef ENABLE_SCI32
error("resMan: Couldn't determine view type");
@@ -1115,6 +1117,8 @@ const char *ResourceManager::versionDescription(ResVersion version) const {
return "SCI0 / Early SCI1";
case kResVersionSci1Middle:
return "Middle SCI1";
+ case kResVersionKQ5FMT:
+ return "KQ5 FM Towns";
case kResVersionSci1Late:
return "Late SCI1";
case kResVersionSci11:
@@ -1164,6 +1168,14 @@ ResVersion ResourceManager::detectMapVersion() {
fileStream->seek(-4, SEEK_END);
uint32 uEnd = fileStream->readUint32LE();
if (uEnd == 0xFFFFFFFF) {
+ // check if the last 7 bytes are all ff, indicating a KQ5 FM-Towns map
+ fileStream->seek(-7, SEEK_END);
+ fileStream->read(buff, 3);
+ if (buff[0] == 0xff && buff[1] == 0xff && buff[2] == 0xff) {
+ delete fileStream;
+ return kResVersionKQ5FMT;
+ }
+
// check if 0 or 01 - try to read resources in SCI0 format and see if exists
fileStream->seek(0, SEEK_SET);
while (fileStream->read(buff, 6) == 6 && !(buff[0] == 0xFF && buff[1] == 0xFF && buff[2] == 0xFF)) {
@@ -1476,7 +1488,7 @@ void ResourceManager::readResourcePatchesBase36() {
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
uint32 tag = stream->readUint32BE();
- if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) {
+ if (tag == MKTAG('R','I','F','F') || tag == MKTAG('F','O','R','M')) {
delete stream;
processWavePatch(resource36, name);
continue;
@@ -1485,7 +1497,7 @@ void ResourceManager::readResourcePatchesBase36() {
// Check for SOL as well
tag = (tag << 16) | stream->readUint16BE();
- if (tag != MKID_BE('SOL\0')) {
+ if (tag != MKTAG('S','O','L',0)) {
delete stream;
continue;
}
@@ -1526,10 +1538,18 @@ void ResourceManager::readResourcePatches() {
mask += s_resourceTypeSuffixes[i];
SearchMan.listMatchingMembers(files, mask);
- if (i == kResourceTypeScript && files.size() == 0) {
- // SCI3 (we can't use getSciVersion() at this point)
- mask = "*.csc";
- SearchMan.listMatchingMembers(files, mask);
+ if (i == kResourceTypeView) {
+ SearchMan.listMatchingMembers(files, "*.v16"); // EGA SCI1 view patches
+ SearchMan.listMatchingMembers(files, "*.v32"); // Amiga SCI1 view patches
+ SearchMan.listMatchingMembers(files, "*.v64"); // Amiga AGA SCI1 (i.e. Longbow) view patches
+ } else if (i == kResourceTypePic) {
+ SearchMan.listMatchingMembers(files, "*.p16"); // EGA SCI1 picture patches
+ SearchMan.listMatchingMembers(files, "*.p32"); // Amiga SCI1 picture patches
+ SearchMan.listMatchingMembers(files, "*.p64"); // Amiga AGA SCI1 (i.e. Longbow) picture patches
+ } else if (i == kResourceTypeScript) {
+ if (files.size() == 0)
+ // SCI3 (we can't use getSciVersion() at this point)
+ SearchMan.listMatchingMembers(files, "*.csc");
}
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
@@ -1561,7 +1581,7 @@ void ResourceManager::readResourcePatches() {
int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
Common::SeekableReadStream *fileStream = 0;
- ResourceType type;
+ ResourceType type = kResourceTypeInvalid; // to silence a false positive in MSVC
uint16 number, id;
uint32 offset;
@@ -1578,10 +1598,15 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
fileStream->seek(0, SEEK_SET);
- byte bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC;
- byte bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26;
+ byte bMask = (_mapVersion >= kResVersionSci1Middle) ? 0xF0 : 0xFC;
+ byte bShift = (_mapVersion >= kResVersionSci1Middle) ? 28 : 26;
do {
+ // King's Quest 5 FM-Towns uses a 7 byte version of the SCI1 Middle map,
+ // splitting the type from the id.
+ if (_mapVersion == kResVersionKQ5FMT)
+ type = convertResType(fileStream->readByte());
+
id = fileStream->readUint16LE();
offset = fileStream->readUint32LE();
@@ -1590,11 +1615,17 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
warning("Error while reading %s", map->getLocationName().c_str());
return SCI_ERROR_RESMAP_NOT_FOUND;
}
+
if (offset == 0xFFFFFFFF)
break;
- type = convertResType(id >> 11);
- number = id & 0x7FF;
+ if (_mapVersion == kResVersionKQ5FMT) {
+ number = id;
+ } else {
+ type = convertResType(id >> 11);
+ number = id & 0x7FF;
+ }
+
ResourceId resId = ResourceId(type, number);
// adding a new resource
if (_resMap.contains(resId) == false) {
@@ -1715,25 +1746,25 @@ struct MacResTag {
};
static const MacResTag macResTagMap[] = {
- { MKID_BE('V56 '), kResourceTypeView },
- { MKID_BE('P56 '), kResourceTypePic },
- { MKID_BE('SCR '), kResourceTypeScript },
- { MKID_BE('TEX '), kResourceTypeText },
- { MKID_BE('SND '), kResourceTypeSound },
- { MKID_BE('VOC '), kResourceTypeVocab },
- { MKID_BE('FON '), kResourceTypeFont },
- { MKID_BE('CURS'), kResourceTypeCursor },
- { MKID_BE('crsr'), kResourceTypeCursor },
- { MKID_BE('Pat '), kResourceTypePatch },
- { MKID_BE('PAL '), kResourceTypePalette },
- { MKID_BE('snd '), kResourceTypeAudio },
- { MKID_BE('MSG '), kResourceTypeMessage },
- { MKID_BE('HEP '), kResourceTypeHeap },
- { MKID_BE('IBIN'), kResourceTypeMacIconBarPictN },
- { MKID_BE('IBIS'), kResourceTypeMacIconBarPictS },
- { MKID_BE('PICT'), kResourceTypeMacPict },
- { MKID_BE('SYN '), kResourceTypeSync },
- { MKID_BE('SYNC'), kResourceTypeSync }
+ { MKTAG('V','5','6',' '), kResourceTypeView },
+ { MKTAG('P','5','6',' '), kResourceTypePic },
+ { MKTAG('S','C','R',' '), kResourceTypeScript },
+ { MKTAG('T','E','X',' '), kResourceTypeText },
+ { MKTAG('S','N','D',' '), kResourceTypeSound },
+ { MKTAG('V','O','C',' '), kResourceTypeVocab },
+ { MKTAG('F','O','N',' '), kResourceTypeFont },
+ { MKTAG('C','U','R','S'), kResourceTypeCursor },
+ { MKTAG('c','r','s','r'), kResourceTypeCursor },
+ { MKTAG('P','a','t',' '), kResourceTypePatch },
+ { MKTAG('P','A','L',' '), kResourceTypePalette },
+ { MKTAG('s','n','d',' '), kResourceTypeAudio },
+ { MKTAG('M','S','G',' '), kResourceTypeMessage },
+ { MKTAG('H','E','P',' '), kResourceTypeHeap },
+ { MKTAG('I','B','I','N'), kResourceTypeMacIconBarPictN },
+ { MKTAG('I','B','I','S'), kResourceTypeMacIconBarPictS },
+ { MKTAG('P','I','C','T'), kResourceTypeMacPict },
+ { MKTAG('S','Y','N',' '), kResourceTypeSync },
+ { MKTAG('S','Y','N','C'), kResourceTypeSync }
};
static Common::Array<uint32> resTypeToMacTags(ResourceType type) {
@@ -2029,7 +2060,13 @@ ViewType ResourceManager::detectViewType() {
switch (res->data[1]) {
case 128:
- // If the 2nd byte is 128, it's a VGA game
+ // If the 2nd byte is 128, it's a VGA game.
+ // However, Longbow Amiga (AGA, 64 colors), also sets this byte
+ // to 128, but it's a mixed VGA/Amiga format. Detect this from
+ // the platform here.
+ if (g_sci && g_sci->getPlatform() == Common::kPlatformAmiga)
+ return kViewAmiga64;
+
return kViewVga;
case 0:
// EGA or Amiga, try to read as Amiga view
@@ -2107,9 +2144,9 @@ void ResourceManager::detectSciVersion() {
if (viewCompression != kCompLZW) {
// If it's a different compression type from kCompLZW, the game is probably
- // SCI_VERSION_1_EGA or later. If the views are uncompressed, it is
+ // SCI_VERSION_1_EGA_ONLY or later. If the views are uncompressed, it is
// likely not an early disk game.
- s_sciVersion = SCI_VERSION_1_EGA;
+ s_sciVersion = SCI_VERSION_1_EGA_ONLY;
oldDecompressors = false;
}
@@ -2223,9 +2260,9 @@ void ResourceManager::detectSciVersion() {
return;
}
- // New decompressors. It's either SCI_VERSION_1_EGA or SCI_VERSION_1_EARLY.
+ // New decompressors. It's either SCI_VERSION_1_EGA_ONLY or SCI_VERSION_1_EARLY.
if (hasSci1Voc900()) {
- s_sciVersion = SCI_VERSION_1_EGA;
+ s_sciVersion = SCI_VERSION_1_EGA_ONLY;
return;
}
@@ -2233,7 +2270,14 @@ void ResourceManager::detectSciVersion() {
s_sciVersion = SCI_VERSION_1_EARLY;
return;
case kResVersionSci1Middle:
+ case kResVersionKQ5FMT:
s_sciVersion = SCI_VERSION_1_MIDDLE;
+ // Amiga SCI1 middle games are actually SCI1 late
+ if (_viewType == kViewAmiga || _viewType == kViewAmiga64)
+ s_sciVersion = SCI_VERSION_1_LATE;
+ // Same goes for Mac SCI1 middle games
+ if (g_sci && g_sci->getPlatform() == Common::kPlatformMacintosh)
+ s_sciVersion = SCI_VERSION_1_LATE;
return;
case kResVersionSci1Late:
if (_volVersion == kResVersionSci11) {
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 92749ba162..e941f666d9 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -124,6 +124,7 @@ enum ResVersion {
kResVersionUnknown,
kResVersionSci0Sci1Early,
kResVersionSci1Middle,
+ kResVersionKQ5FMT,
kResVersionSci1Late,
kResVersionSci11,
kResVersionSci11Mac,
@@ -330,8 +331,6 @@ public:
int getAudioLanguage() const;
void changeAudioDirectory(Common::String path);
bool isGMTrackIncluded();
- bool isVGA() const { return (_viewType == kViewVga) || (_viewType == kViewVga11); }
- bool isAmiga32color() const { return _viewType == kViewAmiga; }
bool isSci11Mac() const { return _volVersion == kResVersionSci11Mac; }
ViewType getViewType() const { return _viewType; }
const char *getMapVersionDesc() const { return versionDescription(_mapVersion); }
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 386bfb37f5..6e74553f56 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -53,9 +53,9 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, co
fileStream->seek(0, SEEK_SET);
uint32 compressionType = fileStream->readUint32BE();
switch (compressionType) {
- case MKID_BE('MP3 '):
- case MKID_BE('OGG '):
- case MKID_BE('FLAC'):
+ case MKTAG('M','P','3',' '):
+ case MKTAG('O','G','G',' '):
+ case MKTAG('F','L','A','C'):
// Detected a compressed audio volume
_audioCompressionType = compressionType;
// Now read the whole offset mapping table for later usage
@@ -91,7 +91,7 @@ bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) {
bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
// Check for WAVE files here
uint32 riffTag = file->readUint32BE();
- if (riffTag == MKID_BE('RIFF')) {
+ if (riffTag == MKTAG('R','I','F','F')) {
_headerSize = 0;
size = file->readUint32LE() + 8;
file->seek(-8, SEEK_CUR);
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index c69e35df6d..85c2eced19 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -213,7 +213,6 @@ Common::Error SciEngine::run() {
// Add the after market GM patches for the specified game, if they exist
_resMan->addNewGMPatch(_gameId);
_gameObjectAddress = _resMan->findGameObject();
- _gameSuperClassAddress = NULL_REG;
SegManager *segMan = new SegManager(_resMan);
@@ -227,7 +226,7 @@ Common::Error SciEngine::run() {
_features = new GameFeatures(segMan, _kernel);
// Only SCI0, SCI01 and SCI1 EGA games used a parser
- _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan, false) : NULL;
+ _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA_ONLY) ? new Vocabulary(_resMan, false) : NULL;
// Also, XMAS1990 apparently had a parser too. Refer to http://forums.scummvm.org/viewtopic.php?t=9135
if (getGameId() == GID_CHRISTMAS1990)
_vocabulary = new Vocabulary(_resMan, false);
@@ -250,7 +249,6 @@ Common::Error SciEngine::run() {
warning("Could not get game object, aborting...");
return Common::kUnknownError;
}
- _gameSuperClassAddress = gameObject->getSuperClassSelector();
script_adjust_opcode_formats();
@@ -261,11 +259,12 @@ Common::Error SciEngine::run() {
syncSoundSettings();
syncIngameAudioOptions();
+ // Load our Mac executable here for icon bar palettes and high-res fonts
+ loadMacExecutable();
+
// Initialize all graphics related subsystems
initGraphics();
- debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
-
// Patch in our save/restore code, so that dialogs are replaced
patchGameSaveRestore();
setLauncherLanguage();
@@ -424,34 +423,66 @@ static byte patchGameRestoreSave[] = {
0x76, // push0
0x38, 0xff, 0xff, // pushi -1
0x76, // push0
- 0x43, 0xff, 0x06, // call kRestoreGame/kSaveGame (will get fixed directly)
+ 0x43, 0xff, 0x06, // callk kRestoreGame/kSaveGame (will get changed afterwards)
+ 0x48, // ret
+};
+
+// SCI2 version: Same as above, but the second parameter to callk is a word
+static byte patchGameRestoreSaveSci2[] = {
+ 0x39, 0x03, // pushi 03
+ 0x76, // push0
+ 0x38, 0xff, 0xff, // pushi -1
+ 0x76, // push0
+ 0x43, 0xff, 0x06, 0x00, // callk kRestoreGame/kSaveGame (will get changed afterwards)
+ 0x48, // ret
+};
+
+// SCI21 version: Same as above, but the second parameter to callk is a word
+static byte patchGameRestoreSaveSci21[] = {
+ 0x39, 0x04, // pushi 04
+ 0x76, // push0 // 0: save, 1: restore (will get changed afterwards)
+ 0x76, // push0
+ 0x38, 0xff, 0xff, // pushi -1
+ 0x76, // push0
+ 0x43, 0xff, 0x08, 0x00, // callk kSave (will get changed afterwards)
0x48, // ret
};
+static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) {
+ Script *script = segMan->getScript(methodAddress.segment);
+ byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.offset));
+ if (getSciVersion() <= SCI_VERSION_1_1)
+ memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
+ else // SCI2+
+ memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
+ patchPtr[8] = id;
+}
+
+static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
+ Script *script = segMan->getScript(methodAddress.segment);
+ byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.offset));
+ memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21));
+ if (doRestore)
+ patchPtr[2] = 0x78; // push1
+ patchPtr[9] = id;
+}
+
void SciEngine::patchGameSaveRestore() {
SegManager *segMan = _gamestate->_segMan;
const Object *gameObject = segMan->getObject(_gameObjectAddress);
- const uint16 gameMethodCount = gameObject->getMethodCount();
- const Object *gameSuperObject = segMan->getObject(_gameSuperClassAddress);
+ const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector());
if (!gameSuperObject)
gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510
- const uint16 gameSuperMethodCount = gameSuperObject->getMethodCount();
- reg_t methodAddress;
- const uint16 kernelCount = _kernel->getKernelNamesSize();
- const byte *scriptRestorePtr = NULL;
byte kernelIdRestore = 0;
- const byte *scriptSavePtr = NULL;
byte kernelIdSave = 0;
- // this feature is currently not supported on SCI32
- if (getSciVersion() >= SCI_VERSION_2)
- return;
-
switch (_gameId) {
- case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs
- case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required
case GID_HOYLE1: // gets confused, although the game doesnt support saving/restoring at all
case GID_HOYLE2: // gets confused, see hoyle1
+ case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required
+ case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs
+ case GID_PHANTASMAGORIA: // has custom save/load code
+ case GID_SHIVERS: // has custom save/load code
return;
default:
break;
@@ -460,61 +491,53 @@ void SciEngine::patchGameSaveRestore() {
if (ConfMan.getBool("sci_originalsaveload"))
return;
- for (uint16 kernelNr = 0; kernelNr < kernelCount; kernelNr++) {
+ uint16 kernelNamesSize = _kernel->getKernelNamesSize();
+ for (uint16 kernelNr = 0; kernelNr < kernelNamesSize; kernelNr++) {
Common::String kernelName = _kernel->getKernelName(kernelNr);
if (kernelName == "RestoreGame")
kernelIdRestore = kernelNr;
if (kernelName == "SaveGame")
kernelIdSave = kernelNr;
+ if (kernelName == "Save")
+ kernelIdSave = kernelIdRestore = kernelNr;
}
- // Search for gameobject-superclass ::restore
- for (uint16 methodNr = 0; methodNr < gameSuperMethodCount; methodNr++) {
+ // Search for gameobject superclass ::restore
+ uint16 gameSuperObjectMethodCount = gameSuperObject->getMethodCount();
+ for (uint16 methodNr = 0; methodNr < gameSuperObjectMethodCount; methodNr++) {
uint16 selectorId = gameSuperObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "restore") {
- methodAddress = gameSuperObject->getFunction(methodNr);
- Script *script = segMan->getScript(methodAddress.segment);
- scriptRestorePtr = script->getBuf(methodAddress.offset);
+ if (kernelIdSave != kernelIdRestore)
+ patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore);
+ else
+ patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore, true);
}
- if (methodName == "save") {
- methodAddress = gameSuperObject->getFunction(methodNr);
- Script *script = segMan->getScript(methodAddress.segment);
- scriptSavePtr = script->getBuf(methodAddress.offset);
+ else if (methodName == "save") {
+ if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
+ if (kernelIdSave != kernelIdRestore)
+ patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave);
+ else
+ patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false);
+ }
}
}
- // Search for gameobject ::save, if there is one patch that one instead
- for (uint16 methodNr = 0; methodNr < gameMethodCount; methodNr++) {
+ // Search for gameobject ::save, if there is one patch that one too
+ uint16 gameObjectMethodCount = gameObject->getMethodCount();
+ for (uint16 methodNr = 0; methodNr < gameObjectMethodCount; methodNr++) {
uint16 selectorId = gameObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "save") {
- methodAddress = gameObject->getFunction(methodNr);
- Script *script = segMan->getScript(methodAddress.segment);
- scriptSavePtr = script->getBuf(methodAddress.offset);
+ if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
+ if (kernelIdSave != kernelIdRestore)
+ patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave);
+ else
+ patchGameSaveRestoreCodeSci21(segMan, gameObject->getFunction(methodNr), kernelIdSave, false);
+ }
break;
}
}
-
- switch (_gameId) {
- case GID_FAIRYTALES: // fairy tales automatically saves w/o dialog
- scriptSavePtr = NULL;
- default:
- break;
- }
-
- if (scriptRestorePtr) {
- // Now patch in our code
- byte *patchPtr = const_cast<byte *>(scriptRestorePtr);
- memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
- patchPtr[8] = kernelIdRestore;
- }
- if (scriptSavePtr) {
- // Now patch in our code
- byte *patchPtr = const_cast<byte *>(scriptSavePtr);
- memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
- patchPtr[8] = kernelIdSave;
- }
}
bool SciEngine::initGame() {
@@ -552,9 +575,8 @@ bool SciEngine::initGame() {
}
// Reset parser
- if (_vocabulary) {
+ if (_vocabulary)
_vocabulary->reset();
- }
_gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis();
@@ -620,7 +642,7 @@ void SciEngine::initGraphics() {
_gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
_gfxCursor->init(_gfxCoordAdjuster, _eventMan);
_gfxCompare = new GfxCompare(_gamestate->_segMan, _kernel, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
- _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, _resMan->isVGA());
+ _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette);
_gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _kernel, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio);
_gfxPaint = _gfxPaint16;
_gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions);
@@ -755,6 +777,16 @@ bool SciEngine::isCD() const {
return _gameDescription->flags & ADGF_CD;
}
+bool SciEngine::isBE() const{
+ switch(_gameDescription->platform) {
+ case Common::kPlatformAmiga:
+ case Common::kPlatformMacintosh:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool SciEngine::hasMacIconBar() const {
return _resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1 &&
(getGameId() == GID_KQ6 || getGameId() == GID_FREDDYPHARKAS);
@@ -857,4 +889,34 @@ void SciEngine::syncIngameAudioOptions() {
}
}
+void SciEngine::loadMacExecutable() {
+ if (getPlatform() != Common::kPlatformMacintosh || getSciVersion() < SCI_VERSION_1_EARLY || getSciVersion() > SCI_VERSION_1_1)
+ return;
+
+ Common::String filename;
+
+ switch (getGameId()) {
+ case GID_KQ6:
+ filename = "King's Quest VI";
+ break;
+ case GID_FREDDYPHARKAS:
+ filename = "Freddy Pharkas";
+ break;
+ default:
+ break;
+ }
+
+ if (filename.empty())
+ return;
+
+ if (!_macExecutable.open(filename) || !_macExecutable.hasResFork()) {
+ // KQ6/Freddy require the executable to load their icon bar palettes
+ if (hasMacIconBar())
+ error("Could not load Mac resource fork '%s'", filename.c_str());
+
+ // TODO: Show some sort of warning dialog saying they can't get any
+ // high-res Mac fonts, when we get to that point ;)
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 9404425af6..cd50b2402c 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -27,6 +27,7 @@
#define SCI_H
#include "engines/engine.h"
+#include "common/macresman.h"
#include "common/util.h"
#include "common/random.h"
#include "sci/engine/vm_types.h" // for Selector
@@ -76,7 +77,6 @@ class GfxText16;
class GfxTransitions;
#ifdef ENABLE_SCI32
-class SciGui32;
class RobotDecoder;
class GfxFrameout;
#endif
@@ -179,20 +179,24 @@ enum SciGameId {
GID_FANMADE // FIXME: Do we really need/want this?
};
-/** SCI versions */
+/**
+ * SCI versions
+ * For more information, check here:
+ * http://wiki.scummvm.org/index.php/Sierra_Game_Versions#SCI_Games
+ */
enum SciVersion {
SCI_VERSION_NONE,
- SCI_VERSION_0_EARLY, // Early KQ4, 1988 xmas card
+ SCI_VERSION_0_EARLY, // KQ4 early, LSL2 early, XMAS card 1988
SCI_VERSION_0_LATE, // KQ4, LSL2, LSL3, SQ3 etc
SCI_VERSION_01, // KQ1 and multilingual games (S.old.*)
- SCI_VERSION_1_EGA, // EGA with parser, QFG2
- SCI_VERSION_1_EARLY, // KQ5. (EGA/VGA)
- SCI_VERSION_1_MIDDLE, // LSL1, JONESCD. (EGA?/VGA)
- SCI_VERSION_1_LATE, // ECO1, LSL5. (EGA/VGA)
- SCI_VERSION_1_1, // KQ6, ECO2
- SCI_VERSION_2, // GK1, PQ4 (Floppy), QFG4 (Floppy)
- SCI_VERSION_2_1, // GK2, KQ7, SQ6, Torin
- SCI_VERSION_3 // LSL7, RAMA, Lighthouse
+ SCI_VERSION_1_EGA_ONLY, // SCI 1 EGA with parser (i.e. QFG2 only)
+ SCI_VERSION_1_EARLY, // KQ5 floppy, SQ4 floppy, XMAS card 1990, Fairy tales, Jones floppy
+ SCI_VERSION_1_MIDDLE, // LSL1, Jones CD
+ SCI_VERSION_1_LATE, // Dr. Brain 1, EcoQuest 1, Longbow, PQ3, SQ1, LSL5, KQ5 CD
+ SCI_VERSION_1_1, // Dr. Brain 2, EcoQuest 1 CD, EcoQuest 2, KQ6, QFG3, SQ4CD, XMAS 1992 and many more
+ SCI_VERSION_2, // GK1, PQ4 floppy, QFG4 floppy
+ SCI_VERSION_2_1, // GK2, KQ7, LSL6 hires, MUMG Deluxe, Phantasmagoria 1, PQ4CD, PQ:SWAT, QFG4CD, Shivers 1, SQ6, Torin
+ SCI_VERSION_3 // LSL7, Lighthouse, RAMA, Phantasmagoria 2
};
/** Supported languages */
@@ -233,6 +237,10 @@ public:
Common::Platform getPlatform() const;
bool isDemo() const;
bool isCD() const;
+
+ /** Returns true if the game's original platform is big-endian. */
+ bool isBE() const;
+
bool hasMacIconBar() const;
inline ResourceManager *getResMan() const { return _resMan; }
@@ -241,7 +249,6 @@ public:
inline Vocabulary *getVocabulary() const { return _vocabulary; }
inline EventManager *getEventManager() const { return _eventMan; }
inline reg_t getGameObject() const { return _gameObjectAddress; }
- inline reg_t getGameSuperClassAddress() const { return _gameSuperClassAddress; }
Common::RandomSource &getRNG() { return _rng; }
@@ -323,6 +330,8 @@ public:
DebugState _debugState;
+ Common::MacResManager *getMacExecutable() { return &_macExecutable; }
+
private:
/**
* Initializes a SCI game
@@ -349,6 +358,11 @@ private:
*/
void exitGame();
+ /**
+ * Loads the Mac executable for SCI1 games
+ */
+ void loadMacExecutable();
+
void initStackBaseWithSelector(Selector selector);
bool gameHasFanMadePatch();
@@ -363,9 +377,9 @@ private:
int16 _vocabularyLanguage;
EventManager *_eventMan;
reg_t _gameObjectAddress; /**< Pointer to the game object */
- reg_t _gameSuperClassAddress; // Address of the super class of the game object
Console *_console;
Common::RandomSource _rng;
+ Common::MacResManager _macExecutable;
};
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index 73f471b247..53311b4252 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -195,7 +195,7 @@ static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSiz
uint32 tag = audioStream->readUint32BE();
- if (tag != MKID_BE('SOL\0')) {
+ if (tag != MKTAG('S','O','L',0)) {
warning("No 'SOL' FourCC found");
return false;
}
@@ -290,17 +290,17 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
Common::SeekableReadStream *compressedStream = new Common::MemoryReadStream(compressedData, audioRes->size, DisposeAfterUse::YES);
switch (audioCompressionType) {
- case MKID_BE('MP3 '):
+ case MKTAG('M','P','3',' '):
#ifdef USE_MAD
audioSeekStream = Audio::makeMP3Stream(compressedStream, DisposeAfterUse::YES);
#endif
break;
- case MKID_BE('OGG '):
+ case MKTAG('O','G','G',' '):
#ifdef USE_VORBIS
audioSeekStream = Audio::makeVorbisStream(compressedStream, DisposeAfterUse::YES);
#endif
break;
- case MKID_BE('FLAC'):
+ case MKTAG('F','L','A','C'):
#ifdef USE_FLAC
audioSeekStream = Audio::makeFLACStream(compressedStream, DisposeAfterUse::YES);
#endif
@@ -319,7 +319,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
data = readSOLAudio(&dataStream, size, audioFlags, flags);
}
- } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('RIFF')) {
+ } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('R','I','F','F')) {
// WAVE detected
Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
@@ -331,7 +331,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
waveStream->seek(0, SEEK_SET);
audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES);
- } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) {
+ } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('F','O','R','M')) {
// AIFF detected
Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index 057b7c177f..65a8e2e3da 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -55,7 +55,7 @@ public:
virtual ~MidiDriver_AdLib() { }
// MidiDriver
- int open(bool isSCI0);
+ int openAdLib(bool isSCI0);
void close();
void send(uint32 b);
MidiChannel *allocateChannel() { return NULL; }
@@ -215,7 +215,7 @@ static const int ym3812_note[13] = {
0x2ae
};
-int MidiDriver_AdLib::open(bool isSCI0) {
+int MidiDriver_AdLib::openAdLib(bool isSCI0) {
int rate = _mixer->getOutputRate();
_stereo = STEREO;
@@ -273,10 +273,6 @@ void MidiDriver_AdLib::send(uint32 b) {
case 0x90:
noteOn(channel, op1, op2);
break;
- case 0xe0:
- _channels[channel].pitchWheel = (op1 & 0x7f) | ((op2 & 0x7f) << 7);
- renewNotes(channel, true);
- break;
case 0xb0:
switch (op1) {
case 0x07:
@@ -321,7 +317,9 @@ void MidiDriver_AdLib::send(uint32 b) {
case 0xa0: // Polyphonic key pressure (aftertouch)
case 0xd0: // Channel pressure (aftertouch)
break;
- case 0xf0: // SysEx, ignore it
+ case 0xe0:
+ _channels[channel].pitchWheel = (op1 & 0x7f) | ((op2 & 0x7f) << 7);
+ renewNotes(channel, true);
break;
default:
warning("ADLIB: Unknown event %02x", command);
@@ -828,7 +826,7 @@ int MidiPlayer_AdLib::open(ResourceManager *resMan) {
return -1;
}
- return static_cast<MidiDriver_AdLib *>(_driver)->open(_version <= SCI_VERSION_0_LATE);
+ return static_cast<MidiDriver_AdLib *>(_driver)->openAdLib(_version <= SCI_VERSION_0_LATE);
}
void MidiPlayer_AdLib::close() {
diff --git a/engines/sci/sound/drivers/amigamac.cpp b/engines/sci/sound/drivers/amigamac.cpp
index 0ec4c283f7..d64dfac23c 100644
--- a/engines/sci/sound/drivers/amigamac.cpp
+++ b/engines/sci/sound/drivers/amigamac.cpp
@@ -34,7 +34,7 @@
namespace Sci {
-/* #define DEBUG */
+//#define DEBUG
class MidiDriver_AmigaMac : public MidiDriver_Emulated {
public:
@@ -289,9 +289,9 @@ void MidiDriver_AmigaMac::playInstrument(int16 *dest, Voice *channel, int count)
void MidiDriver_AmigaMac::changeInstrument(int channel, int instrument) {
#ifdef DEBUG
if (_bank.instruments[instrument][0])
- debugN("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument]->name, instrument);
+ debugN("Amiga/Mac driver: Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument].name, instrument);
else
- warning("[sfx:seq:amiga] instrument %i does not exist (channel %i)", instrument, channel);
+ warning("Amiga/Mac driver: instrument %i does not exist (channel %i)", instrument, channel);
#endif
_channels[channel].instrument = instrument;
}
@@ -326,7 +326,7 @@ void MidiDriver_AmigaMac::stopNote(int ch, int note) {
if (channel == kChannels) {
#ifdef DEBUG
- warning("[sfx:seq:amiga] cannot stop note %i on channel %i", note, ch);
+ warning("Amiga/Mac driver: cannot stop note %i on channel %i", note, ch);
#endif
return;
}
@@ -366,7 +366,7 @@ void MidiDriver_AmigaMac::setOutputFrac(int voice) {
fnote += instrument->transpose;
if (fnote < 0 || fnote > 127) {
- warning("[sfx:seq:amiga] illegal note %i", fnote);
+ warning("Amiga/Mac driver: illegal note %i", fnote);
return;
}
} else
@@ -403,14 +403,14 @@ void MidiDriver_AmigaMac::startNote(int ch, int note, int velocity) {
int channel;
if (_channels[ch].instrument < 0 || _channels[ch].instrument > 255) {
- warning("[sfx:seq:amiga] invalid instrument %i on channel %i", _channels[ch].instrument, ch);
+ warning("Amiga/Mac driver: invalid instrument %i on channel %i", _channels[ch].instrument, ch);
return;
}
InstrumentSample *instrument = findInstrument(_channels[ch].instrument, note);
if (!instrument) {
- warning("[sfx:seq:amiga] instrument %i does not exist", _channels[ch].instrument);
+ warning("Amiga/Mac driver: instrument %i does not exist", _channels[ch].instrument);
return;
}
@@ -419,7 +419,7 @@ void MidiDriver_AmigaMac::startNote(int ch, int note, int velocity) {
break;
if (channel == kChannels) {
- warning("[sfx:seq:amiga] could not find a free channel");
+ warning("Amiga/Mac driver: could not find a free channel");
return;
}
@@ -447,14 +447,14 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
byte header[61];
if (file.read(header, 61) < 61) {
- warning("[sfx:seq:amiga] failed to read instrument header");
+ warning("Amiga/Mac driver: failed to read instrument header");
return NULL;
}
int seg_size[3];
- seg_size[0] = READ_BE_UINT16(header + 35) * 2;
- seg_size[1] = READ_BE_UINT16(header + 41) * 2;
- seg_size[2] = READ_BE_UINT16(header + 47) * 2;
+ seg_size[0] = (int16)READ_BE_UINT16(header + 35) * 2;
+ seg_size[1] = (int16)READ_BE_UINT16(header + 41) * 2;
+ seg_size[2] = (int16)READ_BE_UINT16(header + 47) * 2;
InstrumentSample *instrument = new InstrumentSample;
@@ -489,18 +489,18 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
instrument->name[29] = 0;
#ifdef DEBUG
- debugN("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n",
+ debugN("Amiga/Mac driver: Reading instrument %i: \"%s\" (%i bytes)\n",
*id, instrument->name, size);
debugN(" Mode: %02x\n", instrument->mode);
debugN(" Looping: %s\n", instrument->mode & kModeLoop ? "on" : "off");
debugN(" Pitch changes: %s\n", instrument->mode & kModePitch ? "on" : "off");
debugN(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]);
- debugN(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43));
+ debugN(" Segment offsets: 0 %i %i\n", loop_offset, (int32)READ_BE_UINT32(header + 43));
#endif
instrument->samples = (int8 *) malloc(size + 1);
if (file.read(instrument->samples, size) < (unsigned int)size) {
- warning("[sfx:seq:amiga] failed to read instrument samples");
+ warning("Amiga/Mac driver: failed to read instrument samples");
free(instrument->samples);
delete instrument;
return NULL;
@@ -512,14 +512,14 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
if (instrument->mode & kModeLoop) {
if (loop_offset + seg_size[1] > size) {
#ifdef DEBUG
- warning("[sfx:seq:amiga] looping samples extend %i bytes past end of sample block",
+ warning("Amiga/Mac driver: looping samples extend %i bytes past end of sample block",
loop_offset + seg_size[1] - size);
#endif
seg_size[1] = size - loop_offset;
}
if (seg_size[1] < 0) {
- warning("[sfx:seq:amiga] invalid looping point");
+ warning("Amiga/Mac driver: invalid looping point");
free(instrument->samples);
delete instrument;
return NULL;
@@ -666,26 +666,42 @@ void MidiDriver_AmigaMac::send(uint32 b) {
case 0x07:
_channels[channel].volume = op2;
break;
- case 0x0a:
+ case 0x0a: // pan
+ // TODO
#ifdef DEBUG
- warning("[sfx:seq:amiga] ignoring pan 0x%02x event for channel %i", op2, channel);
+ warning("Amiga/Mac driver: ignoring pan 0x%02x event for channel %i", op2, channel);
#endif
break;
+ case 0x40: // hold
+ // TODO
+#ifdef DEBUG
+ warning("Amiga/Mac driver: ignoring hold 0x%02x event for channel %i", op2, channel);
+#endif
+ break;
+ case 0x4b: // voice mapping
+ break;
+ case 0x4e: // velocity
+ break;
case 0x7b:
stopChannel(channel);
break;
default:
- warning("[sfx:seq:amiga] unknown control event 0x%02x", op1);
+ //warning("Amiga/Mac driver: unknown control event 0x%02x", op1);
+ break;
}
break;
case 0xc0:
changeInstrument(channel, op1);
break;
+ // The original MIDI driver from sierra ignores aftertouch completely, so should we
+ case 0xa0: // Polyphonic key pressure (aftertouch)
+ case 0xd0: // Channel pressure (aftertouch)
+ break;
case 0xe0:
pitchWheel(channel, (op2 << 7) | op1);
break;
default:
- warning("[sfx:seq:amiga] unknown event %02x", command);
+ warning("Amiga/Mac driver: unknown event %02x", command);
}
}
@@ -738,7 +754,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
byte header[40];
if (file.read(header, 40) < 40) {
- warning("[sfx:seq:amiga] failed to read header of file bank.001");
+ warning("Amiga/Mac driver: failed to read header of file bank.001");
return false;
}
@@ -746,7 +762,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
strncpy(_bank.name, (char *) header + 8, 29);
_bank.name[29] = 0;
#ifdef DEBUG
- debugN("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
+ debugN("Amiga/Mac driver: Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
#endif
for (uint i = 0; i < _bank.size; i++) {
@@ -754,12 +770,12 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
InstrumentSample *instrument = readInstrumentSCI0(file, &id);
if (!instrument) {
- warning("[sfx:seq:amiga] failed to read bank.001");
+ warning("Amiga/Mac driver: failed to read bank.001");
return false;
}
if (id < 0 || id > 255) {
- warning("[sfx:seq:amiga] Error: instrument ID out of bounds");
+ warning("Amiga/Mac driver: Error: instrument ID out of bounds");
return false;
}
@@ -777,7 +793,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
byte header[40];
if (file.read(header, 40) < 40) {
- warning("[sfx:seq:amiga] failed to read header of file patch.200");
+ warning("Amiga/Mac driver: failed to read header of file patch.200");
return false;
}
@@ -785,7 +801,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
strncpy(_bank.name, (char *) header + 8, 29);
_bank.name[29] = 0;
#ifdef DEBUG
- debugN("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
+ debugN("Amiga/Mac driver: Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
#endif
Common::Array<uint32> instrumentOffsets;
@@ -848,7 +864,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
instrument->samples = (int8 *)malloc(size + 1);
if (file.read(instrument->samples, size) < size) {
- warning("[sfx:seq:amiga] failed to read instrument sample");
+ warning("Amiga/Mac driver: failed to read instrument sample");
free(instrument->samples);
delete instrument;
continue;
diff --git a/engines/sci/sound/drivers/cms.cpp b/engines/sci/sound/drivers/cms.cpp
index ff38e1c554..051fa7f1fd 100644
--- a/engines/sci/sound/drivers/cms.cpp
+++ b/engines/sci/sound/drivers/cms.cpp
@@ -785,7 +785,7 @@ public:
int open(ResourceManager *resMan) {
if (_driver)
- return MERR_ALREADY_OPEN;
+ return MidiDriver::MERR_ALREADY_OPEN;
_driver = new MidiDriver_CMS(g_system->getMixer(), resMan);
int driverRetVal = _driver->open();
diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp
index ce48b7f1f8..971c2ff92d 100644
--- a/engines/sci/sound/drivers/fb01.cpp
+++ b/engines/sci/sound/drivers/fb01.cpp
@@ -129,7 +129,7 @@ private:
MidiPlayer_Fb01::MidiPlayer_Fb01(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _timerParam(NULL), _timerProc(NULL) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
- _driver = createMidi(dev);
+ _driver = MidiDriver::createMidi(dev);
_sysExBuf[0] = 0x43;
_sysExBuf[1] = 0x75;
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 08e93d3213..9eef867aeb 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -28,9 +28,9 @@
#include "common/config-manager.h"
#include "common/file.h"
#include "common/memstream.h"
+#include "common/system.h"
#include "audio/fmopl.h"
-#include "audio/softsynth/emumidi.h"
#include "sci/resource.h"
#include "sci/engine/features.h"
@@ -104,7 +104,7 @@ private:
uint8 volume;
Channel() : mappedPatch(MIDI_UNMAPPED), patch(MIDI_UNMAPPED), velocityMapIdx(0), playing(false),
- keyShift(0), volAdjust(0), pan(0x80), hold(0), volume(0x7f) { }
+ keyShift(0), volAdjust(0), pan(0x40), hold(0), volume(0x7f) { }
};
bool _isMt32;
@@ -132,7 +132,7 @@ private:
MidiPlayer_Midi::MidiPlayer_Midi(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _isMt32(false), _hasReverb(false), _useMT32Track(true) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
- _driver = createMidi(dev);
+ _driver = MidiDriver::createMidi(dev);
if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32"))
_isMt32 = true;
@@ -248,11 +248,17 @@ void MidiPlayer_Midi::controlChange(int channel, int control, int value) {
_channels[channel].hold = value;
break;
+ case 0x4b: // voice mapping
+ break;
+ case 0x4e: // velocity
+ break;
case 0x7b:
if (!_channels[channel].playing)
return;
_channels[channel].playing = false;
+ default:
+ break;
}
_driver->send(0xb0 | channel, control, value);
@@ -387,7 +393,7 @@ int MidiPlayer_Midi::getVolume() {
void MidiPlayer_Midi::setReverb(int8 reverb) {
assert(reverb < kReverbConfigNr);
-
+
if (_hasReverb && (_reverb != reverb))
sendMt32SysEx(0x100001, _reverbConfig[reverb], 3, true);
@@ -604,41 +610,83 @@ void MidiPlayer_Midi::readMt32DrvData() {
if (f.open("MT32.DRV")) {
int size = f.size();
- assert(size >= 166);
-
- // Send before-SysEx text
- f.seek(0x59);
+ // Skip before-SysEx text
+ if (size == 1773 || size == 1759 || size == 1747) // XMAS88 / KQ4 early (0.000.253 / 0.000.274)
+ f.seek(0x59);
+ else if (size == 2771) // LSL2 early
+ f.seek(0x29);
+ else
+ error("Unknown MT32.DRV size (%d)", size);
// Skip 2 extra 0 bytes in some drivers
if (f.readUint16LE() != 0)
f.seek(-2, SEEK_CUR);
+ // Send before-SysEx text
sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
- // Send after-SysEx text (SSCI sends this before every song)
- sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
+ if (size != 2271) {
+ // Send after-SysEx text (SSCI sends this before every song).
+ // There aren't any SysEx calls in old drivers, so this can
+ // be sent right after the before-SysEx text.
+ sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
+ } else {
+ // Skip the after-SysEx text in the newer patch version, we'll send
+ // it after the SysEx messages are sent.
+ f.skip(20);
+ }
- // Save goodbye message
+ // Save goodbye message. This isn't a C string, so it may not be
+ // nul-terminated.
f.read(_goodbyeMsg, 20);
// Set volume
byte volume = CLIP<uint16>(f.readUint16LE(), 0, 100);
setMt32Volume(volume);
- byte reverbSysEx[13];
- // This old driver should have a full reverb SysEx
- if ((f.read(reverbSysEx, 13) != 13) || (reverbSysEx[0] != 0xf0) || (reverbSysEx[12] != 0xf7))
- error("Error reading MT32.DRV");
+ if (size == 2771) {
+ // MT32.DRV in LSL2 early contains more data, like a normal patch
+ byte reverb = f.readByte();
- // Send reverb SysEx
- sysEx(reverbSysEx + 1, 11);
- _hasReverb = false;
+ _hasReverb = true;
- f.seek(0x29);
+ // Skip reverb SysEx message
+ f.skip(11);
- // Read AdLib->MT-32 patch map
- for (int i = 0; i < 48; i++) {
- _patchMap[i] = f.readByte();
+ // Read reverb data (stored vertically - patch #3117434)
+ for (int j = 0; j < 3; ++j) {
+ for (int i = 0; i < kReverbConfigNr; i++) {
+ _reverbConfig[i][j] = f.readByte();
+ }
+ }
+
+ f.skip(2235); // skip driver code
+
+ // Patches 1-48
+ sendMt32SysEx(0x50000, static_cast<Common::SeekableReadStream *>(&f), 256);
+ sendMt32SysEx(0x50200, static_cast<Common::SeekableReadStream *>(&f), 128);
+
+ setReverb(reverb);
+
+ // Send the after-SysEx text
+ f.seek(0x3d);
+ sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
+ } else {
+ byte reverbSysEx[13];
+ // This old driver should have a full reverb SysEx
+ if ((f.read(reverbSysEx, 13) != 13) || (reverbSysEx[0] != 0xf0) || (reverbSysEx[12] != 0xf7))
+ error("Error reading MT32.DRV");
+
+ // Send reverb SysEx
+ sysEx(reverbSysEx + 1, 11);
+ _hasReverb = false;
+
+ f.seek(0x29);
+
+ // Read AdLib->MT-32 patch map
+ for (int i = 0; i < 48; i++) {
+ _patchMap[i] = f.readByte();
+ }
}
f.close();
@@ -913,7 +961,7 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
// TODO: The MT-32 <-> GM mapping hasn't been worked on for SCI1 games. Throw
// a warning to the user
- if (getSciVersion() >= SCI_VERSION_1_EGA)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
warning("The automatic mapping for General MIDI hasn't been worked on for "
"SCI1 games. Music might sound wrong or broken. Please choose another "
"music driver for this game (e.g. Adlib or MT-32) if you are "
diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h
index f745d62716..2038725dbe 100644
--- a/engines/sci/sound/drivers/mididriver.h
+++ b/engines/sci/sound/drivers/mididriver.h
@@ -76,7 +76,7 @@ enum {
#define SCI_MIDI_CONTROLLER(status) ((status & 0xF0) == 0xB0)
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
protected:
MidiDriver *_driver;
int8 _reverb;
@@ -91,10 +91,8 @@ public:
virtual int open(ResourceManager *resMan) { return _driver->open(); }
virtual void close() { _driver->close(); }
virtual void send(uint32 b) { _driver->send(b); }
- uint32 getBaseTempo() { return _driver->getBaseTempo(); }
+ virtual uint32 getBaseTempo() { return _driver->getBaseTempo(); }
virtual bool hasRhythmChannel() const = 0;
- MidiChannel *allocateChannel() { return _driver->allocateChannel(); }
- MidiChannel *getPercussionChannel() { return _driver->getPercussionChannel(); }
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { _driver->setTimerCallback(timer_param, timer_proc); }
virtual byte getPlayId() const = 0;
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index f0963e7d64..c7743ac587 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -75,7 +75,7 @@ void SciMusic::init() {
deviceFlags |= MDT_PREFER_GM;
// Currently our CMS implementation only supports SCI1(.1)
- if (getSciVersion() >= SCI_VERSION_1_EGA && getSciVersion() <= SCI_VERSION_1_1)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY && getSciVersion() <= SCI_VERSION_1_1)
deviceFlags |= MDT_CMS;
uint32 dev = MidiDriver::detectDevice(deviceFlags);
@@ -303,7 +303,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
pSnd->hCurrentAud = Audio::SoundHandle();
} else {
// play MIDI track
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->soundType = Audio::Mixer::kMusicSoundType;
if (pSnd->pMidiParser == NULL) {
pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this);
@@ -318,10 +318,22 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
pSnd->pMidiParser->mainThreadBegin();
+ // loadMusic() below calls jumpToTick.
+ // Disable sound looping and hold before jumpToTick is called,
+ // otherwise the song may keep looping forever when it ends in
+ // jumpToTick (e.g. LSL3, when going left from room 210).
+ uint16 prevLoop = pSnd->loop;
+ int16 prevHold = pSnd->hold;
+ pSnd->loop = 0;
+ pSnd->hold = -1;
+
pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
pSnd->reverb = pSnd->pMidiParser->getSongReverb();
+
+ // Restore looping and hold
+ pSnd->loop = prevLoop;
+ pSnd->hold = prevHold;
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
}
@@ -428,26 +440,52 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
}
} else {
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
+
+ if (pSnd->status != kSoundPaused) {
+ // Stop any in progress music fading, as that will reset the
+ // volume of the sound channels that the faded song occupies..
+ // Fixes bug #3266480 and partially fixes bug #3041738.
+ for (uint i = 0; i < playListCount; i++) {
+ // Is another MIDI song being faded? If yes, stop it
+ // immediately instead
+ if (_playList[i]->fadeStep && _playList[i]->pMidiParser) {
+ _playList[i]->status = kSoundStopped;
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ _playList[i]->isQueued = false;
+ _playList[i]->pMidiParser->stop();
+ freeChannels(_playList[i]);
+ _playList[i]->fadeStep = 0;
+ }
+ }
+ }
+
pSnd->pMidiParser->tryToOwnChannels();
if (pSnd->status != kSoundPaused)
pSnd->pMidiParser->sendInitCommands();
pSnd->pMidiParser->setVolume(pSnd->volume);
- if (pSnd->status == kSoundStopped) {
+
+ // Disable sound looping and hold before jumpToTick is called,
+ // otherwise the song may keep looping forever when it ends in jumpToTick.
+ // This is needed when loading saved games, or when a game
+ // stops the same sound twice (e.g. LSL3 Amiga, going left from
+ // room 210 to talk with Kalalau). Fixes bugs #3083151 and #3106107.
+ uint16 prevLoop = pSnd->loop;
+ int16 prevHold = pSnd->hold;
+ pSnd->loop = 0;
+ pSnd->hold = -1;
+
+ if (pSnd->status == kSoundStopped)
pSnd->pMidiParser->jumpToTick(0);
- } else {
- // Disable sound looping before fast forwarding to the last position,
- // when loading a saved game. Fixes bug #3083151.
- uint16 prevLoop = pSnd->loop;
- pSnd->loop = 0;
+ else
// Fast forward to the last position and perform associated events when loading
pSnd->pMidiParser->jumpToTick(pSnd->ticker, true, true, true);
- // Restore looping
- pSnd->loop = prevLoop;
- }
+
+ // Restore looping and hold
+ pSnd->loop = prevLoop;
+ pSnd->hold = prevHold;
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
@@ -463,7 +501,7 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
_pMixer->stopHandle(pSnd->hCurrentAud);
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
// We shouldn't call stop in case it's paused, otherwise we would send
// allNotesOff() again
@@ -471,7 +509,6 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
pSnd->pMidiParser->stop();
freeChannels(pSnd);
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
pSnd->fadeStep = 0; // end fading, if fading was in progress
@@ -483,11 +520,10 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
// we simply ignore volume changes for samples, because sierra sci also
// doesn't support volume for samples via kDoSound
} else if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->setVolume(volume);
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
@@ -509,13 +545,12 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
pSnd->status = kSoundStopped;
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->unloadMusic();
pSnd->pMidiParser->mainThreadEnd();
delete pSnd->pMidiParser;
pSnd->pMidiParser = NULL;
- _mutex.unlock();
}
if (pSnd->pStreamAud) {
@@ -526,7 +561,7 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
pSnd->pLoopStream = 0;
}
- _mutex.lock();
+ Common::StackLock lock(_mutex);
uint sz = _playList.size(), i;
// Remove sound from playlist
for (i = 0; i < sz; i++) {
@@ -537,7 +572,6 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
break;
}
}
- _mutex.unlock();
}
void SciMusic::soundPause(MusicEntry *pSnd) {
@@ -560,12 +594,11 @@ void SciMusic::soundPause(MusicEntry *pSnd) {
_pMixer->pauseHandle(pSnd->hCurrentAud, true);
} else {
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->pause();
freeChannels(pSnd);
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
}
@@ -630,9 +663,11 @@ void SciMusic::printPlayList(Console *con) {
for (uint32 i = 0; i < _playList.size(); i++) {
MusicEntry *song = _playList[i];
- con->DebugPrintf("%d: %04x:%04x, resource id: %d, status: %s, %s type\n", i,
- PRINT_REG(song->soundObj), song->resourceId,
- musicStatus[song->status], song->pMidiParser ? "MIDI" : "digital audio");
+ con->DebugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n",
+ i, PRINT_REG(song->soundObj),
+ g_sci->getEngineState()->_segMan->getObjectName(song->soundObj),
+ song->resourceId, musicStatus[song->status],
+ song->pMidiParser ? "MIDI" : "digital audio");
}
}
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 45a3e09453..9ad964b67e 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -325,6 +325,14 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) {
return acc;
}
+ // If the current volume of the slot is the same as the target volume,
+ // return without performing any fading. This fixes the music in room
+ // 406 in KQ6 (bug #3267956), where the game scripts ask for the background
+ // music to be played, and then faded to volume 127 (but the music is
+ // already at volume 127) and subsequently stopped.
+ if (argc >= 4 && musicSlot->volume == CLIP<uint16>(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX))
+ return acc;
+
switch (argc) {
case 1: // SCI0
// SCI0 fades out all the time and when fadeout is done it will also
@@ -445,8 +453,16 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
if (musicSlot->fadeCompleted) {
musicSlot->fadeCompleted = false;
- // We need signal for sci0 at least in iceman as well (room 14, fireworks)
- writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ // We need signal for sci0 at least in iceman as well (room 14,
+ // fireworks).
+ // It is also needed in other games, e.g. LSL6 when talking to the
+ // receptionist (bug #3192166).
+ if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 95) {
+ // HACK: Don't set a signal here in the intro of Longbow, as that makes some dialog
+ // boxes disappear too soon (bug #3044844).
+ } else {
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ }
if (_soundVersion <= SCI_VERSION_0_LATE) {
processStopSound(obj, false);
} else {
diff --git a/engines/sci/util.cpp b/engines/sci/util.cpp
index f6a2465682..f346adddeb 100644
--- a/engines/sci/util.cpp
+++ b/engines/sci/util.cpp
@@ -30,25 +30,39 @@
namespace Sci {
+uint16 READ_SCIENDIAN_UINT16(const void *ptr) {
+ if (g_sci->isBE())
+ return READ_BE_UINT16(ptr);
+ else
+ return READ_LE_UINT16(ptr);
+}
+
+void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val) {
+ if (g_sci->isBE())
+ WRITE_BE_UINT16(ptr, val);
+ else
+ WRITE_LE_UINT16(ptr, val);
+}
+
uint16 READ_SCI11ENDIAN_UINT16(const void *ptr) {
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1)
return READ_BE_UINT16(ptr);
-
- return READ_LE_UINT16(ptr);
+ else
+ return READ_LE_UINT16(ptr);
}
uint16 READ_SCI32ENDIAN_UINT16(const void *ptr) {
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1)
return READ_BE_UINT16(ptr);
-
- return READ_LE_UINT16(ptr);
+ else
+ return READ_LE_UINT16(ptr);
}
uint32 READ_SCI11ENDIAN_UINT32(const void *ptr) {
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1)
return READ_BE_UINT32(ptr);
-
- return READ_LE_UINT32(ptr);
+ else
+ return READ_LE_UINT32(ptr);
}
void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val) {
diff --git a/engines/sci/util.h b/engines/sci/util.h
index d9ced5c9f6..7a2abb1873 100644
--- a/engines/sci/util.h
+++ b/engines/sci/util.h
@@ -30,6 +30,11 @@
namespace Sci {
+// Wrappers for reading/writing 16-bit values in the endianness
+// of the original game platform.
+uint16 READ_SCIENDIAN_UINT16(const void *ptr);
+void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val);
+
// Wrappers for reading integer values for SCI1.1+.
// Mac versions have big endian data for some fields.
uint16 READ_SCI11ENDIAN_UINT16(const void *ptr);
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index bf52de67d5..ecdce3bd6b 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -251,6 +251,11 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() {
_fileStream->skip(4); // unknown, almost always 0
uint16 frameX = _fileStream->readUint16();
uint16 frameY = _fileStream->readUint16();
+ // TODO: In v4 robot files, frameX and frameY have a different meaning.
+ // Set them both to 0 for v4 for now, so that robots in PQ:SWAT show up
+ // correctly.
+ if (_header.version == 4)
+ frameX = frameY = 0;
uint16 compressedSize = _fileStream->readUint16();
uint16 frameFragments = _fileStream->readUint16();
_fileStream->skip(4); // unknown
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 5906545917..13581c4b45 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -26,6 +26,7 @@
#include "common/system.h" // for setFocusRectangle/clearFocusRectangle
#include "scumm/scumm.h"
#include "scumm/actor.h"
+#include "scumm/actor_he.h"
#include "scumm/akos.h"
#include "scumm/boxes.h"
#include "scumm/charset.h"
@@ -75,7 +76,7 @@ void ActorHE::initActor(int mode) {
if (_vm->_game.heversion >= 61)
_flip = 0;
- _clipOverride = _vm->_actorClipOverride;
+ _clipOverride = ((ScummEngine_v60he *)_vm)->_actorClipOverride;
_auxBlock.reset();
}
@@ -241,7 +242,7 @@ void Actor::setActorWalkSpeed(uint newSpeedX, uint newSpeedY) {
int getAngleFromPos(int x, int y, bool useATAN) {
if (useATAN) {
double temp = atan2((double)x, (double)-y);
- return normalizeAngle((int)(temp * 180 / PI));
+ return normalizeAngle((int)(temp * 180 / M_PI));
} else {
if (ABS(y) * 2 < ABS(x)) {
if (x > 0)
@@ -1852,8 +1853,8 @@ void Actor::animateLimb(int limb, int f) {
byte *akos = _vm->getResourceAddress(rtCostume, _costume);
assert(akos);
- aksq = _vm->findResourceData(MKID_BE('AKSQ'), akos);
- akfo = _vm->findResourceData(MKID_BE('AKFO'), akos);
+ aksq = _vm->findResourceData(MKTAG('A','K','S','Q'), akos);
+ akfo = _vm->findResourceData(MKTAG('A','K','F','O'), akos);
size = _vm->getResourceDataSize(akfo) / 2;
@@ -2373,7 +2374,7 @@ void Actor::remapActorPaletteColor(int color, int new_color) {
return;
}
- akpl = _vm->findResourceData(MKID_BE('AKPL'), akos);
+ akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos);
if (!akpl) {
debugC(DEBUG_ACTORS, "Actor::remapActorPaletteColor: Can't remap actor %d, costume %d doesn't contain an AKPL block", _number, _costume);
return;
@@ -2408,7 +2409,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold)
return;
}
- akpl = _vm->findResourceData(MKID_BE('AKPL'), akos);
+ akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos);
if (!akpl) {
debugC(DEBUG_ACTORS, "Actor::remapActorPalette: Can't remap actor %d, costume %d doesn't contain an AKPL block", _number, _costume);
return;
@@ -2417,7 +2418,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold)
// Get the number palette entries
akpl_size = _vm->getResourceDataSize(akpl);
- rgbs = _vm->findResourceData(MKID_BE('RGBS'), akos);
+ rgbs = _vm->findResourceData(MKTAG('R','G','B','S'), akos);
if (!rgbs) {
debugC(DEBUG_ACTORS, "Actor::remapActorPalette: Can't remap actor %d costume %d doesn't contain an RGB block", _number, _costume);
@@ -2534,19 +2535,19 @@ void ScummEngine_v71he::postProcessAuxQueue() {
if (_game.heversion >= 72)
dy -= a->getElevation();
- const uint8 *akax = findResource(MKID_BE('AKAX'), cost);
+ const uint8 *akax = findResource(MKTAG('A','K','A','X'), cost);
assert(akax);
const uint8 *auxd = findPalInPals(akax, ae->subIndex) - _resourceHeaderSize;
assert(auxd);
- const uint8 *frel = findResourceData(MKID_BE('FREL'), auxd);
+ const uint8 *frel = findResourceData(MKTAG('F','R','E','L'), auxd);
if (frel) {
error("unhandled FREL block");
}
- const uint8 *disp = findResourceData(MKID_BE('DISP'), auxd);
+ const uint8 *disp = findResourceData(MKTAG('D','I','S','P'), auxd);
if (disp) {
error("unhandled DISP block");
}
- const uint8 *axfd = findResourceData(MKID_BE('AXFD'), auxd);
+ const uint8 *axfd = findResourceData(MKTAG('A','X','F','D'), auxd);
assert(axfd);
uint16 comp = READ_LE_UINT16(axfd);
@@ -2566,7 +2567,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {
error("unimplemented compression type %d", comp);
}
}
- const uint8 *axur = findResourceData(MKID_BE('AXUR'), auxd);
+ const uint8 *axur = findResourceData(MKTAG('A','X','U','R'), auxd);
if (axur) {
uint16 n = READ_LE_UINT16(axur); axur += 2;
while (n--) {
@@ -2578,7 +2579,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {
axur += 8;
}
}
- const uint8 *axer = findResourceData(MKID_BE('AXER'), auxd);
+ const uint8 *axer = findResourceData(MKTAG('A','X','E','R'), auxd);
if (axer) {
a->_auxBlock.visible = true;
a->_auxBlock.r.left = (int16)READ_LE_UINT16(axer + 0) + dx;
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index 98854ec5ba..8e699b5a49 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -34,7 +34,6 @@
namespace Scumm {
-
enum {
V12_X_MULTIPLIER = 8,
V12_Y_MULTIPLIER = 2,
@@ -315,46 +314,6 @@ protected:
bool findPathTowards(byte box, byte box2, byte box3, Common::Point &foundPath);
};
-class ActorHE : public Actor {
-public:
- ActorHE(ScummEngine *scumm, int id) : Actor(scumm, id) {}
-
- virtual void initActor(int mode);
-
- virtual void hideActor();
-
- void drawActorToBackBuf(int x, int y);
-
- void setHEFlag(int bit, int set);
-
- void setUserCondition(int slot, int set);
- bool isUserConditionSet(int slot) const;
-
- void setTalkCondition(int slot);
- bool isTalkConditionSet(int slot) const;
-
-public:
- /** This rect is used to clip actor drawing. */
- Common::Rect _clipOverride;
-
- bool _heNoTalkAnimation;
- bool _heTalking;
- byte _heFlags;
-
- AuxBlock _auxBlock;
-
- struct {
- int16 posX;
- int16 posY;
- int16 color;
- byte sentence[128];
- } _heTalkQueue[16];
-
-
- virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
- virtual void setActorCostume(int c);
-};
-
class Actor_v3 : public Actor {
public:
Actor_v3(ScummEngine *scumm, int id) : Actor(scumm, id) {}
diff --git a/engines/scumm/actor_he.h b/engines/scumm/actor_he.h
new file mode 100644
index 0000000000..bb7bbb6487
--- /dev/null
+++ b/engines/scumm/actor_he.h
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+
+#ifndef SCUMM_ACTOR_HE_H
+#define SCUMM_ACTOR_HE_H
+
+#include "scumm/actor.h"
+
+namespace Scumm {
+
+struct AuxBlock {
+ bool visible;
+ Common::Rect r;
+
+ void reset() {
+ visible = false;
+ r.left = r.top = 0;
+ r.right = r.bottom = -1;
+ }
+};
+
+struct AuxEntry {
+ int actorNum;
+ int subIndex;
+};
+
+class ActorHE : public Actor {
+public:
+ ActorHE(ScummEngine *scumm, int id) : Actor(scumm, id) {}
+
+ virtual void initActor(int mode);
+
+ virtual void hideActor();
+
+ void drawActorToBackBuf(int x, int y);
+
+ void setHEFlag(int bit, int set);
+
+ void setUserCondition(int slot, int set);
+ bool isUserConditionSet(int slot) const;
+
+ void setTalkCondition(int slot);
+ bool isTalkConditionSet(int slot) const;
+
+public:
+ /** This rect is used to clip actor drawing. */
+ Common::Rect _clipOverride;
+
+ bool _heNoTalkAnimation;
+ bool _heTalking;
+ byte _heFlags;
+
+ AuxBlock _auxBlock;
+
+ struct {
+ int16 posX;
+ int16 posY;
+ int16 color;
+ byte sentence[128];
+ } _heTalkQueue[16];
+
+
+ virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
+ virtual void setActorCostume(int c);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 354a1d4491..8acbb8058e 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -146,7 +146,7 @@ void AkosCostumeLoader::loadCostume(int id) {
bool AkosCostumeLoader::hasManyDirections() {
const AkosHeader *akhd;
- akhd = (const AkosHeader *)_vm->findResourceData(MKID_BE('AKHD'), _akos);
+ akhd = (const AkosHeader *)_vm->findResourceData(MKTAG('A','K','H','D'), _akos);
return (akhd->flags & 2) != 0;
}
@@ -170,12 +170,12 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
else
anim = newDirToOldDir(a->getFacing()) + frame * 4;
- akhd = (const AkosHeader *)_vm->findResourceData(MKID_BE('AKHD'), _akos);
+ akhd = (const AkosHeader *)_vm->findResourceData(MKTAG('A','K','H','D'), _akos);
if (anim >= READ_LE_UINT16(&akhd->num_anims))
return;
- r = _vm->findResourceData(MKID_BE('AKCH'), _akos);
+ r = _vm->findResourceData(MKTAG('A','K','C','H'), _akos);
assert(r);
offs = READ_LE_UINT16(r + anim * sizeof(uint16));
@@ -183,8 +183,8 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
return;
r += offs;
- const uint8 *akstPtr = _vm->findResourceData(MKID_BE('AKST'), _akos);
- const uint8 *aksfPtr = _vm->findResourceData(MKID_BE('AKSF'), _akos);
+ const uint8 *akstPtr = _vm->findResourceData(MKTAG('A','K','S','T'), _akos);
+ const uint8 *aksfPtr = _vm->findResourceData(MKTAG('A','K','S','F'), _akos);
i = 0;
mask = READ_LE_UINT16(r); r += 2;
@@ -341,21 +341,21 @@ void AkosRenderer::setCostume(int costume, int shadow) {
const byte *akos = _vm->getResourceAddress(rtCostume, costume);
assert(akos);
- akhd = (const AkosHeader *) _vm->findResourceData(MKID_BE('AKHD'), akos);
- akof = (const AkosOffset *) _vm->findResourceData(MKID_BE('AKOF'), akos);
- akci = _vm->findResourceData(MKID_BE('AKCI'), akos);
- aksq = _vm->findResourceData(MKID_BE('AKSQ'), akos);
- akcd = _vm->findResourceData(MKID_BE('AKCD'), akos);
- akpl = _vm->findResourceData(MKID_BE('AKPL'), akos);
+ akhd = (const AkosHeader *) _vm->findResourceData(MKTAG('A','K','H','D'), akos);
+ akof = (const AkosOffset *) _vm->findResourceData(MKTAG('A','K','O','F'), akos);
+ akci = _vm->findResourceData(MKTAG('A','K','C','I'), akos);
+ aksq = _vm->findResourceData(MKTAG('A','K','S','Q'), akos);
+ akcd = _vm->findResourceData(MKTAG('A','K','C','D'), akos);
+ akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos);
_codec = READ_LE_UINT16(&akhd->codec);
- akct = _vm->findResourceData(MKID_BE('AKCT'), akos);
- rgbs = _vm->findResourceData(MKID_BE('RGBS'), akos);
+ akct = _vm->findResourceData(MKTAG('A','K','C','T'), akos);
+ rgbs = _vm->findResourceData(MKTAG('R','G','B','S'), akos);
xmap = 0;
if (shadow) {
const uint8 *xmapPtr = _vm->getResourceAddress(rtImage, shadow);
assert(xmapPtr);
- xmap = _vm->findResourceData(MKID_BE('XMAP'), xmapPtr);
+ xmap = _vm->findResourceData(MKTAG('X','M','A','P'), xmapPtr);
assert(xmap);
}
}
@@ -1384,8 +1384,8 @@ bool ScummEngine_v6::akos_increaseAnims(const byte *akos, Actor *a) {
uint size;
bool result;
- aksq = findResourceData(MKID_BE('AKSQ'), akos);
- akfo = findResourceData(MKID_BE('AKFO'), akos);
+ aksq = findResourceData(MKTAG('A','K','S','Q'), akos);
+ akfo = findResourceData(MKTAG('A','K','F','O'), akos);
size = getResourceDataSize(akfo) / 2;
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index d5bcd8f3d8..861e448221 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -54,13 +54,14 @@ void ScummEngine::loadCJKFont() {
if (_game.version <= 5 && _game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) { // FM-TOWNS v3 / v5 Kanji
#ifdef DISABLE_TOWNS_DUAL_LAYER_MODE
error("FM-Towns Kanji font drawing requires dual graphics layer support which is disabled in this build");
-#endif
+#else
// use FM-TOWNS font rom, since game files don't have kanji font resources
_cjkFont = Graphics::FontSJIS::createFont(Common::kPlatformFMTowns);
if (!_cjkFont)
error("SCUMM::Font: Could not open file 'FMT_FNT.ROM'");
_textSurfaceMultiplier = 2;
_useCJKMode = true;
+#endif
} else if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN) {
int numChar = 3418;
_2byteWidth = 12;
@@ -689,10 +690,12 @@ void CharsetRendererCommon::enableShadow(bool enable) {
_shadowMode = kNormalShadowMode;
}
} else {
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_vm->_cjkFont) {
_vm->_cjkFont->setDrawingMode(Graphics::FontSJIS::kDefaultMode);
_vm->_cjkFont->toggleFlippedMode(false);
}
+#endif
_shadowMode = kNoShadowMode;
}
}
@@ -719,6 +722,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (chr == '@')
return;
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_vm->_useCJKMode && chr > 127) {
if (_vm->_game.platform == Common::kPlatformFMTowns) {
charPtr = 0;
@@ -729,7 +733,9 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
height = _vm->_2byteHeight;
charPtr = _vm->get2byteCharPtr(chr);
}
- } else {
+ } else
+#endif
+ {
charPtr = _fontPtr + chr * 8;
width = getCharWidth(chr);
height = 8;
@@ -772,14 +778,18 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
dst = vs->getPixels(_left, drawTop);
if (charPtr)
drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel);
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
else if (_vm->_cjkFont)
_vm->_cjkFont->drawChar(vs, chr, _left, drawTop, _color, _shadowColor);
+#endif
} else {
dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);
if (charPtr)
drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.bytesPerPixel, (_vm->_textSurfaceMultiplier == 2 && !is2byte));
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
else if (_vm->_cjkFont)
_vm->_cjkFont->drawChar(_vm->_textSurface, chr, _left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier, _color, _shadowColor);
+#endif
if (is2byte)
origWidth /= _vm->_textSurfaceMultiplier;
}
@@ -805,10 +815,14 @@ void CharsetRendererV3::drawChar(int chr, Graphics::Surface &s, int x, int y) {
int width, height;
int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0;
if (is2byte) {
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_vm->_game.platform == Common::kPlatformFMTowns) {
_vm->_cjkFont->drawChar(s, chr, x * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, _color, _shadowColor);
return;
- } else {
+ }
+ else
+#endif
+ {
charPtr = _vm->get2byteCharPtr(chr);
width = _vm->_2byteWidth;
height = _vm->_2byteHeight;
@@ -922,9 +936,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
origHeight = height = getFontHeight();
offsX = offsY = 0;
- } else
-#endif
- if (_vm->_useCJKMode && (chr >= 128) && !noSjis) {
+ } else if (_vm->_useCJKMode && (chr >= 128) && !noSjis) {
enableShadow(true);
origWidth = width = _vm->_2byteWidth;
origHeight = height = _vm->_2byteHeight;
@@ -934,7 +946,9 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
width++;
height++;
}
- } else {
+ } else
+#endif
+ {
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
assert(charOffs < 0x14000);
if (!charOffs)
@@ -1076,9 +1090,12 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
drawTop = _top - _vm->_screenTop;
}
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (!charPtr && _vm->_cjkFont) {
_vm->_cjkFont->drawChar(dstSurface, _vm->_cjkChar, _left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier, _vm->_townsCharsetColorMap[1], _shadowColor);
- } else if (is2byte) {
+ } else
+#endif
+ if (is2byte) {
drawBits1(dstSurface, dstPtr, charPtr, drawTop, origWidth, origHeight, dstSurface.bytesPerPixel);
} else {
drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight, _vm->_textSurfaceMultiplier == 2);
@@ -1129,10 +1146,13 @@ void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int
if (is2byte) {
enableShadow(true);
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_vm->_game.platform == Common::kPlatformFMTowns) {
_vm->_cjkFont->drawChar(s, chr, x * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, _color, _shadowColor);
return;
- } else {
+ } else
+#endif
+ {
charPtr = _vm->get2byteCharPtr(chr);
width = _vm->_2byteWidth;
height = _vm->_2byteHeight;
@@ -1170,7 +1190,6 @@ void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, co
int color;
byte numbits, bits;
- byte *dst2 = dst;
int pitch = s.pitch - width;
assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
@@ -1179,6 +1198,8 @@ void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, co
byte *cmap = _vm->_charsetColorMap;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
+ byte *dst2 = dst;
+
if (_vm->_game.platform == Common::kPlatformFMTowns)
cmap = _vm->_townsCharsetColorMap;
if (scale2x) {
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index 8e211a5041..bb3c4bcc02 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -176,9 +176,9 @@ void ScummEngine_v70he::setCursorFromImg(uint img, uint room, uint imgindex) {
void ScummEngine_v70he::setDefaultCursor() {
const uint16 *src;
int i, j;
- static const byte palette[] = {0, 0, 0, 0,
- 0xff, 0xff, 0xff, 0,
- 0, 0, 0, 0};
+ static const byte palette[] = {0, 0, 0,
+ 0xff, 0xff, 0xff,
+ 0, 0, 0, };
if (_bytesPerPixel == 2) {
for (i = 0; i < 1024; i++)
@@ -240,7 +240,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {
room = getObjectRoom(img);
findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room);
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), foir.obim);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), foir.obim);
if (_game.version == 8) {
setCursorHotspot(READ_LE_UINT32(&imhd->v8.hotspot[0].x),
@@ -270,7 +270,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {
if (size > sizeof(_grabbedCursor))
error("setCursorFromImg: Cursor image too large");
- bomp = findResource(MKID_BE('BOMP'), dataptr);
+ bomp = findResource(MKTAG('B','O','M','P'), dataptr);
}
if (bomp != NULL)
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index cf0ee0fa0a..63188c1d7a 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -479,7 +479,7 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) {
//is BgNeedsRedraw enough?
_vm->_bgNeedsRedraw = true;
} else {
- DebugPrintf("object command 'state' requires a parameter\n");
+ DebugPrintf("State of object %d: %d\n", obj, _vm->getState(obj));
}
} else if (!strcmp(argv[2], "name")) {
DebugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj));
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 2a6de98dee..87ec7b85a4 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -77,8 +77,6 @@ Common::String ScummEngine::generateFilename(const int room) const {
snprintf(buf, sizeof(buf), "disk%02d.lec", diskNumber);
}
} else {
- char id = 0;
-
switch (_filenamePattern.genMethod) {
case kGenDiskNum:
snprintf(buf, sizeof(buf), _filenamePattern.pattern, diskNumber);
@@ -88,59 +86,6 @@ Common::String ScummEngine::generateFilename(const int room) const {
snprintf(buf, sizeof(buf), _filenamePattern.pattern, room);
break;
- case kGenHEMac:
- case kGenHEMacNoParens:
- case kGenHEPC:
- if (room < 0) {
- id = '0' - room;
- } else if (_game.heversion >= 98) {
- int disk = 0;
- if (_heV7DiskOffsets)
- disk = _heV7DiskOffsets[room];
-
- switch (disk) {
- case 2:
- id = 'b';
- // Special cases for Blue's games, which share common (b) files
- if (_game.id == GID_BIRTHDAY && !(_game.features & GF_DEMO))
- strcpy(buf, "Blue'sBirthday.(b)");
- else if (_game.id == GID_TREASUREHUNT)
- strcpy(buf, "Blue'sTreasureHunt.(b)");
- else
- snprintf(buf, sizeof(buf), "%s.(b)", _filenamePattern.pattern);
- break;
- case 1:
- id = 'a';
- snprintf(buf, sizeof(buf), "%s.(a)", _filenamePattern.pattern);
- break;
- default:
- id = '0';
- snprintf(buf, sizeof(buf), "%s.he0", _filenamePattern.pattern);
- }
- } else if (_game.heversion >= 70) {
- id = (room == 0) ? '0' : '1';
- } else {
- id = diskNumber + '0';
- }
-
- if (_filenamePattern.genMethod == kGenHEPC) {
- // For HE >= 98, we already called snprintf above.
- if (_game.heversion < 98 || room < 0)
- snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
- } else {
- if (id == '3') { // special case for cursors
- // For mac they're stored in game binary
- strncpy(buf, _filenamePattern.pattern, sizeof(buf));
- } else {
- if (_filenamePattern.genMethod == kGenHEMac)
- snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
- else
- snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
- }
- }
-
- break;
-
case kGenUnchanged:
strncpy(buf, _filenamePattern.pattern, sizeof(buf));
break;
@@ -153,6 +98,109 @@ Common::String ScummEngine::generateFilename(const int room) const {
return buf;
}
+Common::String ScummEngine_v60he::generateFilename(const int room) const {
+ char buf[128];
+ char id = 0;
+
+ switch (_filenamePattern.genMethod) {
+ case kGenHEMac:
+ case kGenHEMacNoParens:
+ case kGenHEPC:
+ if (room < 0) {
+ id = '0' - room;
+ } else {
+ const int diskNumber = (room > 0) ? _res->roomno[rtRoom][room] : 0;
+ id = diskNumber + '0';
+ }
+
+ if (_filenamePattern.genMethod == kGenHEPC) {
+ snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
+ } else {
+ if (id == '3') { // special case for cursors
+ // For mac they're stored in game binary
+ strncpy(buf, _filenamePattern.pattern, sizeof(buf));
+ } else {
+ if (_filenamePattern.genMethod == kGenHEMac)
+ snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
+ else
+ snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
+ }
+ }
+
+ break;
+
+ default:
+ // Fallback to parent method
+ return ScummEngine::generateFilename(room);
+ }
+
+ return buf;
+}
+
+Common::String ScummEngine_v70he::generateFilename(const int room) const {
+ char buf[128];
+ char id = 0;
+
+ switch (_filenamePattern.genMethod) {
+ case kGenHEMac:
+ case kGenHEMacNoParens:
+ case kGenHEPC:
+ if (_game.heversion >= 98 && room >= 0) {
+ int disk = 0;
+ if (_heV7DiskOffsets)
+ disk = _heV7DiskOffsets[room];
+
+ switch (disk) {
+ case 2:
+ id = 'b';
+ // Special cases for Blue's games, which share common (b) files
+ if (_game.id == GID_BIRTHDAY && !(_game.features & GF_DEMO))
+ strcpy(buf, "Blue'sBirthday.(b)");
+ else if (_game.id == GID_TREASUREHUNT)
+ strcpy(buf, "Blue'sTreasureHunt.(b)");
+ else
+ snprintf(buf, sizeof(buf), "%s.(b)", _filenamePattern.pattern);
+ break;
+ case 1:
+ id = 'a';
+ snprintf(buf, sizeof(buf), "%s.(a)", _filenamePattern.pattern);
+ break;
+ default:
+ id = '0';
+ snprintf(buf, sizeof(buf), "%s.he0", _filenamePattern.pattern);
+ }
+ } else if (room < 0) {
+ id = '0' - room;
+ } else {
+ id = (room == 0) ? '0' : '1';
+ }
+
+ if (_filenamePattern.genMethod == kGenHEPC) {
+ // For HE >= 98, we already called snprintf above.
+ if (_game.heversion < 98 || room < 0)
+ snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
+ } else {
+ if (id == '3') { // special case for cursors
+ // For mac they're stored in game binary
+ strncpy(buf, _filenamePattern.pattern, sizeof(buf));
+ } else {
+ if (_filenamePattern.genMethod == kGenHEMac)
+ snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
+ else
+ snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
+ }
+ }
+
+ break;
+
+ default:
+ // Fallback to parent method
+ return ScummEngine_v60he::generateFilename(room);
+ }
+
+ return buf;
+}
+
static Common::String generateFilenameForDetection(const char *pattern, FilenameGenMethod genMethod) {
char buf[128];
@@ -1186,7 +1234,7 @@ SaveStateDescriptor ScummMetaEngine::querySaveMetaInfos(const char *target, int
desc.setDeletableFlag(true);
desc.setThumbnail(thumbnail);
- InfoStuff infos;
+ SaveStateMetaInfos infos;
memset(&infos, 0, sizeof(infos));
if (ScummEngine::loadInfosFromSlot(target, slot, &infos)) {
int day = (infos.date >> 24) & 0xFF;
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 9efddc6ad2..a6a97ec426 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -283,7 +283,7 @@ void Gdi::loadTiles(byte *roomptr) {
#ifdef USE_RGB_COLOR
void GdiPCEngine::loadTiles(byte *roomptr) {
- decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), roomptr));
+ decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), roomptr));
}
#endif
@@ -858,7 +858,7 @@ void ScummEngine::initBGBuffers(int height) {
_gdi->_numZBuffer = 2;
} else if (_game.features & GF_SMALL_HEADER) {
int off;
- ptr = findResourceData(MKID_BE('SMAP'), room);
+ ptr = findResourceData(MKTAG('S','M','A','P'), room);
_gdi->_numZBuffer = 0;
if (_game.features & GF_16COLOR)
@@ -873,13 +873,13 @@ void ScummEngine::initBGBuffers(int height) {
}
} else if (_game.version == 8) {
// in V8 there is no RMIH and num z buffers is in RMHD
- ptr = findResource(MKID_BE('RMHD'), room);
+ ptr = findResource(MKTAG('R','M','H','D'), room);
_gdi->_numZBuffer = READ_LE_UINT32(ptr + 24) + 1;
} else if (_game.heversion >= 70) {
- ptr = findResource(MKID_BE('RMIH'), room);
+ ptr = findResource(MKTAG('R','M','I','H'), room);
_gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1;
} else {
- ptr = findResource(MKID_BE('RMIH'), findResource(MKID_BE('RMIM'), room));
+ ptr = findResource(MKTAG('R','M','I','H'), findResource(MKTAG('R','M','I','M'), room));
_gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1;
}
assert(_gdi->_numZBuffer >= 1 && _gdi->_numZBuffer <= 8);
@@ -1283,10 +1283,8 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
- if (color == 254) {
- color = color;
+ if (color == 254)
towns_setupPalCycleField(x, y, x2, y2);
- }
} else
#endif
{
@@ -1649,9 +1647,9 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage)
if ((_vm->_game.features & GF_SMALL_HEADER) || _vm->_game.version == 8)
zplane_list[0] = ptr;
else if (bmapImage)
- zplane_list[0] = _vm->findResource(MKID_BE('BMAP'), ptr);
+ zplane_list[0] = _vm->findResource(MKTAG('B','M','A','P'), ptr);
else
- zplane_list[0] = _vm->findResource(MKID_BE('SMAP'), ptr);
+ zplane_list[0] = _vm->findResource(MKTAG('S','M','A','P'), ptr);
if (_zbufferDisabled)
numzbuf = 0;
@@ -1694,11 +1692,11 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage)
}
} else {
const uint32 zplane_tags[] = {
- MKID_BE('ZP00'),
- MKID_BE('ZP01'),
- MKID_BE('ZP02'),
- MKID_BE('ZP03'),
- MKID_BE('ZP04')
+ MKTAG('Z','P','0','0'),
+ MKTAG('Z','P','0','1'),
+ MKTAG('Z','P','0','2'),
+ MKTAG('Z','P','0','3'),
+ MKTAG('Z','P','0','4')
};
for (i = 1; i < numzbuf; i++) {
@@ -1735,7 +1733,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
// Skip to the BSTR->WRAP->OFFS chunk
smap_ptr = ptr + 24;
} else {
- smap_ptr = _vm->findResource(MKID_BE('SMAP'), ptr);
+ smap_ptr = _vm->findResource(MKTAG('S','M','A','P'), ptr);
assert(smap_ptr);
}
@@ -1743,7 +1741,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
const byte *tmsk_ptr = NULL;
if (_vm->_game.heversion >= 72) {
- tmsk_ptr = _vm->findResource(MKID_BE('TMSK'), ptr);
+ tmsk_ptr = _vm->findResource(MKTAG('T','M','S','K'), ptr);
}
if (y + height > vs->h) {
@@ -2013,7 +2011,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
byte *mask_ptr;
const byte *zplane_list[9];
- const byte *bmap_ptr = _vm->findResourceData(MKID_BE('BMAP'), ptr);
+ const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr);
assert(bmap_ptr);
byte code = *bmap_ptr++;
@@ -2093,7 +2091,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
}
void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h) {
- const byte *bmap_ptr = _vm->findResourceData(MKID_BE('BMAP'), ptr);
+ const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr);
assert(bmap_ptr);
byte code = *bmap_ptr++;
@@ -2830,10 +2828,10 @@ void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint
void GdiPCEngine::decodePCEngineGfx(const byte *room) {
uint16* stripOffsets;
- decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), room));
- decodePCEngineMaskData(_vm->findResourceData(MKID_BE('ZP00'), room));
+ decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), room));
+ decodePCEngineMaskData(_vm->findResourceData(MKTAG('Z','P','0','0'), room));
- const byte* smap_ptr = _vm->findResourceData(MKID_BE('IM00'), room);
+ const byte* smap_ptr = _vm->findResourceData(MKTAG('I','M','0','0'), room);
smap_ptr++; // roomID
int numStrips = *smap_ptr++;
int numRows = *smap_ptr++;
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index 7840b9df20..e3e25c161c 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -112,7 +112,7 @@ void MoviePlayer::handleNextFrame() {
if (_flags & 2) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum);
assert(dstPtr);
- uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ uint8 *dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0);
assert(dst);
copyFrameToBuffer(dst, kDstResource, 0, 0, _vm->_screenWidth * _vm->_bytesPerPixel);
} else if (_flags & 1) {
diff --git a/engines/scumm/he/cup_player_he.cpp b/engines/scumm/he/cup_player_he.cpp
index 516ff6b977..a16af73135 100644
--- a/engines/scumm/he/cup_player_he.cpp
+++ b/engines/scumm/he/cup_player_he.cpp
@@ -47,7 +47,7 @@ bool CUP_Player::open(const char *filename) {
if (_fileStream.open(filename)) {
uint32 tag = _fileStream.readUint32BE();
_fileStream.readUint32BE();
- if (tag == MKID_BE('BEAN')) {
+ if (tag == MKTAG('B','E','A','N')) {
_playbackRate = kDefaultPlaybackRate;
_width = kDefaultVideoWidth;
_height = kDefaultVideoHeight;
@@ -168,7 +168,7 @@ void CUP_Player::updateSfx() {
assert(sfxIndex >= 0 && sfxIndex < _sfxCount);
uint32 offset = READ_LE_UINT32(_sfxBuffer + sfxIndex * 4) - 8;
uint8 *soundData = _sfxBuffer + offset;
- if (READ_BE_UINT32(soundData) == MKID_BE('DATA')) {
+ if (READ_BE_UINT32(soundData) == MKTAG('D','A','T','A')) {
uint32 soundSize = READ_BE_UINT32(soundData + 4);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &sfxChannel->handle,
Audio::makeLoopingAudioStream(
@@ -208,19 +208,19 @@ bool CUP_Player::parseNextHeaderTag(Common::SeekableReadStream &dataStream) {
uint32 next = dataStream.pos() + size;
debug(1, "New header tag %s %d dataSize %d", tag2str(tag), size, _dataSize);
switch (tag) {
- case MKID_BE('HEAD'):
+ case MKTAG('H','E','A','D'):
handleHEAD(dataStream, size);
break;
- case MKID_BE('SFXB'):
+ case MKTAG('S','F','X','B'):
handleSFXB(dataStream, size);
break;
- case MKID_BE('RGBS'):
+ case MKTAG('R','G','B','S'):
handleRGBS(dataStream, size);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
_dataSize = size;
return false;
- case MKID_BE('GFXB'):
+ case MKTAG('G','F','X','B'):
// this is never triggered
default:
warning("Unhandled tag %s", tag2str(tag));
@@ -236,34 +236,34 @@ bool CUP_Player::parseNextBlockTag(Common::SeekableReadStream &dataStream) {
uint32 next = dataStream.pos() + size;
debug(1, "New block tag %s %d dataSize %d", tag2str(tag), size, _dataSize);
switch (tag) {
- case MKID_BE('FRAM'):
+ case MKTAG('F','R','A','M'):
handleFRAM(dataStream, size);
break;
- case MKID_BE('LZSS'):
+ case MKTAG('L','Z','S','S'):
if (handleLZSS(dataStream, size) && _outLzssBufSize != 0) {
Common::MemoryReadStream memoryStream(_outLzssBufData, _outLzssBufSize);
parseNextBlockTag(memoryStream);
}
break;
- case MKID_BE('RATE'):
+ case MKTAG('R','A','T','E'):
handleRATE(dataStream, size);
break;
- case MKID_BE('RGBS'):
+ case MKTAG('R','G','B','S'):
handleRGBS(dataStream, size);
break;
- case MKID_BE('SNDE'):
+ case MKTAG('S','N','D','E'):
handleSNDE(dataStream, size);
break;
- case MKID_BE('TOIL'):
+ case MKTAG('T','O','I','L'):
handleTOIL(dataStream, size);
break;
- case MKID_BE('SRLE'):
+ case MKTAG('S','R','L','E'):
handleSRLE(dataStream, size);
break;
- case MKID_BE('BLOK'):
+ case MKTAG('B','L','O','K'):
_dataSize -= size + 8;
return false;
- case MKID_BE('WRLE'):
+ case MKTAG('W','R','L','E'):
// this is never triggered
default:
warning("Unhandled tag %s", tag2str(tag));
@@ -283,10 +283,10 @@ void CUP_Player::handleSFXB(Common::SeekableReadStream &dataStream, uint32 dataS
if (dataSize > 16) { // WRAP and OFFS chunks
uint32 tag = dataStream.readUint32BE();
uint32 size = dataStream.readUint32BE();
- if (tag == MKID_BE('WRAP')) {
+ if (tag == MKTAG('W','R','A','P')) {
tag = dataStream.readUint32BE();
size = dataStream.readUint32BE();
- if (tag == MKID_BE('OFFS')) {
+ if (tag == MKTAG('O','F','F','S')) {
_sfxCount = (size - 8) / 4;
_sfxBuffer = (uint8 *)malloc(dataSize - 16);
if (_sfxBuffer) {
@@ -298,9 +298,7 @@ void CUP_Player::handleSFXB(Common::SeekableReadStream &dataStream, uint32 dataS
}
void CUP_Player::handleRGBS(Common::SeekableReadStream &dataStream, uint32 dataSize) {
- for (int i = 0; i < 256; i++) {
- dataStream.read(&_paletteData[i * 4], 3);
- }
+ dataStream.read(_paletteData, 256 * 3);
_paletteChanged = true;
}
@@ -441,12 +439,12 @@ static void decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const u
bool CUP_Player::handleLZSS(Common::SeekableReadStream &dataStream, uint32 dataSize) {
uint32 tag = dataStream.readUint32BE();
uint32 size = dataStream.readUint32BE();
- if (tag == MKID_BE('LZHD')) {
+ if (tag == MKTAG('L','Z','H','D')) {
uint32 compressionType = dataStream.readUint32LE();
uint32 compressionSize = dataStream.readUint32LE();
tag = dataStream.readUint32BE();
size = dataStream.readUint32BE();
- if (tag == MKID_BE('DATA') && compressionType == 0x2000) {
+ if (tag == MKTAG('D','A','T','A') && compressionType == 0x2000) {
if (_inLzssBufSize < size - 16) {
free(_inLzssBufData);
_inLzssBufSize = size - 16;
diff --git a/engines/scumm/he/cup_player_he.h b/engines/scumm/he/cup_player_he.h
index 1b1c32d86f..93146fdf85 100644
--- a/engines/scumm/he/cup_player_he.h
+++ b/engines/scumm/he/cup_player_he.h
@@ -90,7 +90,7 @@ protected:
int _playbackRate;
int _width, _height;
- uint8 _paletteData[256 * 4];
+ uint8 _paletteData[256 * 3];
bool _paletteChanged;
uint8 *_offscreenBuffer;
diff --git a/engines/scumm/he/floodfill_he.cpp b/engines/scumm/he/floodfill_he.cpp
index 491b91c17e..026a848828 100644
--- a/engines/scumm/he/floodfill_he.cpp
+++ b/engines/scumm/he/floodfill_he.cpp
@@ -240,7 +240,7 @@ void Wiz::fillWizFlood(const WizParameters *params) {
if (params->processFlags & kWPFNewState) {
state = params->img.state;
}
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -258,7 +258,7 @@ void Wiz::fillWizFlood(const WizParameters *params) {
color = params->fillColor;
}
if (imageRect.contains(px, py)) {
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
FloodFillState *ffs = new FloodFillState;
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 5b59558dd7..830e940322 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -31,6 +31,7 @@
#include "scumm/he/floodfill_he.h"
#include "scumm/he/wiz_he.h"
#endif
+#include "scumm/actor_he.h" // For AuxBlock & AuxEntry
namespace Common {
class SeekableReadStream;
@@ -55,7 +56,10 @@ public:
Common::SeekableReadStream *_hInFileTable[17];
Common::WriteStream *_hOutFileTable[17];
+ Common::Rect _actorClipOverride; // HE specific
+
int _heTimers[16];
+
int getHETimer(int timer);
void setHETimer(int timer);
@@ -63,6 +67,8 @@ public:
ScummEngine_v60he(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v60he();
+ virtual Common::String generateFilename(const int room) const;
+
virtual void resetScumm();
protected:
@@ -107,7 +113,9 @@ class ScummEngine_v70he : public ScummEngine_v60he {
protected:
ResExtractor *_resExtractor;
+ byte *_heV7DiskOffsets;
byte *_heV7RoomOffsets;
+ uint32 *_heV7RoomIntOffsets;
int32 _heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags, _heSndSoundFreq;
@@ -118,9 +126,14 @@ public:
ScummEngine_v70he(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v70he();
+ virtual Common::String generateFilename(const int room) const;
+
void restoreBackgroundHE(Common::Rect rect, int dirtybit = 0);
protected:
+ virtual void allocateArrays();
+ virtual int readResTypeList(int id);
+ virtual uint32 getResourceRoomOffset(int type, int idx);
virtual void setupOpcodes();
virtual void setupScummVars();
diff --git a/engines/scumm/he/logic_he.cpp b/engines/scumm/he/logic_he.cpp
index ed92c33105..c088fd6e22 100644
--- a/engines/scumm/he/logic_he.cpp
+++ b/engines/scumm/he/logic_he.cpp
@@ -160,8 +160,8 @@ int32 LogicHErace::dispatch(int op, int numArgs, int32 *args) {
return res;
}
-#define RAD2DEG (180 / PI)
-#define DEG2RAD (PI / 180)
+#define RAD2DEG (180 / M_PI)
+#define DEG2RAD (M_PI / 180)
int32 LogicHErace::op_1003(int32 *args) {
int value = args[2] ? args[2] : 1;
@@ -457,7 +457,7 @@ void LogicHEfunshop::op_1004(int32 *args) {
sq = sqrt(data[i + 1] * data[i + 1] + data[i] * data[i]);
if (at <= 0)
- at += 2 * PI;
+ at += 2 * M_PI;
data[i] = cos(at + a1) * sq;
data[i + 1] = sin(at + a1) * sq;
diff --git a/engines/scumm/he/palette_he.cpp b/engines/scumm/he/palette_he.cpp
index c7ed9e64a8..7f517c56ed 100644
--- a/engines/scumm/he/palette_he.cpp
+++ b/engines/scumm/he/palette_he.cpp
@@ -192,7 +192,7 @@ void ScummEngine_v90he::setHEPaletteFromCostume(int palSlot, int resId) {
assertRange(1, palSlot, _numPalettes, "palette");
const uint8 *data = getResourceAddress(rtCostume, resId);
assert(data);
- const uint8 *rgbs = findResourceData(MKID_BE('RGBS'), data);
+ const uint8 *rgbs = findResourceData(MKTAG('R','G','B','S'), data);
assert(rgbs);
setHEPaletteFromPtr(palSlot, rgbs);
}
@@ -202,7 +202,7 @@ void ScummEngine_v90he::setHEPaletteFromImage(int palSlot, int resId, int state)
assertRange(1, palSlot, _numPalettes, "palette");
uint8 *data = getResourceAddress(rtImage, resId);
assert(data);
- const uint8 *rgbs = findWrappedBlock(MKID_BE('RGBS'), data, state, 0);
+ const uint8 *rgbs = findWrappedBlock(MKTAG('R','G','B','S'), data, state, 0);
if (rgbs)
setHEPaletteFromPtr(palSlot, rgbs);
}
@@ -212,7 +212,7 @@ void ScummEngine_v90he::setHEPaletteFromRoom(int palSlot, int resId, int state)
assertRange(1, palSlot, _numPalettes, "palette");
const uint8 *data = getResourceAddress(rtRoom, resId);
assert(data);
- const uint8 *pals = findResourceData(MKID_BE('PALS'), data);
+ const uint8 *pals = findResourceData(MKTAG('P','A','L','S'), data);
assert(pals);
const uint8 *rgbs = findPalInPals(pals, state);
assert(rgbs);
@@ -380,21 +380,8 @@ void ScummEngine_v99he::updatePalette() {
return;
int num = _palDirtyMax - _palDirtyMin + 1;
- int i;
-
- byte palette_colors[1024];
- byte *p = palette_colors;
-
- for (i = _palDirtyMin; i <= _palDirtyMax; i++) {
- byte *data = _hePalettes + 1024 + i * 3;
-
- *p++ = data[0];
- *p++ = data[1];
- *p++ = data[2];
- *p++ = 0;
- }
- _system->getPaletteManager()->setPalette(palette_colors, _palDirtyMin, num);
+ _system->getPaletteManager()->setPalette(_hePalettes + 1024 + _palDirtyMin * 3, _palDirtyMin, num);
_palDirtyMax = -1;
_palDirtyMin = 256;
diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp
index 72e7052034..ecb094f29b 100644
--- a/engines/scumm/he/resource_he.cpp
+++ b/engines/scumm/he/resource_he.cpp
@@ -4,10 +4,6 @@
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
- * Parts of this code are heavily based on:
- * icoutils - A set of programs dealing with MS Windows icons and cursors.
- * Copyright (C) 1998-2001 Oskar Liljeblad
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -36,6 +32,7 @@
#include "audio/decoders/wave.h"
#include "graphics/cursorman.h"
+#include "graphics/wincursor.h"
#include "common/archive.h"
#include "common/memstream.h"
@@ -43,14 +40,6 @@
namespace Scumm {
-#if defined(SCUMM_LITTLE_ENDIAN)
-#define LE16(x)
-#define LE32(x)
-#elif defined(SCUMM_BIG_ENDIAN)
-#define LE16(x) ((x) = TO_LE_16(x))
-#define LE32(x) ((x) = TO_LE_32(x))
-#endif
-
ResExtractor::ResExtractor(ScummEngine_v70he *scumm)
: _vm(scumm) {
@@ -65,1092 +54,112 @@ ResExtractor::~ResExtractor() {
free(cc->palette);
}
}
+
memset(_cursorCache, 0, sizeof(_cursorCache));
}
ResExtractor::CachedCursor *ResExtractor::findCachedCursor(int id) {
- for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
- CachedCursor *cc = &_cursorCache[i];
- if (cc->valid && cc->id == id) {
- return cc;
- }
- }
+ for (int i = 0; i < MAX_CACHED_CURSORS; ++i)
+ if (_cursorCache[i].valid && _cursorCache[i].id == id)
+ return &_cursorCache[i];
+
return NULL;
}
ResExtractor::CachedCursor *ResExtractor::getCachedCursorSlot() {
- uint32 min_last_used = 0;
+ uint32 minLastUsed = 0;
CachedCursor *r = NULL;
+
for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
CachedCursor *cc = &_cursorCache[i];
- if (!cc->valid) {
+ if (!cc->valid)
return cc;
- } else {
- if (min_last_used == 0 || cc->last_used < min_last_used) {
- min_last_used = cc->last_used;
- r = cc;
- }
+
+ if (minLastUsed == 0 || cc->lastUsed < minLastUsed) {
+ minLastUsed = cc->lastUsed;
+ r = cc;
}
}
+
assert(r);
- free(r->bitmap);
- free(r->palette);
+ delete[] r->bitmap;
+ delete[] r->palette;
memset(r, 0, sizeof(CachedCursor));
return r;
}
void ResExtractor::setCursor(int id) {
- byte *cursorRes = 0;
- int cursorsize;
- int keycolor = 0;
CachedCursor *cc = findCachedCursor(id);
+
if (cc != NULL) {
debug(7, "Found cursor %d in cache slot %lu", id, (long)(cc - _cursorCache));
} else {
cc = getCachedCursorSlot();
assert(cc && !cc->valid);
- cursorsize = extractResource(id, &cursorRes);
- convertIcons(cursorRes, cursorsize, &cc->bitmap, &cc->w, &cc->h, &cc->hotspot_x, &cc->hotspot_y, &keycolor, &cc->palette, &cc->palSize);
+
+ if (!extractResource(id, cc))
+ error("Could not extract cursor %d", id);
+
debug(7, "Adding cursor %d to cache slot %lu", id, (long)(cc - _cursorCache));
- free(cursorRes);
+
cc->valid = true;
cc->id = id;
- cc->last_used = g_system->getMillis();
+ cc->lastUsed = g_system->getMillis();
}
if (cc->palette)
CursorMan.replaceCursorPalette(cc->palette, 0, cc->palSize);
- _vm->setCursorHotspot(cc->hotspot_x, cc->hotspot_y);
- _vm->setCursorFromBuffer(cc->bitmap, cc->w, cc->h, cc->w);
+ _vm->setCursorHotspot(cc->hotspotX, cc->hotspotY);
+ _vm->setCursorFromBuffer(cc->bitmap, cc->width, cc->height, cc->width);
}
-/*
- * Static variables
- */
-const char *res_types[] = {
- /* 0x01: */
- "cursor", "bitmap", "icon", "menu", "dialog", "string",
- "fontdir", "font", "accelerator", "rcdata", "messagelist",
- "group_cursor", NULL, "group_icon", NULL,
- /* the following are not defined in winbase.h, but found in wrc. */
- /* 0x10: */
- "version", "dlginclude", NULL, "plugplay", "vxd",
- "anicursor", "aniicon"
-};
-#define RES_TYPE_COUNT (sizeof(res_types)/sizeof(char *))
-
Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
}
-int Win32ResExtractor::extractResource(int resId, byte **data) {
- char buf[20];
-
- snprintf(buf, sizeof(buf), "%d", resId);
-
- return extractResource_("group_cursor", buf, data);
-}
-
-int Win32ResExtractor::extractResource_(const char *resType, char *resName, byte **data) {
- char *arg_language = NULL;
- const char *arg_type = resType;
- char *arg_name = resName;
- int ressize = 0;
-
- _arg_raw = false;
-
- /* translate --type option from resource type string to integer */
- arg_type = res_type_string_to_id(arg_type);
-
- WinLibrary fi;
-
- /* initiate stuff */
- fi.memory = NULL;
- fi.file = NULL;
-
+bool Win32ResExtractor::extractResource(int id, CachedCursor *cc) {
if (_fileName.empty()) { // We are running for the first time
_fileName = _vm->generateFilename(-3);
- }
-
- /* get file size */
- fi.file = SearchMan.createReadStreamForMember(_fileName);
- if (!fi.file) {
- error("Cannot open file %s", _fileName.c_str());
- }
-
- fi.total_size = fi.file->size();
- if (fi.total_size == -1) {
- error("Cannot get size of file %s", _fileName.c_str());
- goto cleanup;
- }
- if (fi.total_size == 0) {
- error("%s: file has a size of 0", _fileName.c_str());
- goto cleanup;
- }
-
- /* read all of file */
- fi.memory = (byte *)malloc(fi.total_size);
- if (fi.file->read(fi.memory, fi.total_size) == 0) {
- error("Cannot read from file %s", _fileName.c_str());
- goto cleanup;
- }
-
- /* identify file and find resource table */
- if (!read_library(&fi)) {
- /* error reported by read_library */
- goto cleanup;
- }
-
- /* errors will be printed by the callback */
- ressize = do_resources(&fi, arg_type, arg_name, arg_language, data);
-
- /* free stuff and close file */
- cleanup:
- delete fi.file;
- free(fi.memory);
-
- return ressize;
-}
-
-
-/**
- * Translate a numeric resource type to it's corresponding string type.
- * (For informative-ness.)
- */
-const char *Win32ResExtractor::res_type_id_to_string(int id) {
- if (id == 241)
- return "toolbar";
- if (id > 0 && id <= (int)RES_TYPE_COUNT)
- return res_types[id-1];
- return NULL;
-}
-
-/**
- * Translate a resource type string to integer.
- * (Used to convert the --type option.)
- */
-const char *Win32ResExtractor::res_type_string_to_id(const char *type) {
- static const char *res_type_ids[] = {
- "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-10",
- "-11", "-12", NULL, "-14", NULL, "-16", "-17", NULL, "-19",
- "-20", "-21", "-22"
- };
- int c;
-
- if (type == NULL)
- return NULL;
-
- for (c = 0; c < (int)RES_TYPE_COUNT; c++) {
- if (res_types[c] != NULL && !scumm_stricmp(type, res_types[c]))
- return res_type_ids[c];
- }
-
- return type;
-}
-
-/**
- * Return the resource id quoted if it is a string, otherwise (i.e. if
- * it is numeric) just return it.
- */
-Common::String Win32ResExtractor::WinResource::getQuotedResourceId() const {
- if (numeric_id || id[0] == '\0')
- return id;
- return '"' + Common::String(id) + '"';
-}
-
-int Win32ResExtractor::extract_resources(WinLibrary *fi, WinResource *wr,
- WinResource *type_wr, WinResource *name_wr,
- WinResource *lang_wr, byte **data) {
- int size;
- bool free_it;
- const char *type;
- int32 id;
-
- if (*data) {
- error("Win32ResExtractor::extract_resources() more than one cursor");
- return 0;
- }
-
- *data = extract_resource(fi, wr, &size, &free_it, type_wr->id, (lang_wr == NULL ? NULL : lang_wr->id), _arg_raw);
-
- if (data == NULL) {
- error("Win32ResExtractor::extract_resources() problem with resource extraction");
- return 0;
- }
-
- /* get named resource type if possible */
- type = NULL;
- if ((id = strtol(type_wr->id, 0, 10)) != 0)
- type = res_type_id_to_string(id);
-
- if (lang_wr != NULL && lang_wr->id[0] != '\0') {
- debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s language: %s [size=%d]",
- name_wr->getQuotedResourceId().c_str(), lang_wr->getQuotedResourceId().c_str(), size);
- } else {
- debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s [size=%d]",
- name_wr->getQuotedResourceId().c_str(), size);
- }
- return size;
-}
-
-/**
- * Extract a resource, returning pointer to data.
- */
-byte *Win32ResExtractor::extract_resource(WinLibrary *fi, WinResource *wr, int *size,
- bool *free_it, char *type, char *lang, bool raw) {
- char *str;
- int32 intval;
-
- /* just return pointer to data if raw */
- if (raw) {
- *free_it = false;
- /* get_resource_entry will print possible error */
- return get_resource_entry(fi, wr, size);
- }
-
- /* find out how to extract */
- str = type;
- if (str != NULL && (intval = strtol(STRIP_RES_ID_FORMAT(str), 0, 10))) {
- if (intval == (int)RT_GROUP_ICON) {
- *free_it = true;
- return extract_group_icon_cursor_resource(fi, wr, lang, size, true);
- }
- if (intval == (int)RT_GROUP_CURSOR) {
- *free_it = true;
- return extract_group_icon_cursor_resource(fi, wr, lang, size, false);
- }
- }
-
- return NULL;
-}
-
-/**
- * Create a complete RT_GROUP_ICON resource, that can be written to
- * an `.ico' file without modifications. Returns an allocated
- * memory block that should be freed with free() once used.
- *
- * `root' is the offset in file that specifies the resource.
- * `base' is the offset that string pointers are calculated from.
- * `ressize' should point to an integer variable where the size of
- * the returned memory block will be placed.
- * `is_icon' indicates whether resource to be extracted is icon
- * or cursor group.
- */
-byte *Win32ResExtractor::extract_group_icon_cursor_resource(WinLibrary *fi, WinResource *wr, char *lang,
- int *ressize, bool is_icon) {
- Win32CursorIconDir *icondir;
- Win32CursorIconFileDir *fileicondir;
- byte *memory;
- int c, offset, skipped;
- int size;
-
- /* get resource data and size */
- icondir = (Win32CursorIconDir *)get_resource_entry(fi, wr, &size);
- if (icondir == NULL) {
- /* get_resource_entry will print error */
- return NULL;
- }
-
- /* calculate total size of output file */
- RETURN_IF_BAD_POINTER(NULL, icondir->count);
- skipped = 0;
- for (c = 0; c < FROM_LE_16(icondir->count); c++) {
- int level;
- int iconsize;
- char name[14];
- WinResource *fwr;
-
- RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]);
- /*debug("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d", c,
- FROM_LE_32(icondir->entries[c].bytes_in_res),
- (is_icon ? icondir->entries[c].res_info.icon.width : FROM_LE_16(icondir->entries[c].res_info.cursor.width)),
- (is_icon ? icondir->entries[c].res_info.icon.height : FROM_LE_16(icondir->entries[c].res_info.cursor.height)),
- FROM_LE_16(icondir->entries[c].plane_count),
- FROM_LE_16(icondir->entries[c].bit_count));*/
-
- /* find the corresponding icon resource */
- snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id));
- fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
- if (fwr == NULL) {
- error("%s: could not find `%s' in `%s' resource.",
- _fileName.c_str(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
- return NULL;
- }
-
- if (get_resource_entry(fi, fwr, &iconsize) != NULL) {
- if (iconsize == 0) {
- debugC(DEBUG_RESOURCE, "%s: icon resource `%s' is empty, skipping", _fileName.c_str(), name);
- skipped++;
- continue;
- }
- if ((uint32)iconsize != FROM_LE_32(icondir->entries[c].bytes_in_res)) {
- debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)",
- _fileName.c_str(), name, iconsize, FROM_LE_32(icondir->entries[c].bytes_in_res));
- }
- size += iconsize; /* size += FROM_LE_32(icondir->entries[c].bytes_in_res); */
- /* cursor resources have two additional WORDs that contain
- * hotspot info */
- if (!is_icon)
- size -= sizeof(uint16)*2;
- }
- }
- offset = sizeof(Win32CursorIconFileDir) + (FROM_LE_16(icondir->count)-skipped) * sizeof(Win32CursorIconFileDirEntry);
- size += offset;
- *ressize = size;
-
- /* allocate that much memory */
- memory = (byte *)malloc(size);
- fileicondir = (Win32CursorIconFileDir *)memory;
-
- /* transfer Win32CursorIconDir structure members */
- fileicondir->reserved = icondir->reserved;
- fileicondir->type = icondir->type;
- fileicondir->count = TO_LE_16(FROM_LE_16(icondir->count) - skipped);
-
- /* transfer each cursor/icon: Win32CursorIconDirEntry and data */
- skipped = 0;
- for (c = 0; c < FROM_LE_16(icondir->count); c++) {
- int level;
- char name[14];
- WinResource *fwr;
- byte *data;
-
- /* find the corresponding icon resource */
- snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id));
- fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
- if (fwr == NULL) {
- error("%s: could not find `%s' in `%s' resource.",
- _fileName.c_str(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
- return NULL;
- }
-
- /* get data and size of that resource */
- data = (byte *)get_resource_entry(fi, fwr, &size);
- if (data == NULL) {
- /* get_resource_entry has printed error */
- return NULL;
- }
- if (size == 0) {
- skipped++;
- continue;
- }
-
- /* copy ICONDIRENTRY (not including last dwImageOffset) */
- memcpy(&fileicondir->entries[c-skipped], &icondir->entries[c],
- sizeof(Win32CursorIconFileDirEntry)-sizeof(uint32));
-
- /* special treatment for cursors */
- if (!is_icon) {
- fileicondir->entries[c-skipped].width = icondir->entries[c].res_info.cursor.width;
- fileicondir->entries[c-skipped].height = TO_LE_16(FROM_LE_16(icondir->entries[c].res_info.cursor.height) / 2);
- fileicondir->entries[c-skipped].color_count = 0;
- fileicondir->entries[c-skipped].reserved = 0;
- }
-
- /* set image offset and increase it */
- fileicondir->entries[c-skipped].dib_offset = TO_LE_32(offset);
-
- /* transfer resource into file memory */
- if (is_icon) {
- memcpy(&memory[offset], data, FROM_LE_32(icondir->entries[c].bytes_in_res));
- } else {
- fileicondir->entries[c-skipped].hotspot_x = ((uint16 *) data)[0];
- fileicondir->entries[c-skipped].hotspot_y = ((uint16 *) data)[1];
- memcpy(&memory[offset], data+sizeof(uint16)*2,
- FROM_LE_32(icondir->entries[c].bytes_in_res)-sizeof(uint16)*2);
- offset -= sizeof(uint16)*2;
- }
-
- /* increase the offset pointer */
- offset += FROM_LE_32(icondir->entries[c].bytes_in_res);
+ if (!_exe.loadFromEXE(_fileName))
+ error("Cannot open file %s", _fileName.c_str());
}
- return memory;
-}
-
-/**
- * Check if a chunk of data (determined by offset and size)
- * is within the bounds of the WinLibrary file.
- * Usually not called directly.
- */
-bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *name, void *offset, int size) {
- int need_size = (int)((byte *)offset - memory + size);
-
- debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x",
- need_size, total_size, (uint)((byte *)offset - memory), size);
+ Graphics::WinCursorGroup *group = Graphics::WinCursorGroup::createCursorGroup(_exe, id);
- if (need_size < 0 || need_size > total_size) {
- error("%s: premature end", name);
+ if (!group)
return false;
- }
-
- return true;
-}
-
-
-/**
- * Do something for each resource matching type, name and lang.
- */
-int Win32ResExtractor::do_resources(WinLibrary *fi, const char *type, char *name, char *lang, byte **data) {
- WinResource *type_wr;
- WinResource *name_wr;
- WinResource *lang_wr;
- int size;
-
- type_wr = (WinResource *)calloc(3, sizeof(WinResource));
- name_wr = type_wr + 1;
- lang_wr = type_wr + 2;
-
- size = do_resources_recurs(fi, NULL, type_wr, name_wr, lang_wr, type, name, lang, data);
-
- free(type_wr);
-
- return size;
-}
-
-/* what is each entry in this directory level for? type, name or language? */
-#define WINRESOURCE_BY_LEVEL(x) ((x)==0 ? type_wr : ((x)==1 ? name_wr : lang_wr))
-
-/* does the id of this entry match the specified id? */
-#define LEVEL_MATCHES(x) (x == NULL || x ## _wr->id[0] == '\0' || compare_resource_id(x ## _wr, x))
-int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base,
- WinResource *type_wr, WinResource *name_wr, WinResource *lang_wr,
- const char *type, char *name, char *lang, byte **data) {
- int c, rescnt;
- WinResource *wr;
- uint32 size = 0;
+ Graphics::WinCursor *cursor = group->cursors[0].cursor;
- /* get a list of all resources at this level */
- wr = list_resources(fi, base, &rescnt);
- if (wr == NULL) {
- return size;
- }
-
- /* process each resource listed */
- for (c = 0; c < rescnt; c++) {
- /* (over)write the corresponding WinResource holder with the current */
- memcpy(WINRESOURCE_BY_LEVEL(wr[c].level), wr+c, sizeof(WinResource));
-
- /* go deeper unless there is something that does NOT match */
- if (LEVEL_MATCHES(type) && LEVEL_MATCHES(name) && LEVEL_MATCHES(lang)) {
- if (wr->is_directory)
- size = do_resources_recurs(fi, wr+c, type_wr, name_wr, lang_wr, type, name, lang, data);
- else
- size = extract_resources(fi, wr+c, type_wr, name_wr, lang_wr, data);
- }
- }
-
- /* since we're moving back one level after this, unset the
- * WinResource holder used on this level */
- memset(WINRESOURCE_BY_LEVEL(wr[0].level), 0, sizeof(WinResource));
-
- return size;
-}
-
-bool Win32ResExtractor::compare_resource_id(WinResource *wr, const char *id) {
- if (wr->numeric_id) {
- int32 cmp1, cmp2;
- if (id[0] == '+')
- return false;
- if (id[0] == '-')
- id++;
- cmp1 = strtol(wr->id, 0, 10);
- cmp2 = strtol(id, 0, 10);
- if (!cmp1 || !cmp2 || cmp1 != cmp2)
- return false;
- } else {
- if (id[0] == '-')
- return false;
- if (id[0] == '+')
- id++;
- if (strcmp(wr->id, id))
- return false;
- }
+ cc->bitmap = new byte[cursor->getWidth() * cursor->getHeight()];
+ cc->width = cursor->getWidth();
+ cc->height = cursor->getHeight();
+ cc->hotspotX = cursor->getHotspotX();
+ cc->hotspotY = cursor->getHotspotY();
- return true;
-}
+ // Convert from the paletted format to the SCUMM palette
+ const byte *srcBitmap = cursor->getSurface();
-bool Win32ResExtractor::decode_pe_resource_id(WinLibrary *fi, WinResource *wr, uint32 value) {
- if (value & IMAGE_RESOURCE_NAME_IS_STRING) { /* numeric id */
- int c, len;
- uint16 *mem = (uint16 *)
- (fi->first_resource + (value & ~IMAGE_RESOURCE_NAME_IS_STRING));
-
- /* copy each char of the string, and terminate it */
- RETURN_IF_BAD_POINTER(false, *mem);
- len = FROM_LE_16(mem[0]);
- RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len);
-
- len = MIN(FROM_LE_16(mem[0]), (uint16)WINRES_ID_MAXLEN);
- for (c = 0; c < len; c++)
- wr->id[c] = FROM_LE_16(mem[c+1]) & 0x00FF;
- wr->id[len] = '\0';
- wr->numeric_id = false;
- } else { /* Unicode string id */
- /* translate id into a string */
- snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value);
- wr->numeric_id = true;
+ for (int i = 0; i < cursor->getWidth() * cursor->getHeight(); i++) {
+ if (srcBitmap[i] == cursor->getKeyColor()) // Transparent
+ cc->bitmap[i] = 255;
+ else if (srcBitmap[i] == 0) // Black
+ cc->bitmap[i] = 253;
+ else // White
+ cc->bitmap[i] = 254;
}
+ delete group;
return true;
}
-byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) {
- byte *result;
-
- Win32ImageResourceDataEntry *dataent;
-
- dataent = (Win32ImageResourceDataEntry *) wr->children;
- RETURN_IF_BAD_POINTER(NULL, *dataent);
- *size = FROM_LE_32(dataent->size);
-
- result = fi->memory + FROM_LE_32(dataent->offset_to_data);
-
- RETURN_IF_BAD_OFFSET(NULL, result, *size);
-
- return result;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::list_pe_resources(WinLibrary *fi, Win32ImageResourceDirectory *pe_res, int level, int *count) {
- WinResource *wr;
- int c, rescnt;
- Win32ImageResourceDirectoryEntry *dirent
- = (Win32ImageResourceDirectoryEntry *)(pe_res + 1);
-
- /* count number of `type' resources */
- RETURN_IF_BAD_POINTER(NULL, *dirent);
- rescnt = FROM_LE_16(pe_res->number_of_named_entries) + FROM_LE_16(pe_res->number_of_id_entries);
- *count = rescnt;
-
- /* allocate WinResource's */
- wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
-
- /* fill in the WinResource's */
- for (c = 0; c < rescnt; c++) {
- RETURN_IF_BAD_POINTER(NULL, dirent[c]);
- wr[c].this_ = pe_res;
- wr[c].level = level;
- wr[c].is_directory = ((FROM_LE_32(dirent[c].offset_to_data) & IMAGE_RESOURCE_DATA_IS_DIRECTORY) != 0);
- wr[c].children = fi->first_resource + (FROM_LE_32(dirent[c].offset_to_data) & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY);
-
- /* fill in wr->id, wr->numeric_id */
- if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name))) {
- free(wr);
- return NULL;
- }
- }
-
- return wr;
-}
-
-
-/**
- * Return an array of WinResource's in the current
- * resource level specified by _res->
- */
-Win32ResExtractor::WinResource *Win32ResExtractor::list_resources(WinLibrary *fi, WinResource *res, int *count) {
- if (res != NULL && !res->is_directory)
- return NULL;
-
- return list_pe_resources(fi, (Win32ImageResourceDirectory *)
- (res == NULL ? fi->first_resource : res->children),
- (res == NULL ? 0 : res->level+1),
- count);
-}
-
-/**
- * Read header and get resource directory offset in a Windows library
- * (AKA module).
- */
-bool Win32ResExtractor::read_library(WinLibrary *fi) {
- /* check for DOS header signature `MZ' */
- RETURN_IF_BAD_POINTER(false, MZ_HEADER(fi->memory)->magic);
- if (FROM_LE_16(MZ_HEADER(fi->memory)->magic) == IMAGE_DOS_SIGNATURE) {
- DOSImageHeader *mz_header = MZ_HEADER(fi->memory);
-
- RETURN_IF_BAD_POINTER(false, mz_header->lfanew);
-
- // Apply endian fix (currently only lfanew is used from the DOSImageHeader,
- // so we don't bother to 'fix' the rest).
- LE32(mz_header->lfanew);
-
- if (mz_header->lfanew < sizeof(DOSImageHeader)) {
- error("%s: not a Windows library", _fileName.c_str());
- return false;
- }
- }
-
- /* check for NT header signature `PE' */
- RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature);
- if (FROM_LE_32(PE_HEADER(fi->memory)->signature) == IMAGE_NT_SIGNATURE) {
- Win32ImageNTHeaders *pe_header;
- int d;
-
- // Fix image header endianess
- fix_win32_image_header_endian(PE_HEADER(fi->memory));
-
- /* allocate new memory */
- fi->total_size = calc_vma_size(fi);
- if (fi->total_size == 0) {
- /* calc_vma_size has reported error */
- return false;
- }
- byte *ptr = (byte *)realloc(fi->memory, fi->total_size);
- assert(ptr);
- fi->memory = ptr;
-
- /* relocate memory, start from last section */
- pe_header = PE_HEADER(fi->memory);
- RETURN_IF_BAD_POINTER(false, pe_header->file_header.number_of_sections);
-
- /* we don't need to do OFFSET checking for the sections.
- * calc_vma_size has already done that */
- for (d = pe_header->file_header.number_of_sections - 1; d >= 0; d--) {
- Win32ImageSectionHeader *pe_sec = PE_SECTIONS(fi->memory) + d;
-
- if (pe_sec->characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- continue;
-
- //if (pe_sec->virtual_address + pe_sec->size_of_raw_data > fi->total_size)
-
- RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->virtual_address, pe_sec->size_of_raw_data);
- RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->pointer_to_raw_data, pe_sec->size_of_raw_data);
- if (FROM_LE_32(pe_sec->virtual_address) != pe_sec->pointer_to_raw_data) {
- memmove(fi->memory + pe_sec->virtual_address,
- fi->memory + pe_sec->pointer_to_raw_data,
- pe_sec->size_of_raw_data);
- }
- }
-
- /* find resource directory */
- RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
- Win32ImageDataDirectory *dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
- if (dir->size == 0) {
- error("%s: file contains no resources", _fileName.c_str());
- return false;
- }
-
- fix_win32_image_data_directory(dir);
-
- fi->first_resource = fi->memory + dir->virtual_address;
- return true;
- }
-
- /* other (unknown) header signature was found */
- error("%s: not a Windows library", _fileName.c_str());
- return false;
-}
-
-/**
- * Calculate the total amount of memory needed for a 32-bit Windows
- * module. Returns -1 if file was too small.
- */
-int Win32ResExtractor::calc_vma_size(WinLibrary *fi) {
- Win32ImageSectionHeader *seg;
- int c, segcount, size;
-
- size = 0;
- RETURN_IF_BAD_POINTER(-1, PE_HEADER(fi->memory)->file_header.number_of_sections);
- segcount = PE_HEADER(fi->memory)->file_header.number_of_sections;
-
- /* If there are no segments, just process file like it is.
- * This is (probably) not the right thing to do, but problems
- * will be delt with later anyway.
- */
- if (segcount == 0)
- return fi->total_size;
-
- seg = PE_SECTIONS(fi->memory);
- RETURN_IF_BAD_POINTER(-1, *seg);
- for (c = 0; c < segcount; c++) {
- RETURN_IF_BAD_POINTER(0, *seg);
- fix_win32_image_section_header(seg);
-
- size = MAX((uint32)size, seg->virtual_address + seg->size_of_raw_data);
- /* I have no idea what misc.virtual_size is for... */
- size = MAX((uint32)size, seg->virtual_address + seg->misc.virtual_size);
- seg++;
- }
-
- return size;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::find_with_resource_array(WinLibrary *fi, WinResource *wr, const char *id) {
- int c, rescnt;
- WinResource *return_wr;
-
- wr = list_resources(fi, wr, &rescnt);
- if (wr == NULL)
- return NULL;
-
- for (c = 0; c < rescnt; c++) {
- if (compare_resource_id(&wr[c], id)) {
- /* duplicate WinResource and return it */
- return_wr = (WinResource *)malloc(sizeof(WinResource));
- memcpy(return_wr, &wr[c], sizeof(WinResource));
-
- /* free old WinResource */
- free(wr);
- return return_wr;
- }
- }
-
- return NULL;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::find_resource(WinLibrary *fi, const char *type, const char *name, const char *language, int *level) {
- WinResource *wr;
-
- *level = 0;
- if (type == NULL)
- return NULL;
- wr = find_with_resource_array(fi, NULL, type);
- if (wr == NULL || !wr->is_directory)
- return wr;
-
- *level = 1;
- if (name == NULL)
- return wr;
- wr = find_with_resource_array(fi, wr, name);
- if (wr == NULL || !wr->is_directory)
- return wr;
-
- *level = 2;
- if (language == NULL)
- return wr;
- wr = find_with_resource_array(fi, wr, language);
- return wr;
-}
-
-#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2)
-
-
-int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) {
- Win32CursorIconFileDir dir;
- Win32CursorIconFileDirEntry *entries = NULL;
- uint32 offset;
- uint32 c, d;
- int completed;
- int matched = 0;
- Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize);
-
- if (!in->read(&dir, sizeof(Win32CursorIconFileDir)- sizeof(Win32CursorIconFileDirEntry)))
- goto cleanup;
- fix_win32_cursor_icon_file_dir_endian(&dir);
-
- if (dir.reserved != 0) {
- error("not an icon or cursor file (reserved non-zero)");
- goto cleanup;
- }
- if (dir.type != 1 && dir.type != 2) {
- error("not an icon or cursor file (wrong type)");
- goto cleanup;
- }
-
- entries = (Win32CursorIconFileDirEntry *)malloc(dir.count * sizeof(Win32CursorIconFileDirEntry));
- for (c = 0; c < dir.count; c++) {
- if (!in->read(&entries[c], sizeof(Win32CursorIconFileDirEntry)))
- goto cleanup;
- fix_win32_cursor_icon_file_dir_entry_endian(&entries[c]);
- if (entries[c].reserved != 0)
- error("reserved is not zero");
- }
-
- offset = sizeof(Win32CursorIconFileDir) + (dir.count - 1) * (sizeof(Win32CursorIconFileDirEntry));
-
- for (completed = 0; completed < dir.count; ) {
- uint32 min_offset = 0x7fffffff;
- int previous = completed;
-
- for (c = 0; c < dir.count; c++) {
- if (entries[c].dib_offset == offset) {
- Win32BitmapInfoHeader bitmap;
- Win32RGBQuad *palette = NULL;
- uint32 palette_count = 0;
- uint32 image_size, mask_size;
- uint32 width, height;
- byte *image_data = NULL, *mask_data = NULL;
- byte *row = NULL;
-
- if (!in->read(&bitmap, sizeof(Win32BitmapInfoHeader)))
- goto local_cleanup;
-
- fix_win32_bitmap_info_header_endian(&bitmap);
- if (bitmap.size < sizeof(Win32BitmapInfoHeader)) {
- error("bitmap header is too short");
- goto local_cleanup;
- }
- if (bitmap.compression != 0) {
- error("compressed image data not supported");
- goto local_cleanup;
- }
- if (bitmap.x_pels_per_meter != 0)
- error("x_pels_per_meter field in bitmap should be zero");
- if (bitmap.y_pels_per_meter != 0)
- error("y_pels_per_meter field in bitmap should be zero");
- if (bitmap.clr_important != 0)
- error("clr_important field in bitmap should be zero");
- if (bitmap.planes != 1)
- error("planes field in bitmap should be one");
- if (bitmap.size != sizeof(Win32BitmapInfoHeader)) {
- uint32 skip = bitmap.size - sizeof(Win32BitmapInfoHeader);
- error("skipping %d bytes of extended bitmap header", skip);
- in->seek(skip, SEEK_CUR);
- }
- offset += bitmap.size;
-
- if (bitmap.clr_used != 0 || bitmap.bit_count < 24) {
- palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count);
- palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count);
- if (!in->read(palette, sizeof(Win32RGBQuad) * palette_count))
- goto local_cleanup;
- offset += sizeof(Win32RGBQuad) * palette_count;
- }
-
- width = bitmap.width;
- height = ABS(bitmap.height)/2;
-
- image_size = height * ROW_BYTES(width * bitmap.bit_count);
- mask_size = height * ROW_BYTES(width);
-
- if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad))
- debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)",
- entries[c].dib_size,
- (int)(bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad))
- );
-
- image_data = (byte *)malloc(image_size);
- if (!in->read(image_data, image_size))
- goto local_cleanup;
-
- mask_data = (byte *)malloc(mask_size);
- if (!in->read(mask_data, mask_size))
- goto local_cleanup;
-
- offset += image_size;
- offset += mask_size;
- completed++;
- matched++;
-
- *hotspot_x = entries[c].hotspot_x;
- *hotspot_y = entries[c].hotspot_y;
- *w = width;
- *h = height;
- *keycolor = 0;
- *cursor = (byte *)malloc(width * height);
-
- row = (byte *)malloc(width * 4);
-
- for (d = 0; d < height; d++) {
- uint32 x;
- uint32 y = (bitmap.height < 0 ? d : height - d - 1);
- uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count;
- uint32 mmod = y * (mask_size / height) * 8;
-
- for (x = 0; x < width; x++) {
-
- uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count);
-
- // We set up cursor palette for default cursor, so use it
- if (!simple_vec(mask_data, x + mmod, 1)) {
- if (color) {
- cursor[0][width * d + x] = 254; // white
- } else {
- cursor[0][width * d + x] = 253; // black
- }
- } else {
- cursor[0][width * d + x] = 255; // transparent
- }
- /*
-
- if (bitmap.bit_count <= 16) {
- if (color >= palette_count) {
- error("color out of range in image data");
- goto local_cleanup;
- }
- row[4*x+0] = palette[color].red;
- row[4*x+1] = palette[color].green;
- row[4*x+2] = palette[color].blue;
-
- } else {
- row[4*x+0] = (color >> 16) & 0xFF;
- row[4*x+1] = (color >> 8) & 0xFF;
- row[4*x+2] = (color >> 0) & 0xFF;
- }
- if (bitmap.bit_count == 32)
- row[4*x+3] = (color >> 24) & 0xFF;
- else
- row[4*x+3] = simple_vec(mask_data, x + mmod, 1) ? 0 : 0xFF;
- */
- }
-
- }
-
- free(row);
- free(palette);
- if (image_data != NULL) {
- free(image_data);
- free(mask_data);
- }
- continue;
-
- local_cleanup:
-
- free(row);
- free(palette);
- if (image_data != NULL) {
- free(image_data);
- free(mask_data);
- }
- goto cleanup;
- } else {
- if (entries[c].dib_offset > offset)
- min_offset = MIN(min_offset, entries[c].dib_offset);
- }
- }
-
- if (previous == completed) {
- if (min_offset < offset) {
- error("offset of bitmap header incorrect (too low)");
- goto cleanup;
- }
- assert(min_offset != 0x7fffffff);
- debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset);
- in->seek(min_offset - offset, SEEK_CUR);
- offset = min_offset;
- }
- }
-
- free(entries);
- return matched;
-
-cleanup:
-
- free(entries);
- return -1;
-}
-
-uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) {
- switch (size) {
- case 1:
- return (data[ofs/8] >> (7 - ofs%8)) & 1;
- case 2:
- return (data[ofs/4] >> ((3 - ofs%4) << 1)) & 3;
- case 4:
- return (data[ofs/2] >> ((1 - ofs%2) << 2)) & 15;
- case 8:
- return data[ofs];
- case 16:
- return data[2*ofs] | data[2*ofs+1] << 8;
- case 24:
- return data[3*ofs] | data[3*ofs+1] << 8 | data[3*ofs+2] << 16;
- case 32:
- return data[4*ofs] | data[4*ofs+1] << 8 | data[4*ofs+2] << 16 | data[4*ofs+3] << 24;
- }
-
- return 0;
-}
-
-void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) {
- LE16(obj->reserved);
- LE16(obj->type);
- LE16(obj->count);
-}
-
-void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj) {
- LE32(obj->size);
- LE32(obj->width);
- LE32(obj->height);
- LE16(obj->planes);
- LE16(obj->bit_count);
- LE32(obj->compression);
- LE32(obj->size_image);
- LE32(obj->x_pels_per_meter);
- LE32(obj->y_pels_per_meter);
- LE32(obj->clr_used);
- LE32(obj->clr_important);
-}
-
-void Win32ResExtractor::fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj) {
- LE16(obj->hotspot_x);
- LE16(obj->hotspot_y);
- LE32(obj->dib_size);
- LE32(obj->dib_offset);
-}
-
-void Win32ResExtractor::fix_win32_image_section_header(Win32ImageSectionHeader *obj) {
- LE32(obj->misc.physical_address);
- LE32(obj->virtual_address);
- LE32(obj->size_of_raw_data);
- LE32(obj->pointer_to_raw_data);
- LE32(obj->pointer_to_relocations);
- LE32(obj->pointer_to_linenumbers);
- LE16(obj->number_of_relocations);
- LE16(obj->number_of_linenumbers);
- LE32(obj->characteristics);
-}
-
-/* fix_win32_image_header_endian:
- * NOTE: This assumes that the optional header is always available.
- */
-void Win32ResExtractor::fix_win32_image_header_endian(Win32ImageNTHeaders *obj) {
- LE32(obj->signature);
- LE16(obj->file_header.machine);
- LE16(obj->file_header.number_of_sections);
- LE32(obj->file_header.time_date_stamp);
- LE32(obj->file_header.pointer_to_symbol_table);
- LE32(obj->file_header.number_of_symbols);
- LE16(obj->file_header.size_of_optional_header);
- LE16(obj->file_header.characteristics);
-
- // FIXME: Does this assert ever trigger? If so, we should modify this function
- // to properly deal with it.
- assert(obj->file_header.size_of_optional_header >= sizeof(obj->optional_header));
- LE16(obj->optional_header.magic);
- LE32(obj->optional_header.size_of_code);
- LE32(obj->optional_header.size_of_initialized_data);
- LE32(obj->optional_header.size_of_uninitialized_data);
- LE32(obj->optional_header.address_of_entry_point);
- LE32(obj->optional_header.base_of_code);
- LE32(obj->optional_header.base_of_data);
- LE32(obj->optional_header.image_base);
- LE32(obj->optional_header.section_alignment);
- LE32(obj->optional_header.file_alignment);
- LE16(obj->optional_header.major_operating_system_version);
- LE16(obj->optional_header.minor_operating_system_version);
- LE16(obj->optional_header.major_image_version);
- LE16(obj->optional_header.minor_image_version);
- LE16(obj->optional_header.major_subsystem_version);
- LE16(obj->optional_header.minor_subsystem_version);
- LE32(obj->optional_header.win32_version_value);
- LE32(obj->optional_header.size_of_image);
- LE32(obj->optional_header.size_of_headers);
- LE32(obj->optional_header.checksum);
- LE16(obj->optional_header.subsystem);
- LE16(obj->optional_header.dll_characteristics);
- LE32(obj->optional_header.size_of_stack_reserve);
- LE32(obj->optional_header.size_of_stack_commit);
- LE32(obj->optional_header.size_of_heap_reserve);
- LE32(obj->optional_header.size_of_heap_commit);
- LE32(obj->optional_header.loader_flags);
- LE32(obj->optional_header.number_of_rva_and_sizes);
-}
-
-void Win32ResExtractor::fix_win32_image_data_directory(Win32ImageDataDirectory *obj) {
- LE32(obj->virtual_address);
- LE32(obj->size);
-}
-
-
MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
_resMgr = NULL;
}
-int MacResExtractor::extractResource(int id, byte **buf) {
+bool MacResExtractor::extractResource(int id, CachedCursor *cc) {
// Create the MacResManager if not created already
if (_resMgr == NULL) {
_resMgr = new Common::MacResManager();
@@ -1158,25 +167,18 @@ int MacResExtractor::extractResource(int id, byte **buf) {
error("Cannot open file %s", _fileName.c_str());
}
- Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', 1000 + id);
+ Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', id + 1000);
if (!dataStream)
- error("There is no cursor ID #%d", 1000 + id);
-
- uint32 size = dataStream->size();
- *buf = (byte *)malloc(size);
- dataStream->read(*buf, size);
- delete dataStream;
+ return false;
- return size;
-}
+ int keyColor; // HACK: key color is ignored
+ _resMgr->convertCrsrCursor(dataStream, &cc->bitmap, cc->width, cc->height, cc->hotspotX, cc->hotspotY,
+ keyColor, _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette),
+ &cc->palette, cc->palSize);
-int MacResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize) {
-
- _resMgr->convertCrsrCursor(data, datasize, cursor, w, h, hotspot_x, hotspot_y, keycolor,
- _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette), palette, palSize);
- return 1;
+ delete dataStream;
+ return true;
}
void ScummEngine_v70he::readRoomsOffsets() {
@@ -1330,7 +332,7 @@ int ScummEngine_v72he::getSoundResourceSize(int id) {
if (!ptr)
return 0;
- if (READ_BE_UINT32(ptr) == MKID_BE('RIFF')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F')) {
byte flags;
int rate;
@@ -1342,11 +344,11 @@ int ScummEngine_v72he::getSoundResourceSize(int id) {
}
} else {
ptr += 8 + READ_BE_UINT32(ptr + 12);
- if (READ_BE_UINT32(ptr) == MKID_BE('SBNG')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) {
ptr += READ_BE_UINT32(ptr + 4);
}
- assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT'));
+ assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T'));
size = READ_BE_UINT32(ptr + 4) - 8;
}
}
diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h
index 6b4c3fe493..5d7c70db76 100644
--- a/engines/scumm/he/resource_he.h
+++ b/engines/scumm/he/resource_he.h
@@ -4,10 +4,6 @@
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
- * Parts of this code are heavily based on:
- * icoutils - A set of programs dealing with MS Windows icons and cursors.
- * Copyright (C) 1998-2001 Oskar Liljeblad
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -31,89 +27,10 @@
#define SCUMM_HE_RESOURCE_HE_H
#include "common/macresman.h"
+#include "common/winexe_pe.h"
namespace Scumm {
-#define WINRES_ID_MAXLEN (256)
-
-/*
- * Definitions
- */
-
-#define MZ_HEADER(x) ((DOSImageHeader *)(x))
-
-#define STRIP_RES_ID_FORMAT(x) (x != NULL && (x[0] == '-' || x[0] == '+') ? ++x : x)
-
-#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-#define IMAGE_SIZEOF_SHORT_NAME 8
-
-#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
-#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
-
-#define PE_HEADER(module) \
- ((Win32ImageNTHeaders*)((byte *)(module) + \
- (((DOSImageHeader*)(module))->lfanew)))
-
-#define PE_SECTIONS(module) \
- ((Win32ImageSectionHeader *)((byte *) &PE_HEADER(module)->optional_header + \
- PE_HEADER(module)->file_header.size_of_optional_header))
-
-#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
-#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
-
-/* The following symbols below and another group a few lines below are defined in
- * the windows header, at least in wince and most likely in plain win32 as well.
- * Defining them out silences a redefinition warning in gcc.
- * If the same problem arises in win32 builds as well, please replace
- * _WIN32_WCE with _WIN32 which is also defined in the wince platform.
- */
-#ifndef _WIN32_WCE
-#define IMAGE_SCN_CNT_CODE 0x00000020
-#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
-#endif
-
-// Only IMAGE_DIRECTORY_ENTRY_RESOURCE is used:
-#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
-#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
-#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
-#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
-#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
-#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
-#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
-#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */
-#define IMAGE_DIRECTORY_ENTRY_TLS 9
-#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
-#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
-#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
-#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
-#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
-
-#ifndef _WIN32_WCE
-// Only RT_GROUP_CURSOR and RT_GROUP_ICON are used
-#define RT_CURSOR 1
-#define RT_BITMAP 2
-#define RT_ICON 3
-#define RT_MENU 4
-#define RT_DIALOG 5
-#define RT_STRING 6
-#define RT_FONTDIR 7
-#define RT_FONT 8
-#define RT_ACCELERATOR 9
-#define RT_RCDATA 10
-#define RT_MESSAGELIST 11
-#define RT_GROUP_CURSOR 12
-#define RT_GROUP_ICON 14
-#endif
-
-#define RETURN_IF_BAD_POINTER(r, x) \
- if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), &(x), sizeof(x))) \
- return (r);
-#define RETURN_IF_BAD_OFFSET(r, x, s) \
- if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), x, s)) \
- return (r);
-
class ScummEngine_v70he;
class ResExtractor {
@@ -123,312 +40,54 @@ public:
void setCursor(int id);
- virtual int extractResource(int id, byte **buf) { return 0; }
- virtual int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor,
- byte **palette, int *palSize) { return 0; }
-
- enum {
- MAX_CACHED_CURSORS = 10
- };
-
+protected:
struct CachedCursor {
bool valid;
int id;
byte *bitmap;
- int w, h;
- int hotspot_x, hotspot_y;
- uint32 last_used;
+ int width, height;
+ int hotspotX, hotspotY;
+ uint32 lastUsed;
byte *palette;
int palSize;
};
+ Common::String _fileName;
ScummEngine_v70he *_vm;
+ virtual bool extractResource(int id, CachedCursor *cc) = 0;
+
+private:
+ enum {
+ MAX_CACHED_CURSORS = 10
+ };
+
ResExtractor::CachedCursor *findCachedCursor(int id);
ResExtractor::CachedCursor *getCachedCursorSlot();
-
- bool _arg_raw;
- Common::String _fileName;
+
CachedCursor _cursorCache[MAX_CACHED_CURSORS];
};
class Win32ResExtractor : public ResExtractor {
- public:
+public:
Win32ResExtractor(ScummEngine_v70he *scumm);
~Win32ResExtractor() {}
- int extractResource(int id, byte **data);
- void setCursor(int id);
- int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
- private:
- int extractResource_(const char *resType, char *resName, byte **data);
-/*
- * Structures
- */
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
- struct WinLibrary {
- Common::SeekableReadStream *file;
- byte *memory;
- byte *first_resource;
- int total_size;
- } PACKED_STRUCT;
-
- struct WinResource {
- char id[256];
- void *this_;
- void *children;
- int level;
- bool numeric_id;
- bool is_directory;
-
- Common::String getQuotedResourceId() const;
- } PACKED_STRUCT;
-
-
- struct Win32IconResDir {
- byte width;
- byte height;
- byte color_count;
- byte reserved;
- } PACKED_STRUCT;
-
- struct Win32CursorDir {
- uint16 width;
- uint16 height;
- } PACKED_STRUCT;
-
- struct Win32CursorIconDirEntry {
- union {
- Win32IconResDir icon;
- Win32CursorDir cursor;
- } res_info;
- uint16 plane_count;
- uint16 bit_count;
- uint32 bytes_in_res;
- uint16 res_id;
- } PACKED_STRUCT;
-
- struct Win32CursorIconDir {
- uint16 reserved;
- uint16 type;
- uint16 count;
- Win32CursorIconDirEntry entries[1];
- } PACKED_STRUCT;
-
- struct Win32CursorIconFileDirEntry {
- byte width;
- byte height;
- byte color_count;
- byte reserved;
- uint16 hotspot_x;
- uint16 hotspot_y;
- uint32 dib_size;
- uint32 dib_offset;
- } PACKED_STRUCT;
-
- struct Win32CursorIconFileDir {
- uint16 reserved;
- uint16 type;
- uint16 count;
- Win32CursorIconFileDirEntry entries[1];
- } PACKED_STRUCT;
-
- struct Win32BitmapInfoHeader {
- uint32 size;
- int32 width;
- int32 height;
- uint16 planes;
- uint16 bit_count;
- uint32 compression;
- uint32 size_image;
- int32 x_pels_per_meter;
- int32 y_pels_per_meter;
- uint32 clr_used;
- uint32 clr_important;
- } PACKED_STRUCT;
-
- struct Win32RGBQuad {
- byte blue;
- byte green;
- byte red;
- byte reserved;
- } PACKED_STRUCT;
-
- struct Win32ImageResourceDirectoryEntry {
- uint32 name;
- uint32 offset_to_data;
- } PACKED_STRUCT;
-
- struct Win16NETypeInfo {
- uint16 type_id;
- uint16 count;
- uint32 resloader; // FARPROC16 - smaller? uint16?
- } PACKED_STRUCT;
-
- struct DOSImageHeader {
- uint16 magic;
- uint16 cblp;
- uint16 cp;
- uint16 crlc;
- uint16 cparhdr;
- uint16 minalloc;
- uint16 maxalloc;
- uint16 ss;
- uint16 sp;
- uint16 csum;
- uint16 ip;
- uint16 cs;
- uint16 lfarlc;
- uint16 ovno;
- uint16 res[4];
- uint16 oemid;
- uint16 oeminfo;
- uint16 res2[10];
- uint32 lfanew;
- } PACKED_STRUCT;
-
- struct Win32ImageFileHeader {
- uint16 machine;
- uint16 number_of_sections;
- uint32 time_date_stamp;
- uint32 pointer_to_symbol_table;
- uint32 number_of_symbols;
- uint16 size_of_optional_header;
- uint16 characteristics;
- } PACKED_STRUCT;
-
- struct Win32ImageDataDirectory {
- uint32 virtual_address;
- uint32 size;
- } PACKED_STRUCT;
-
- struct Win32ImageOptionalHeader {
- uint16 magic;
- byte major_linker_version;
- byte minor_linker_version;
- uint32 size_of_code;
- uint32 size_of_initialized_data;
- uint32 size_of_uninitialized_data;
- uint32 address_of_entry_point;
- uint32 base_of_code;
- uint32 base_of_data;
- uint32 image_base;
- uint32 section_alignment;
- uint32 file_alignment;
- uint16 major_operating_system_version;
- uint16 minor_operating_system_version;
- uint16 major_image_version;
- uint16 minor_image_version;
- uint16 major_subsystem_version;
- uint16 minor_subsystem_version;
- uint32 win32_version_value;
- uint32 size_of_image;
- uint32 size_of_headers;
- uint32 checksum;
- uint16 subsystem;
- uint16 dll_characteristics;
- uint32 size_of_stack_reserve;
- uint32 size_of_stack_commit;
- uint32 size_of_heap_reserve;
- uint32 size_of_heap_commit;
- uint32 loader_flags;
- uint32 number_of_rva_and_sizes;
- Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- } PACKED_STRUCT;
-
- struct Win32ImageNTHeaders {
- uint32 signature;
- Win32ImageFileHeader file_header;
- Win32ImageOptionalHeader optional_header;
- } PACKED_STRUCT;
-
- struct Win32ImageSectionHeader {
- byte name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- uint32 physical_address;
- uint32 virtual_size;
- } misc;
- uint32 virtual_address;
- uint32 size_of_raw_data;
- uint32 pointer_to_raw_data;
- uint32 pointer_to_relocations;
- uint32 pointer_to_linenumbers;
- uint16 number_of_relocations;
- uint16 number_of_linenumbers;
- uint32 characteristics;
- } PACKED_STRUCT;
-
- struct Win32ImageResourceDataEntry {
- uint32 offset_to_data;
- uint32 size;
- uint32 code_page;
- uint32 resource_handle;
- } PACKED_STRUCT;
-
- struct Win32ImageResourceDirectory {
- uint32 characteristics;
- uint32 time_date_stamp;
- uint16 major_version;
- uint16 minor_version;
- uint16 number_of_named_entries;
- uint16 number_of_id_entries;
- } PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
-/*
- * Function Prototypes
- */
-
- WinResource *list_resources(WinLibrary *, WinResource *, int *);
- bool read_library(WinLibrary *);
- WinResource *find_resource(WinLibrary *, const char *, const char *, const char *, int *);
- byte *get_resource_entry(WinLibrary *, WinResource *, int *);
- int do_resources(WinLibrary *, const char *, char *, char *, byte **);
- bool compare_resource_id(WinResource *, const char *);
- const char *res_type_string_to_id(const char *);
-
- const char *res_type_id_to_string(int);
- char *get_destination_name(WinLibrary *, char *, char *, char *);
-
- byte *extract_resource(WinLibrary *, WinResource *, int *, bool *, char *, char *, bool);
- int extract_resources(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, byte **);
- byte *extract_group_icon_cursor_resource(WinLibrary *, WinResource *, char *, int *, bool);
-
- bool decode_pe_resource_id(WinLibrary *, WinResource *, uint32);
- WinResource *list_pe_resources(WinLibrary *, Win32ImageResourceDirectory *, int, int *);
- int calc_vma_size(WinLibrary *);
- int do_resources_recurs(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, const char *, char *, char *, byte **);
- WinResource *find_with_resource_array(WinLibrary *, WinResource *, const char *);
-
- bool check_offset(byte *, int, const char *, void *, int);
-
- uint32 simple_vec(byte *data, uint32 ofs, byte size);
+private:
+ Common::PEResources _exe;
- void fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj);
- void fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj);
- void fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj);
- void fix_win32_image_section_header(Win32ImageSectionHeader *obj);
- void fix_win32_image_header_endian(Win32ImageNTHeaders *obj);
- void fix_win32_image_data_directory(Win32ImageDataDirectory *obj);
+ bool extractResource(int id, CachedCursor *cc);
};
class MacResExtractor : public ResExtractor {
-
public:
MacResExtractor(ScummEngine_v70he *scumm);
- ~MacResExtractor() { }
+ ~MacResExtractor() {}
private:
Common::MacResManager *_resMgr;
- int extractResource(int id, byte **buf);
- int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
+ bool extractResource(int id, CachedCursor *cc);
};
} // End of namespace Scumm
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index ca4a65ac74..69063a1837 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -2999,7 +2999,7 @@ void ScummEngine_v100he::decodeParseString(int m, int n) {
case 78:
{
byte *dataPtr = getResourceAddress(rtTalkie, pop());
- byte *text = findWrappedBlock(MKID_BE('TEXT'), dataPtr, 0, 0);
+ byte *text = findWrappedBlock(MKTAG('T','E','X','T'), dataPtr, 0, 0);
size = getResourceDataSize(text);
memcpy(name, text, size);
printString(m, name);
diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp
index 9d62a31f6d..7ecabd55e1 100644
--- a/engines/scumm/he/script_v60he.cpp
+++ b/engines/scumm/he/script_v60he.cpp
@@ -741,10 +741,14 @@ void ScummEngine_v60he::o60_openFile() {
void ScummEngine_v60he::o60_closeFile() {
int slot = pop();
if (0 <= slot && slot < 17) {
- delete _hInFileTable[slot];
- delete _hOutFileTable[slot];
+ if (_hOutFileTable[slot]) {
+ _hOutFileTable[slot]->finalize();
+ delete _hOutFileTable[slot];
+ _hOutFileTable[slot] = 0;
+ }
+
+ delete _hInFileTable[slot];
_hInFileTable[slot] = 0;
- _hOutFileTable[slot] = 0;
}
}
diff --git a/engines/scumm/he/script_v71he.cpp b/engines/scumm/he/script_v71he.cpp
index 46a8868949..a800a7d85c 100644
--- a/engines/scumm/he/script_v71he.cpp
+++ b/engines/scumm/he/script_v71he.cpp
@@ -88,15 +88,15 @@ byte *ScummEngine_v71he::heFindResource(uint32 tag, byte *searchin) {
}
byte *ScummEngine_v71he::findWrappedBlock(uint32 tag, byte *ptr, int state, bool errorFlag) {
- if (READ_BE_UINT32(ptr) == MKID_BE('MULT')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('M','U','L','T')) {
byte *offs, *wrap;
uint32 size;
- wrap = heFindResource(MKID_BE('WRAP'), ptr);
+ wrap = heFindResource(MKTAG('W','R','A','P'), ptr);
if (wrap == NULL)
return NULL;
- offs = heFindResourceData(MKID_BE('OFFS'), wrap);
+ offs = heFindResourceData(MKTAG('O','F','F','S'), wrap);
if (offs == NULL)
return NULL;
@@ -109,7 +109,7 @@ byte *ScummEngine_v71he::findWrappedBlock(uint32 tag, byte *ptr, int state, bool
if (offs)
return offs;
- offs = heFindResourceData(MKID_BE('DEFA'), ptr);
+ offs = heFindResourceData(MKTAG('D','E','F','A'), ptr);
if (offs == NULL)
return NULL;
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 32c15abcba..17bd29d826 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -1408,18 +1408,49 @@ void ScummEngine_v72he::o72_openFile() {
if (slot != -1) {
switch (mode) {
- case 1:
+ case 1: // Read mode
if (!_saveFileMan->listSavefiles(filename).empty()) {
_hInFileTable[slot] = _saveFileMan->openForLoading(filename);
} else {
_hInFileTable[slot] = SearchMan.createReadStreamForMember(filename);
}
break;
- case 2:
+ case 2: // Write mode
if (!strchr(filename, '/')) {
_hOutFileTable[slot] = _saveFileMan->openForSaving(filename);
}
break;
+ case 6: { // Append mode
+ if (strchr(filename, '/'))
+ break;
+
+ // First check if the file already exists
+ Common::InSaveFile *initialState = 0;
+ if (!_saveFileMan->listSavefiles(filename).empty())
+ initialState = _saveFileMan->openForLoading(filename);
+ else
+ initialState = SearchMan.createReadStreamForMember(filename);
+
+ // Read in the data from the initial file
+ uint32 initialSize = 0;
+ byte *initialData = 0;
+ if (initialState) {
+ initialSize = initialState->size();
+ initialData = new byte[initialSize];
+ initialState->read(initialData, initialSize);
+ delete initialState;
+ }
+
+ // Attempt to open a save file
+ _hOutFileTable[slot] = _saveFileMan->openForSaving(filename);
+
+ // Begin us off with the data from the previous file
+ if (_hOutFileTable[slot] && initialData) {
+ _hOutFileTable[slot]->write(initialData, initialSize);
+ delete[] initialData;
+ }
+
+ } break;
default:
error("o72_openFile(): wrong open file mode %d", mode);
}
@@ -2008,7 +2039,7 @@ void ScummEngine_v72he::decodeParseString(int m, int n) {
case 0xE1:
{
byte *dataPtr = getResourceAddress(rtTalkie, pop());
- byte *text = findWrappedBlock(MKID_BE('TEXT'), dataPtr, 0, 0);
+ byte *text = findWrappedBlock(MKTAG('T','E','X','T'), dataPtr, 0, 0);
size = getResourceDataSize(text);
memcpy(name, text, size);
printString(m, name);
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index 841eba960d..1a38a99f17 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -351,12 +351,12 @@ void ScummEngine_v90he::o90_max() {
}
void ScummEngine_v90he::o90_sin() {
- double a = pop() * PI / 180.;
+ double a = pop() * M_PI / 180.;
push((int)(sin(a) * 100000));
}
void ScummEngine_v90he::o90_cos() {
- double a = pop() * PI / 180.;
+ double a = pop() * M_PI / 180.;
push((int)(cos(a) * 100000));
}
@@ -372,7 +372,7 @@ void ScummEngine_v90he::o90_sqrt() {
void ScummEngine_v90he::o90_atan2() {
int y = pop();
int x = pop();
- int a = (int)(atan2((double)y, (double)x) * 180. / PI);
+ int a = (int)(atan2((double)y, (double)x) * 180. / M_PI);
if (a < 0) {
a += 360;
}
@@ -384,7 +384,7 @@ void ScummEngine_v90he::o90_getSegmentAngle() {
int x1 = pop();
int dy = y1 - pop();
int dx = x1 - pop();
- int a = (int)(atan2((double)dy, (double)dx) * 180. / PI);
+ int a = (int)(atan2((double)dy, (double)dx) * 180. / M_PI);
if (a < 0) {
a += 360;
}
@@ -2292,13 +2292,13 @@ void ScummEngine_v90he::o90_kernelGetFunctions() {
switch (args[0]) {
case 1001:
{
- double b = args[1] * PI / 180.;
+ double b = args[1] * M_PI / 180.;
push((int)(sin(b) * 100000));
}
break;
case 1002:
{
- double b = args[1] * PI / 180.;
+ double b = args[1] * M_PI / 180.;
push((int)(cos(b) * 100000));
}
break;
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 4770f28cbc..4fd7caebf5 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -499,11 +499,11 @@ byte *findSoundTag(uint32 tag, byte *ptr) {
byte *endPtr;
uint32 offset, size;
- if (READ_BE_UINT32(ptr) == MKID_BE('WSOU')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) {
ptr += 8;
}
- if (READ_BE_UINT32(ptr) != MKID_BE('RIFF'))
+ if (READ_BE_UINT32(ptr) != MKTAG('R','I','F','F'))
return NULL;
endPtr = (ptr + 12);
@@ -591,14 +591,14 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
}
// Support for sound in later HE games
- if (READ_BE_UINT32(ptr) == MKID_BE('RIFF') || READ_BE_UINT32(ptr) == MKID_BE('WSOU')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F') || READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) {
uint16 compType;
int blockAlign;
int codeOffs = -1;
priority = (soundID > _vm->_numSounds) ? 255 : *(ptr + 18);
- byte *sbngPtr = findSoundTag(MKID_BE('SBNG'), ptr);
+ byte *sbngPtr = findSoundTag(MKTAG('S','B','N','G'), ptr);
if (sbngPtr != NULL) {
codeOffs = sbngPtr - ptr + 8;
}
@@ -611,7 +611,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
return;
}
- if (READ_BE_UINT32(ptr) == MKID_BE('WSOU'))
+ if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U'))
ptr += 8;
size = READ_LE_UINT32(ptr + 4);
@@ -675,7 +675,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID);
}
// Support for sound in Humongous Entertainment games
- else if (READ_BE_UINT32(ptr) == MKID_BE('DIGI') || READ_BE_UINT32(ptr) == MKID_BE('TALK')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('D','I','G','I') || READ_BE_UINT32(ptr) == MKTAG('T','A','L','K')) {
byte *sndPtr = ptr;
int codeOffs = -1;
@@ -693,12 +693,12 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
return;
}
- if (READ_BE_UINT32(ptr) == MKID_BE('SBNG')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) {
codeOffs = ptr - sndPtr + 8;
ptr += READ_BE_UINT32(ptr + 4);
}
- assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT'));
+ assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T'));
size = READ_BE_UINT32(ptr + 4) - 8;
if (heOffset < 0 || heOffset > size) {
// Occurs when making fireworks in puttmoon
@@ -734,14 +734,14 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID);
}
// Support for PCM music in 3DO versions of Humongous Entertainment games
- else if (READ_BE_UINT32(ptr) == MKID_BE('MRAW')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('M','R','A','W')) {
priority = *(ptr + 18);
rate = READ_LE_UINT16(ptr + 22);
// Skip DIGI (8) and HSHD (24) blocks
ptr += 32;
- assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT'));
+ assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T'));
size = READ_BE_UINT32(ptr + 4) - 8;
byte *sound = (byte *)malloc(size);
@@ -753,7 +753,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
stream = Audio::makeRawStream(sound, size, rate, 0);
_mixer->playStream(Audio::Mixer::kMusicSoundType, NULL, stream, soundID);
}
- else if (READ_BE_UINT32(ptr) == MKID_BE('MIDI')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('M','I','D','I')) {
if (_vm->_imuse) {
// This is used in the DOS version of Fatty Bear's
// Birthday Surprise to change the note on the piano
@@ -833,9 +833,9 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
chan = i;
}
- if (!findSoundTag(MKID_BE('data'), snd1Ptr)) {
- sbng1Ptr = heFindResource(MKID_BE('SBNG'), snd1Ptr);
- sbng2Ptr = heFindResource(MKID_BE('SBNG'), snd2Ptr);
+ if (!findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) {
+ sbng1Ptr = heFindResource(MKTAG('S','B','N','G'), snd1Ptr);
+ sbng2Ptr = heFindResource(MKTAG('S','B','N','G'), snd2Ptr);
}
if (sbng1Ptr != NULL && sbng2Ptr != NULL) {
@@ -879,10 +879,10 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
}
}
- if (findSoundTag(MKID_BE('data'), snd1Ptr)) {
- sdat1Ptr = findSoundTag(MKID_BE('data'), snd1Ptr);
+ if (findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) {
+ sdat1Ptr = findSoundTag(MKTAG('d','a','t','a'), snd1Ptr);
assert(sdat1Ptr);
- sdat2Ptr = findSoundTag(MKID_BE('data'), snd2Ptr);
+ sdat2Ptr = findSoundTag(MKTAG('d','a','t','a'), snd2Ptr);
assert(sdat2Ptr);
if (!_sndDataSize)
@@ -890,9 +890,9 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
sdat2size = READ_LE_UINT32(sdat2Ptr + 4) - 8;
} else {
- sdat1Ptr = heFindResource(MKID_BE('SDAT'), snd1Ptr);
+ sdat1Ptr = heFindResource(MKTAG('S','D','A','T'), snd1Ptr);
assert(sdat1Ptr);
- sdat2Ptr = heFindResource(MKID_BE('SDAT'), snd2Ptr);
+ sdat2Ptr = heFindResource(MKTAG('S','D','A','T'), snd2Ptr);
assert(sdat2Ptr);
_sndDataSize = READ_BE_UINT32(sdat1Ptr + 4) - 8;
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 5f751d8285..c66eed6ae6 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -46,7 +46,7 @@ Sprite::~Sprite() {
}
void ScummEngine_v90he::allocateArrays() {
- ScummEngine::allocateArrays();
+ ScummEngine_v70he::allocateArrays();
_sprite->allocTables(_numSprites, MAX(64, _numSprites / 4), 64);
}
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index c7e6a56083..16cbadd65b 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -111,7 +111,7 @@ void Wiz::polygonStore(int id, bool flag, int vert1x, int vert1y, int vert2x, in
}
void Wiz::polygonRotatePoints(Common::Point *pts, int num, int angle) {
- double alpha = angle * PI / 180.;
+ double alpha = angle * M_PI / 180.;
double cos_alpha = cos(alpha);
double sin_alpha = sin(alpha);
@@ -1445,21 +1445,21 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
if (shadow) {
dataPtr = _vm->getResourceAddress(rtImage, shadow);
assert(dataPtr);
- xmapPtr = _vm->findResourceData(MKID_BE('XMAP'), dataPtr);
+ xmapPtr = _vm->findResourceData(MKTAG('X','M','A','P'), dataPtr);
assert(xmapPtr);
}
dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
uint32 comp = READ_LE_UINT32(wizh + 0x0);
uint32 width = READ_LE_UINT32(wizh + 0x4);
uint32 height = READ_LE_UINT32(wizh + 0x8);
debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
uint8 *mask = NULL;
@@ -1467,28 +1467,28 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum);
assert(maskPtr);
- wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), maskPtr, maskState, 0);
+ wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), maskPtr, maskState, 0);
assert(wizh);
assert(comp == 2 && READ_LE_UINT32(wizh + 0x0) == 1);
width = READ_LE_UINT32(wizh + 0x4);
height = READ_LE_UINT32(wizh + 0x8);
- mask = _vm->findWrappedBlock(MKID_BE('WIZD'), maskPtr, maskState, 0);
+ mask = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), maskPtr, maskState, 0);
assert(mask);
}
if (flags & kWIFHasPalette) {
- uint8 *pal = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0);
+ uint8 *pal = _vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0);
assert(pal);
_vm->setPaletteFromPtr(pal, 256);
}
uint8 *rmap = NULL;
if (flags & kWIFRemapPalette) {
- rmap = _vm->findWrappedBlock(MKID_BE('RMAP'), dataPtr, state, 0);
+ rmap = _vm->findWrappedBlock(MKTAG('R','M','A','P'), dataPtr, state, 0);
assert(rmap);
if (_vm->_game.heversion <= 80 || READ_BE_UINT32(rmap) != 0x01234567) {
- uint8 *rgbs = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0);
+ uint8 *rgbs = _vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0);
assert(rgbs);
_vm->remapHEPalette(rgbs, rmap + 4);
}
@@ -1526,7 +1526,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
if (dstResNum) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
assert(dstPtr);
- dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0);
assert(dst);
getWizImageDim(dstResNum, 0, cw, ch);
dstPitch = cw * _vm->_bytesPerPixel;
@@ -1567,7 +1567,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
int transColor = -1;
if (_vm->VAR_WIZ_TCOLOR != 0xFF) {
- uint8 *trns = _vm->findWrappedBlock(MKID_BE('TRNS'), dataPtr, state, 0);
+ uint8 *trns = _vm->findWrappedBlock(MKTAG('T','R','N','S'), dataPtr, state, 0);
transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1;
}
@@ -1817,7 +1817,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
assert(_vm->_bytesPerPixel == 1);
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ srcWizBuf = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(srcWizBuf);
freeBuffer = false;
}
@@ -1827,7 +1827,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
} else {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ srcWizBuf = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(srcWizBuf);
freeBuffer = false;
}
@@ -1842,7 +1842,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
if (dstResNum) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
assert(dstPtr);
- dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0);
assert(dst);
getWizImageDim(dstResNum, 0, dstw, dsth);
dstpitch = dstw * _vm->_bytesPerPixel;
@@ -2185,7 +2185,7 @@ void Wiz::fillWizRect(const WizParameters *params) {
}
uint8 *dataPtr = _vm->getResourceAddress(rtImage, params->img.resNum);
if (dataPtr) {
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -2210,7 +2210,7 @@ void Wiz::fillWizRect(const WizParameters *params) {
}
if (areaRect.intersects(imageRect)) {
areaRect.clip(imageRect);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
int dx = areaRect.width();
int dy = areaRect.height();
@@ -2256,7 +2256,7 @@ void Wiz::fillWizLine(const WizParameters *params) {
}
uint8 *dataPtr = _vm->getResourceAddress(rtImage, params->img.resNum);
if (dataPtr) {
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -2274,7 +2274,7 @@ void Wiz::fillWizLine(const WizParameters *params) {
if (params->processFlags & kWPFFillColor) {
color = params->fillColor;
}
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
int x1 = params->box2.left;
int y1 = params->box2.top;
@@ -2309,7 +2309,7 @@ void Wiz::fillWizPixel(const WizParameters *params) {
if (params->processFlags & kWPFNewState) {
state = params->img.state;
}
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -2327,7 +2327,7 @@ void Wiz::fillWizPixel(const WizParameters *params) {
color = params->fillColor;
}
if (imageRect.contains(px, py)) {
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
*(wizd + py * w + px) = color;
}
@@ -2342,7 +2342,7 @@ void Wiz::remapWizImagePal(const WizParameters *params) {
const uint8 *index = params->remapIndex;
uint8 *iwiz = _vm->getResourceAddress(rtImage, params->img.resNum);
assert(iwiz);
- uint8 *rmap = _vm->findWrappedBlock(MKID_BE('RMAP'), iwiz, st, 0);
+ uint8 *rmap = _vm->findWrappedBlock(MKTAG('R','M','A','P'), iwiz, st, 0);
assert(rmap);
WRITE_BE_UINT32(rmap, 0x01234567);
while (num--) {
@@ -2380,7 +2380,7 @@ void Wiz::processWizImage(const WizParameters *params) {
if (f) {
uint32 id = f->readUint32BE();
- if (id == MKID_BE('AWIZ') || id == MKID_BE('MULT')) {
+ if (id == MKTAG('A','W','I','Z') || id == MKTAG('M','U','L','T')) {
uint32 size = f->readUint32BE();
f->seek(0, SEEK_SET);
byte *p = _vm->_res->createResource(rtImage, params->img.resNum, size);
@@ -2510,7 +2510,7 @@ void Wiz::processWizImage(const WizParameters *params) {
void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
w = READ_LE_UINT32(wizh + 0x4);
h = READ_LE_UINT32(wizh + 0x8);
@@ -2519,7 +2519,7 @@ void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) {
void Wiz::getWizImageSpot(int resId, int state, int32 &x, int32 &y) {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resId);
assert(dataPtr);
- uint8 *spotPtr = _vm->findWrappedBlock(MKID_BE('SPOT'), dataPtr, state, 0);
+ uint8 *spotPtr = _vm->findWrappedBlock(MKTAG('S','P','O','T'), dataPtr, state, 0);
if (spotPtr) {
x = READ_LE_UINT32(spotPtr + 0);
y = READ_LE_UINT32(spotPtr + 4);
@@ -2537,17 +2537,17 @@ int Wiz::getWizImageData(int resNum, int state, int type) {
switch (type) {
case 0:
- wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
return READ_LE_UINT32(wizh + 0x0);
case 1:
- return (_vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0) != NULL) ? 1 : 0;
case 2:
- return (_vm->findWrappedBlock(MKID_BE('RMAP'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('R','M','A','P'), dataPtr, state, 0) != NULL) ? 1 : 0;
case 3:
- return (_vm->findWrappedBlock(MKID_BE('TRNS'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('T','R','N','S'), dataPtr, state, 0) != NULL) ? 1 : 0;
case 4:
- return (_vm->findWrappedBlock(MKID_BE('XMAP'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('X','M','A','P'), dataPtr, state, 0) != NULL) ? 1 : 0;
default:
error("getWizImageData: Unknown type %d", type);
}
@@ -2556,14 +2556,14 @@ int Wiz::getWizImageData(int resNum, int state, int type) {
int Wiz::getWizImageStates(int resNum) {
const uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- if (READ_BE_UINT32(dataPtr) == MKID_BE('MULT')) {
+ if (READ_BE_UINT32(dataPtr) == MKTAG('M','U','L','T')) {
const byte *offs, *wrap;
- wrap = _vm->findResource(MKID_BE('WRAP'), dataPtr);
+ wrap = _vm->findResource(MKTAG('W','R','A','P'), dataPtr);
if (wrap == NULL)
return 1;
- offs = _vm->findResourceData(MKID_BE('OFFS'), wrap);
+ offs = _vm->findResourceData(MKTAG('O','F','F','S'), wrap);
if (offs == NULL)
return 1;
@@ -2577,12 +2577,12 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags
int ret = 0;
uint8 *data = _vm->getResourceAddress(rtImage, resNum);
assert(data);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), data, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
int h = READ_LE_UINT32(wizh + 0x8);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), data, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0);
assert(wizd);
if (x >= 0 && x < w && y >= 0 && y < h) {
if (flags & kWIFFlipX) {
@@ -2627,12 +2627,12 @@ uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) {
uint16 color = 0;
uint8 *data = _vm->getResourceAddress(rtImage, resNum);
assert(data);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), data, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
int h = READ_LE_UINT32(wizh + 0x8);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), data, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0);
assert(wizd);
switch (c) {
case 0:
@@ -2671,13 +2671,13 @@ int ScummEngine_v90he::computeWizHistogram(int resNum, int state, int x, int y,
Common::Rect rCapt(x, y, w + 1, h + 1);
uint8 *data = getResourceAddress(rtImage, resNum);
assert(data);
- uint8 *wizh = findWrappedBlock(MKID_BE('WIZH'), data, state, 0);
+ uint8 *wizh = findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
w = READ_LE_UINT32(wizh + 0x4);
h = READ_LE_UINT32(wizh + 0x8);
Common::Rect rWiz(w, h);
- uint8 *wizd = findWrappedBlock(MKID_BE('WIZD'), data, state, 0);
+ uint8 *wizd = findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0);
assert(wizd);
if (rCapt.intersects(rWiz)) {
rCapt.clip(rWiz);
diff --git a/engines/scumm/help.cpp b/engines/scumm/help.cpp
index 3738ebc2e5..a3bb85ab42 100644
--- a/engines/scumm/help.cpp
+++ b/engines/scumm/help.cpp
@@ -79,14 +79,14 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo
ADD_BIND(".", _("Skip line of text"));
ADD_BIND(_("Esc"), _("Skip cutscene"));
ADD_BIND(_("Space"), _("Pause game"));
- ADD_BIND(_("Ctrl 0-9"), _("Load game state 1-10"));
- ADD_BIND(_("Alt 0-9"), _("Save game state 1-10"));
+ ADD_BIND(String(_("Ctrl")) + " 0-9", _("Load game state 1-10"));
+ ADD_BIND(String(_("Alt")) + " 0-9", _("Save game state 1-10"));
#ifdef MACOSX
ADD_BIND("Cmd q", _("Quit"));
#else
- ADD_BIND(_("Alt x, Ctrl z"), _("Quit"));
+ ADD_BIND(String(_("Alt")) + " x, " + _("Ctrl") + " z", _("Quit"));
#endif
- ADD_BIND(_("Alt Enter"), _("Toggle fullscreen"));
+ ADD_BIND(String(_("Alt")) + " " + _("Enter"), _("Toggle fullscreen"));
ADD_BIND("[, ]", _("Music volume up / down"));
ADD_BIND("-, +", _("Text speed slower / faster"));
ADD_BIND(_("Enter"), _("Simulate left mouse button"));
@@ -95,14 +95,14 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo
case 2:
title = _("Special keyboard commands:");
ADD_BIND("~, #", _("Show / Hide console"));
- ADD_BIND(_("Ctrl d"), _("Start the debugger"));
- ADD_BIND(_("Ctrl s"), _("Show memory consumption"));
- ADD_BIND(_("Ctrl f"), _("Run in fast mode (*)"));
- ADD_BIND(_("Ctrl g"), _("Run in really fast mode (*)"));
- ADD_BIND(_("Ctrl m"), _("Toggle mouse capture"));
- ADD_BIND(_("Ctrl Alt 1-8"), _("Switch between graphics filters"));
- ADD_BIND(_("Ctrl Alt +, -"), _("Increase / Decrease scale factor"));
- ADD_BIND(_("Ctrl Alt a"), _("Toggle aspect-ratio correction"));
+ ADD_BIND(String(_("Ctrl")) + " d", _("Start the debugger"));
+ ADD_BIND(String(_("Ctrl")) + " s", _("Show memory consumption"));
+ ADD_BIND(String(_("Ctrl")) + " f", _("Run in fast mode (*)"));
+ ADD_BIND(String(_("Ctrl")) + " g", _("Run in really fast mode (*)"));
+ ADD_BIND(String(_("Ctrl")) + " m", _("Toggle mouse capture"));
+ ADD_BIND(String(_("Ctrl")) + " " + _("Alt") + " 1-8", _("Switch between graphics filters"));
+ ADD_BIND(String(_("Ctrl")) + " " + _("Alt") + " +, -", _("Increase / Decrease scale factor"));
+ ADD_BIND(String(_("Ctrl")) + " " + _("Alt") + " a", _("Toggle aspect-ratio correction"));
ADD_LINE;
ADD_LINE;
// FIXME: This should use word-wrapping, and should not assume
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 4db40e6247..07fd99c809 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -57,7 +57,6 @@ _initialized(false),
_tempoFactor(0),
_player_limit(ARRAYSIZE(_players)),
_recycle_players(false),
-_direct_passthrough(false),
_queue_end(0),
_queue_pos(0),
_queue_sound(0),
@@ -151,22 +150,22 @@ bool IMuseInternal::isMT32(int sound) {
tag = READ_BE_UINT32(ptr + 4);
switch (tag) {
- case MKID_BE('ADL '):
- case MKID_BE('ASFX'): // Special AD class for old AdLib sound effects
- case MKID_BE('SPK '):
+ case MKTAG('A','D','L',' '):
+ case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects
+ case MKTAG('S','P','K',' '):
return false;
- case MKID_BE('AMI '):
- case MKID_BE('ROL '):
+ case MKTAG('A','M','I',' '):
+ case MKTAG('R','O','L',' '):
return true;
- case MKID_BE('MAC '): // Occurs in the Mac version of FOA and MI2
+ case MKTAG('M','A','C',' '): // Occurs in the Mac version of FOA and MI2
return true;
- case MKID_BE('GMD '):
+ case MKTAG('G','M','D',' '):
return false;
- case MKID_BE('MIDI'): // Occurs in Sam & Max
+ case MKTAG('M','I','D','I'): // Occurs in Sam & Max
// HE games use Roland music
if (ptr[12] == 'H' && ptr[13] == 'S')
return true;
@@ -198,20 +197,20 @@ bool IMuseInternal::isMIDI(int sound) {
tag = READ_BE_UINT32(ptr + 4);
switch (tag) {
- case MKID_BE('ADL '):
- case MKID_BE('ASFX'): // Special AD class for old AdLib sound effects
- case MKID_BE('SPK '):
+ case MKTAG('A','D','L',' '):
+ case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects
+ case MKTAG('S','P','K',' '):
return false;
- case MKID_BE('AMI '):
- case MKID_BE('ROL '):
+ case MKTAG('A','M','I',' '):
+ case MKTAG('R','O','L',' '):
return true;
- case MKID_BE('MAC '): // Occurs in the Mac version of FOA and MI2
+ case MKTAG('M','A','C',' '): // Occurs in the Mac version of FOA and MI2
return true;
- case MKID_BE('GMD '):
- case MKID_BE('MIDI'): // Occurs in Sam & Max
+ case MKTAG('G','M','D',' '):
+ case MKTAG('M','I','D','I'): // Occurs in Sam & Max
return true;
}
@@ -472,10 +471,6 @@ uint32 IMuseInternal::property(int prop, uint32 value) {
_recycle_players = (value != 0);
break;
- case IMuse::PROP_DIRECT_PASSTHROUGH:
- _direct_passthrough = (value != 0);
- break;
-
case IMuse::PROP_GAME_ID:
_game_id = value;
break;
@@ -636,7 +631,7 @@ bool IMuseInternal::startSound_internal(int sound, int offset) {
player->clear();
player->setOffsetNote(offset);
- return player->startSound(sound, driver, _direct_passthrough);
+ return player->startSound(sound, driver);
}
int IMuseInternal::stopSound_internal(int sound) {
diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h
index d7ce2b7bdd..1e3b0fd756 100644
--- a/engines/scumm/imuse/imuse.h
+++ b/engines/scumm/imuse/imuse.h
@@ -58,7 +58,6 @@ public:
PROP_GS,
PROP_LIMIT_PLAYERS,
PROP_RECYCLE_PLAYERS,
- PROP_DIRECT_PASSTHROUGH,
PROP_GAME_ID
};
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index 0014480894..7d46650d2e 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -155,7 +155,7 @@ struct CommandQueue {
//
//////////////////////////////////////////////////
-class Player : public MidiDriver {
+class Player : public MidiDriver_BASE {
/*
* External SysEx handler functions shall each be defined in
* a separate file. This header file shall be included at the
@@ -174,7 +174,6 @@ protected:
protected:
MidiDriver *_midi;
MidiParser *_parser;
- bool _passThrough; // Only respond to EOT, all else direct to MidiDriver
Part *_parts;
bool _active;
@@ -278,21 +277,14 @@ public:
void setSpeed(byte speed);
int setTranspose(byte relative, int b);
int setVolume(byte vol);
- bool startSound(int sound, MidiDriver *midi, bool passThrough);
+ bool startSound(int sound, MidiDriver *midi);
int getMusicTimer() const;
public:
// MidiDriver interface
- int open() { return 0; }
- void close() { }
void send(uint32 b);
- const char *getErrorName(int error_code) { return "Unknown"; }
void sysEx(const byte *msg, uint16 length);
void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timer_param, void(*timer_proc)(void *)) { }
- uint32 getBaseTempo();
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
};
@@ -424,7 +416,6 @@ protected:
int _player_limit; // Limits how many simultaneous music tracks are played
bool _recycle_players; // Can we stop a player in order to start another one?
- bool _direct_passthrough; // Pass data direct to MidiDriver (no interactivity)
uint _queue_end, _queue_pos, _queue_sound;
byte _queue_adding;
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index ac2b2d4203..4d185d94d7 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -61,7 +61,6 @@ uint16 Player::_active_notes[128];
Player::Player() :
_midi(NULL),
_parser(NULL),
- _passThrough(0),
_parts(NULL),
_active(false),
_scanning(false),
@@ -93,7 +92,7 @@ Player::~Player() {
}
}
-bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
+bool Player::startSound(int sound, MidiDriver *midi) {
void *ptr;
int i;
@@ -119,7 +118,6 @@ bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
_pan = 0;
_transpose = 0;
_detune = 0;
- _passThrough = passThrough;
for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i)
_parameterFaders[i].init();
@@ -227,11 +225,6 @@ void Player::setSpeed(byte speed) {
}
void Player::send(uint32 b) {
- if (_passThrough) {
- _midi->send(b);
- return;
- }
-
byte cmd = (byte)(b & 0xF0);
byte chan = (byte)(b & 0x0F);
byte param1 = (byte)((b >> 8) & 0xFF);
@@ -348,11 +341,6 @@ void Player::sysEx(const byte *p, uint16 len) {
byte buf[128];
Part *part;
- if (_passThrough) {
- _midi->sysEx(p, len);
- return;
- }
-
// Check SysEx manufacturer.
a = *p++;
--len;
@@ -998,10 +986,6 @@ void Player::fixAfterLoad() {
}
}
-uint32 Player::getBaseTempo() {
- return (_midi ? _midi->getBaseTempo() : 0);
-}
-
void Player::metaEvent(byte type, byte *msg, uint16 len) {
if (type == 0x2F)
clear();
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index 516a0497fa..3831689def 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -31,6 +31,7 @@
#include "scumm/sound.h"
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
#include "scumm/imuse_digi/dimuse_track.h"
#include "audio/audiostream.h"
diff --git a/engines/scumm/imuse_digi/dimuse_bndmgr.cpp b/engines/scumm/imuse_digi/dimuse_bndmgr.cpp
index f10f17f3d8..cb894d77cc 100644
--- a/engines/scumm/imuse_digi/dimuse_bndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_bndmgr.cpp
@@ -28,6 +28,7 @@
#include "scumm/util.h"
#include "scumm/file.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
namespace Scumm {
@@ -92,7 +93,7 @@ int BundleDirCache::matchFile(const char *filename) {
error("BundleDirCache::matchFileFile() Can't find free slot for file bundle dir cache");
tag = file.readUint32BE();
- if (tag == MKID_BE('LB23'))
+ if (tag == MKTAG('L','B','2','3'))
_budleDirCache[freeSlot].isCompressed = true;
offset = file.readUint32BE();
@@ -112,7 +113,7 @@ int BundleDirCache::matchFile(const char *filename) {
int32 z = 0;
int32 z2;
- if (tag == MKID_BE('LB23')) {
+ if (tag == MKTAG('L','B','2','3')) {
file.read(_budleDirCache[freeSlot].bundleTable[i].filename, 24);
} else {
for (z2 = 0; z2 < 8; z2++)
@@ -224,7 +225,7 @@ bool BundleMgr::loadCompTable(int32 index) {
assert(_numCompItems > 0);
_file->seek(8, SEEK_CUR);
- if (tag != MKID_BE('COMP')) {
+ if (tag != MKTAG('C','O','M','P')) {
error("BundleMgr::loadCompTable() Compressed sound %d (%s:%d) invalid (%s)", index, _file->getName(), _bundleTable[index].offset, tag2str(tag));
return false;
}
diff --git a/engines/scumm/imuse_digi/dimuse_bndmgr.h b/engines/scumm/imuse_digi/dimuse_bndmgr.h
index a78697a854..bed1ac6549 100644
--- a/engines/scumm/imuse_digi/dimuse_bndmgr.h
+++ b/engines/scumm/imuse_digi/dimuse_bndmgr.h
@@ -107,14 +107,6 @@ public:
int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **compFinal, int headerSize, bool headerOutside);
};
-namespace BundleCodecs {
-
-uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size);
-void initializeImcTables();
-int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize);
-
-} // End of namespace BundleCodecs
-
} // End of namespace Scumm
#endif
diff --git a/engines/scumm/imuse_digi/dimuse_codecs.cpp b/engines/scumm/imuse_digi/dimuse_codecs.cpp
index 3f7c341701..f526530405 100644
--- a/engines/scumm/imuse_digi/dimuse_codecs.cpp
+++ b/engines/scumm/imuse_digi/dimuse_codecs.cpp
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/util.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
namespace Scumm {
@@ -59,7 +60,8 @@ uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size) {
* varies the size of each "packet" between 2 and 7 bits.
*/
-static byte _imcTableEntryBitCount[89];
+static byte *_destImcTable = NULL;
+static uint32 *_destImcTable2 = NULL;
static const int16 imcTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14,
@@ -116,23 +118,47 @@ static const byte imxOtherTable[6][64] = {
}
};
+void releaseImcTables() {
+ free(_destImcTable);
+ free(_destImcTable2);
+}
+
void initializeImcTables() {
int pos;
- for (pos = 0; pos < ARRAYSIZE(imcTable); ++pos) {
- byte put = 0;
+ if (!_destImcTable) _destImcTable = (byte *)calloc(89, sizeof(byte));
+ if (!_destImcTable2) _destImcTable2 = (uint32 *)calloc(89 * 64, sizeof(uint32));
+
+ for (pos = 0; pos <= 88; ++pos) {
+ byte put = 1;
int32 tableValue = ((imcTable[pos] * 4) / 7) / 2;
while (tableValue != 0) {
tableValue /= 2;
put++;
}
- if (put < 2) {
- put = 2;
+ if (put < 3) {
+ put = 3;
+ }
+ if (put > 8) {
+ put = 8;
}
- if (put > 7) {
- put = 7;
+ _destImcTable[pos] = put - 1;
+ }
+
+ for (int n = 0; n < 64; n++) {
+ for (pos = 0; pos <= 88; ++pos) {
+ int32 count = 32;
+ int32 put = 0;
+ int32 tableValue = imcTable[pos];
+ do {
+ if ((count & n) != 0) {
+ put += tableValue;
+ }
+ count /= 2;
+ tableValue /= 2;
+ } while (count != 0);
+ _destImcTable2[n + pos * 64] = put;
}
- _imcTableEntryBitCount[pos] = put;
}
}
@@ -183,8 +209,134 @@ static int32 compDecode(byte *src, byte *dst) {
}
#undef NextBit
+int32 decompressADPCM(byte *compInput, byte *compOutput, int channels) {
+ byte *src;
+
+ // Decoder for the the IMA ADPCM variants used in COMI.
+ // Contrary to regular IMA ADPCM, this codec uses a variable
+ // bitsize for the encoded data.
+
+ const int MAX_CHANNELS = 2;
+ int32 outputSamplesLeft;
+ int32 destPos;
+ int16 firstWord;
+ byte initialTablePos[MAX_CHANNELS] = {0, 0};
+ int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7};
+ int32 initialOutputWord[MAX_CHANNELS] = {0, 0};
+ int32 totalBitOffset, curTablePos, outputWord;
+ byte *dst;
+ int i;
+
+ // We only support mono and stereo
+ assert(channels == 1 || channels == 2);
+
+ src = compInput;
+ dst = compOutput;
+ outputSamplesLeft = 0x1000;
+
+ // Every data packet contains 0x2000 bytes of audio data
+ // when extracted. In order to encode bigger data sets,
+ // one has to split the data into multiple blocks.
+ //
+ // Every block starts with a 2 byte word. If that word is
+ // non-zero, it indicates the size of a block of raw audio
+ // data (not encoded) following it. That data we simply copy
+ // to the output buffer and the proceed by decoding the
+ // remaining data.
+ //
+ // If on the other hand the word is zero, then what follows
+ // are 7*channels bytes containing seed data for the decoder.
+ firstWord = READ_BE_UINT16(src);
+ src += 2;
+ if (firstWord != 0) {
+ // Copy raw data
+ memcpy(dst, src, firstWord);
+ dst += firstWord;
+ src += firstWord;
+ assert((firstWord & 1) == 0);
+ outputSamplesLeft -= firstWord / 2;
+ } else {
+ // Read the seed values for the decoder.
+ for (i = 0; i < channels; i++) {
+ initialTablePos[i] = *src;
+ src += 1;
+ initialimcTableEntry[i] = READ_BE_UINT32(src);
+ src += 4;
+ initialOutputWord[i] = READ_BE_UINT32(src);
+ src += 4;
+ }
+ }
+
+ totalBitOffset = 0;
+ // The channels are encoded separately.
+ for (int chan = 0; chan < channels; chan++) {
+ // Read initial state (this makes it possible for the data stream
+ // to be split & spread across multiple data chunks.
+ curTablePos = initialTablePos[chan];
+ //imcTableEntry = initialimcTableEntry[chan];
+ outputWord = initialOutputWord[chan];
+
+ // We need to interleave the channels in the output; we achieve
+ // that by using a variables dest offset:
+ destPos = chan * 2;
+
+ const int bound = (channels == 1)
+ ? outputSamplesLeft
+ : ((chan == 0)
+ ? (outputSamplesLeft+1) / 2
+ : outputSamplesLeft / 2);
+ for (i = 0; i < bound; ++i) {
+ // Determine the size (in bits) of the next data packet
+ const int32 curTableEntryBitCount = _destImcTable[curTablePos];
+ assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7);
+
+ // Read the next data packet
+ const byte *readPos = src + (totalBitOffset >> 3);
+ const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7));
+ const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount));
+
+ // Advance read position to the next data packet
+ totalBitOffset += curTableEntryBitCount;
+
+ // Decode the data packet into a delta value for the output signal.
+ const byte signBitMask = (1 << (curTableEntryBitCount - 1));
+ const byte dataBitMask = (signBitMask - 1);
+ const byte data = (packet & dataBitMask);
+
+ const int32 tmpA = (data << (7 - curTableEntryBitCount));
+ const int32 imcTableEntry = imcTable[curTablePos] >> (curTableEntryBitCount - 1);
+ int32 delta = imcTableEntry + _destImcTable2[tmpA + (curTablePos * 64)];
+
+ // The topmost bit in the data packet tells is a sign bit
+ if ((packet & signBitMask) != 0) {
+ delta = -delta;
+ }
+
+ // Accumulate the delta onto the output data
+ outputWord += delta;
+
+ // Clip outputWord to 16 bit signed, and write it into the destination stream
+ if (outputWord > 0x7fff)
+ outputWord = 0x7fff;
+ if (outputWord < -0x8000)
+ outputWord = -0x8000;
+ WRITE_BE_UINT16(dst + destPos, outputWord);
+ destPos += channels << 1;
+
+ // Adjust the curTablePos
+ curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data];
+ if (curTablePos < 0)
+ curTablePos = 0;
+ else if (curTablePos >= ARRAYSIZE(imcTable))
+ curTablePos = ARRAYSIZE(imcTable) - 1;
+ }
+ }
+
+ return 0x2000;
+}
+
int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize) {
- int32 outputSize, channels;
+ int32 outputSize;
int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z;
byte *src, *t_table, *p, *ptr;
byte t_tmp1, t_tmp2;
@@ -506,132 +658,7 @@ int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inpu
case 13:
case 15:
- if (codec == 13) {
- channels = 1;
- } else {
- channels = 2;
- }
-
- {
- // Decoder for the the IMA ADPCM variants used in COMI.
- // Contrary to regular IMA ADPCM, this codec uses a variable
- // bitsize for the encoded data.
-
- const int MAX_CHANNELS = 2;
- int32 outputSamplesLeft;
- int32 destPos;
- int16 firstWord;
- byte initialTablePos[MAX_CHANNELS] = {0, 0};
- int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7};
- int32 initialOutputWord[MAX_CHANNELS] = {0, 0};
- int32 totalBitOffset, curTablePos, outputWord;
- byte *dst;
- int i;
-
- // We only support mono and stereo
- assert(channels == 1 || channels == 2);
-
- src = compInput;
- dst = compOutput;
- outputSize = 0x2000;
- outputSamplesLeft = 0x1000;
-
- // Every data packet contains 0x2000 bytes of audio data
- // when extracted. In order to encode bigger data sets,
- // one has to split the data into multiple blocks.
- //
- // Every block starts with a 2 byte word. If that word is
- // non-zero, it indicates the size of a block of raw audio
- // data (not encoded) following it. That data we simply copy
- // to the output buffer and the proceed by decoding the
- // remaining data.
- //
- // If on the other hand the word is zero, then what follows
- // are 7*channels bytes containing seed data for the decoder.
- firstWord = READ_BE_UINT16(src);
- src += 2;
- if (firstWord != 0) {
- // Copy raw data
- memcpy(dst, src, firstWord);
- dst += firstWord;
- src += firstWord;
- assert((firstWord & 1) == 0);
- outputSamplesLeft -= firstWord / 2;
- } else {
- // Read the seed values for the decoder.
- for (i = 0; i < channels; i++) {
- initialTablePos[i] = *src;
- src += 1;
- initialimcTableEntry[i] = READ_BE_UINT32(src);
- src += 4;
- initialOutputWord[i] = READ_BE_UINT32(src);
- src += 4;
- }
- }
-
- totalBitOffset = 0;
- // The channels are encoded separately.
- for (int chan = 0; chan < channels; chan++) {
- // Read initial state (this makes it possible for the data stream
- // to be split & spread across multiple data chunks.
- curTablePos = initialTablePos[chan];
- //imcTableEntry = initialimcTableEntry[chan];
- outputWord = initialOutputWord[chan];
-
- // We need to interleave the channels in the output; we achieve
- // that by using a variables dest offset:
- destPos = chan * 2;
-
- const int bound = (channels == 1)
- ? outputSamplesLeft
- : ((chan == 0)
- ? (outputSamplesLeft+1) / 2
- : outputSamplesLeft / 2);
- for (i = 0; i < bound; ++i) {
- // Determine the size (in bits) of the next data packet
- const int32 curTableEntryBitCount = _imcTableEntryBitCount[curTablePos];
- assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7);
-
- // Read the next data packet
- const byte *readPos = src + (totalBitOffset >> 3);
- const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7));
- const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount));
-
- // Advance read position to the next data packet
- totalBitOffset += curTableEntryBitCount;
-
- // Decode the data packet into a delta value for the output signal.
- const byte signBitMask = (1 << (curTableEntryBitCount - 1));
- const byte dataBitMask = (signBitMask - 1);
- const byte data = (packet & dataBitMask);
-
- int32 delta = imcTable[curTablePos] * (2 * data + 1) >> (curTableEntryBitCount - 1);
-
- // The topmost bit in the data packet tells is a sign bit
- if ((packet & signBitMask) != 0) {
- delta = -delta;
- }
-
- // Accumulate the delta onto the output data
- outputWord += delta;
-
- // Clip outputWord to 16 bit signed, and write it into the destination stream
- if (outputWord > 0x7fff)
- outputWord = 0x7fff;
- if (outputWord < -0x8000)
- outputWord = -0x8000;
- WRITE_BE_UINT16(dst + destPos, outputWord);
- destPos += channels << 1;
-
- // Adjust the curTablePos
- curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data];
- if (curTablePos < 0)
- curTablePos = 0;
- else if (curTablePos >= ARRAYSIZE(imcTable))
- curTablePos = ARRAYSIZE(imcTable) - 1;
- }
- }
- }
+ outputSize = decompressADPCM(compInput, compOutput, (codec == 13) ? 1 : 2);
break;
default:
diff --git a/engines/scumm/imuse_digi/dimuse_codecs.h b/engines/scumm/imuse_digi/dimuse_codecs.h
new file mode 100644
index 0000000000..71fd24c3ac
--- /dev/null
+++ b/engines/scumm/imuse_digi/dimuse_codecs.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef SCUMM_IMUSE_DIGI_CODECS_H
+#define SCUMM_IMUSE_DIGI_CODECS_H
+
+#include "common/scummsys.h"
+
+namespace Scumm {
+
+namespace BundleCodecs {
+
+uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size);
+int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize);
+
+void initializeImcTables();
+void releaseImcTables();
+
+} // End of namespace BundleCodecs
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index 00074a951a..2cd90c4f2b 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -34,8 +34,9 @@
#include "scumm/scumm.h"
#include "scumm/util.h"
#include "scumm/imuse_digi/dimuse.h"
-#include "scumm/imuse_digi/dimuse_sndmgr.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
+#include "scumm/imuse_digi/dimuse_sndmgr.h"
namespace Scumm {
@@ -56,6 +57,7 @@ ImuseDigiSndMgr::~ImuseDigiSndMgr() {
}
delete _cacheBundleDir;
+ BundleCodecs::releaseImcTables();
}
void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs, int &numMarkers) {
@@ -65,32 +67,32 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
switch (tag) {
- case MKID_BE('STOP'):
- case MKID_BE('FRMT'):
- case MKID_BE('DATA'):
+ case MKTAG('S','T','O','P'):
+ case MKTAG('F','R','M','T'):
+ case MKTAG('D','A','T','A'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
if (!scumm_stricmp((const char *)(ptr + 8), "exit"))
numMarkers++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('REGN'):
+ case MKTAG('R','E','G','N'):
numRegions++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('JUMP'):
+ case MKTAG('J','U','M','P'):
numJumps++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('SYNC'):
+ case MKTAG('S','Y','N','C'):
numSyncs++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
default:
error("ImuseDigiSndMgr::countElements() Unknown sfx header '%s'", tag2str(tag));
}
- } while (tag != MKID_BE('DATA'));
+ } while (tag != MKTAG('D','A','T','A'));
}
void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, SoundDesc *sound, int32 offset, int32 size) {
@@ -98,7 +100,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, Sou
file->seek(offset, SEEK_SET);
uint32 tag = file->readUint32BE();
- assert(tag == MKID_BE('RMAP'));
+ assert(tag == MKTAG('R','M','A','P'));
int32 version = file->readUint32BE();
if (version != 3) {
if (version == 2) {
@@ -153,7 +155,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, Sou
}
void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
- if (READ_BE_UINT32(ptr) == MKID_BE('Crea')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('C','r','e','a')) {
bool quit = false;
int len;
@@ -222,7 +224,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
}
offset += len;
}
- } else if (READ_BE_UINT32(ptr) == MKID_BE('iMUS')) {
+ } else if (READ_BE_UINT32(ptr) == MKTAG('i','M','U','S')) {
uint32 tag;
int32 size = 0;
byte *s_ptr = ptr;
@@ -250,13 +252,13 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
switch (tag) {
- case MKID_BE('FRMT'):
+ case MKTAG('F','R','M','T'):
ptr += 12;
sound->bits = READ_BE_UINT32(ptr); ptr += 4;
sound->freq = READ_BE_UINT32(ptr); ptr += 4;
sound->channels = READ_BE_UINT32(ptr); ptr += 4;
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
if (!scumm_stricmp((const char *)(ptr + 8), "exit")) {
sound->marker[curIndexMarker].pos = READ_BE_UINT32(ptr + 4);
sound->marker[curIndexMarker].length = strlen((const char *)(ptr + 8)) + 1;
@@ -267,16 +269,16 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
}
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('STOP'):
+ case MKTAG('S','T','O','P'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('REGN'):
+ case MKTAG('R','E','G','N'):
ptr += 4;
sound->region[curIndexRegion].offset = READ_BE_UINT32(ptr); ptr += 4;
sound->region[curIndexRegion].length = READ_BE_UINT32(ptr); ptr += 4;
curIndexRegion++;
break;
- case MKID_BE('JUMP'):
+ case MKTAG('J','U','M','P'):
ptr += 4;
sound->jump[curIndexJump].offset = READ_BE_UINT32(ptr); ptr += 4;
sound->jump[curIndexJump].dest = READ_BE_UINT32(ptr); ptr += 4;
@@ -284,7 +286,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
sound->jump[curIndexJump].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
curIndexJump++;
break;
- case MKID_BE('SYNC'):
+ case MKTAG('S','Y','N','C'):
size = READ_BE_UINT32(ptr); ptr += 4;
sound->sync[curIndexSync].size = size;
sound->sync[curIndexSync].ptr = new byte[size];
@@ -293,13 +295,13 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
curIndexSync++;
ptr += size;
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
ptr += 4;
break;
default:
error("ImuseDigiSndMgr::prepareSound(%d/%s) Unknown sfx header '%s'", sound->soundId, sound->name, tag2str(tag));
}
- } while (tag != MKID_BE('DATA'));
+ } while (tag != MKTAG('D','A','T','A'));
sound->offsetData = ptr - s_ptr;
} else {
error("ImuseDigiSndMgr::prepareSound(): Unknown sound format");
diff --git a/engines/scumm/insane/insane.cpp b/engines/scumm/insane/insane.cpp
index f2e50382b3..a82c0ae408 100644
--- a/engines/scumm/insane/insane.cpp
+++ b/engines/scumm/insane/insane.cpp
@@ -1413,7 +1413,7 @@ int32 Insane::smush_setupSanWithFlu(const char *filename, int32 setupsan2, int32
_smush_setupsan1 = setupsan1;
/* skip FLUP marker */
- if (READ_BE_UINT32(fluPtr) == MKID_BE('FLUP'))
+ if (READ_BE_UINT32(fluPtr) == MKTAG('F','L','U','P'))
tmp += 8;
_smush_setupsan2 = setupsan2;
diff --git a/engines/scumm/insane/insane_iact.cpp b/engines/scumm/insane/insane_iact.cpp
index 942256b1a4..265931ecc2 100644
--- a/engines/scumm/insane/insane_iact.cpp
+++ b/engines/scumm/insane/insane_iact.cpp
@@ -62,7 +62,7 @@ void Insane::procIACT(byte *renderBitmap, int32 codecparam, int32 setupsan12,
void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
- int16 par5, par6, par7, par9, par11, par13, tmp;
+ int16 par5, par6, par7, par9, par11, par13;
switch (par1) {
case 2: // PATCH
@@ -99,15 +99,15 @@ void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
if (par2 != 13)
break;
- tmp = b.readUint16LE(); // +8
- tmp = b.readUint16LE(); // +10
- par7 = b.readUint16LE(); // +12 dx
- tmp = b.readUint16LE(); // +14
- par9 = b.readUint16LE(); // +16 bx
- tmp = b.readUint16LE(); // +18
- par11 = b.readUint16LE(); // +20 cx
- tmp = b.readUint16LE(); // +22
- par13 = b.readUint16LE(); // +24 ax
+ b.readUint16LE(); // +8
+ b.readUint16LE(); // +10
+ par7 = b.readUint16LE(); // +12 dx
+ b.readUint16LE(); // +14
+ par9 = b.readUint16LE(); // +16 bx
+ b.readUint16LE(); // +18
+ par11 = b.readUint16LE(); // +20 cx
+ b.readUint16LE(); // +22
+ par13 = b.readUint16LE(); // +24 ax
if (par13 > _actor[0].x || par11 < _actor[0].x) {
_tiresRustle = true;
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index d56017c6f5..7f250e45e0 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -95,7 +95,7 @@ void NutRenderer::loadFont(const char *filename) {
}
uint32 tag = file.readUint32BE();
- if (tag != MKID_BE('ANIM')) {
+ if (tag != MKTAG('A','N','I','M')) {
error("NutRenderer::loadFont() there is no ANIM chunk in font header");
}
@@ -104,7 +104,7 @@ void NutRenderer::loadFont(const char *filename) {
file.read(dataSrc, length);
file.close();
- if (READ_BE_UINT32(dataSrc) != MKID_BE('AHDR')) {
+ if (READ_BE_UINT32(dataSrc) != MKTAG('A','H','D','R')) {
error("NutRenderer::loadFont() there is no AHDR chunk in font header");
}
@@ -142,12 +142,12 @@ void NutRenderer::loadFont(const char *filename) {
offset = 0;
for (l = 0; l < _numChars; l++) {
offset += READ_BE_UINT32(dataSrc + offset + 4) + 8;
- if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FRME')) {
+ if (READ_BE_UINT32(dataSrc + offset) != MKTAG('F','R','M','E')) {
error("NutRenderer::loadFont(%s) there is no FRME chunk %d (offset %x)", filename, l, offset);
break;
}
offset += 8;
- if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FOBJ')) {
+ if (READ_BE_UINT32(dataSrc + offset) != MKTAG('F','O','B','J')) {
error("NutRenderer::loadFont(%s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, l, offset);
break;
}
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index c44043ca81..c2547f74f4 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -416,7 +416,7 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
debug(0, "getObjectXYPos: Can't find object %d", object);
return;
}
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), ptr);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), ptr);
assert(imhd);
if (_game.version == 8) {
switch (FROM_LE_32(imhd->v8.version)) {
@@ -655,7 +655,7 @@ void ScummEngine::drawObject(int obj, int arg) {
flags |= Gdi::dbDrawMaskOnAll;
#ifdef ENABLE_HE
- if (_game.heversion >= 70 && findResource(MKID_BE('SMAP'), ptr) == NULL)
+ if (_game.heversion >= 70 && findResource(MKTAG('S','M','A','P'), ptr) == NULL)
_gdi->drawBMAPObject(ptr, &_virtscr[kMainVirtScreen], obj, od.x_pos, od.y_pos, od.width, od.height);
else
#endif
@@ -762,12 +762,12 @@ void ScummEngine::resetRoomObjects() {
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
- ptr = obcds.findNext(MKID_BE('OBCD'));
+ ptr = obcds.findNext(MKTAG('O','B','C','D'));
if (ptr == NULL)
error("Room %d missing object code block(s)", _roomResource);
od->OBCDoffset = ptr - rootptr;
- cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), ptr);
+ cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), ptr);
if (_game.version >= 7)
od->obj_nr = READ_LE_UINT16(&(cdhd->v7.obj_id));
@@ -779,7 +779,7 @@ void ScummEngine::resetRoomObjects() {
if (_dumpScripts) {
char buf[32];
sprintf(buf, "roomobj-%d-", _roomResource);
- ptr = findResource(MKID_BE('VERB'), ptr);
+ ptr = findResource(MKTAG('V','E','R','B'), ptr);
dumpResource(buf, od->obj_nr, ptr);
}
@@ -788,7 +788,7 @@ void ScummEngine::resetRoomObjects() {
searchptr = room;
ResourceIterator obims(room, false);
for (i = 0; i < _numObjectsInRoom; i++) {
- ptr = obims.findNext(MKID_BE('OBIM'));
+ ptr = obims.findNext(MKTAG('O','B','I','M'));
if (ptr == NULL)
error("Room %d missing image blocks(s)", _roomResource);
@@ -870,7 +870,7 @@ void ScummEngine_v4::resetRoomObjects() {
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
- ptr = obcds.findNext(MKID_BE('OBCD'));
+ ptr = obcds.findNext(MKTAG('O','B','C','D'));
if (ptr == NULL)
error("Room %d missing object code block(s)", _roomResource);
@@ -887,7 +887,7 @@ void ScummEngine_v4::resetRoomObjects() {
for (i = 0; i < _numObjectsInRoom; i++) {
// In the PC Engine version of Loom, there aren't image blocks
// for all objects.
- ptr = obims.findNext(MKID_BE('OBIM'));
+ ptr = obims.findNext(MKTAG('O','B','I','M'));
if (ptr == NULL)
break;
@@ -991,11 +991,11 @@ void ScummEngine::resetRoomObject(ObjectData *od, const byte *room, const byte *
searchptr = room;
}
- cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), searchptr + od->OBCDoffset);
+ cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), searchptr + od->OBCDoffset);
if (cdhd == NULL)
error("Room %d missing CDHD blocks(s)", _roomResource);
if (od->OBIMoffset)
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), room + od->OBIMoffset);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), room + od->OBIMoffset);
od->flags = Gdi::dbAllowMaskOr;
@@ -1194,7 +1194,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) {
return (objptr + offset);
}
- return findResourceData(MKID_BE('OBNA'), objptr);
+ return findResourceData(MKTAG('O','B','N','A'), objptr);
}
void ScummEngine::setObjectName(int obj) {
@@ -1278,7 +1278,7 @@ const byte *ScummEngine::getOBIMFromObjectData(const ObjectData &od) {
if (od.fl_object_index) {
ptr = getResourceAddress(rtFlObject, od.fl_object_index);
- ptr = findResource(MKID_BE('OBIM'), ptr);
+ ptr = findResource(MKTAG('O','B','I','M'), ptr);
} else {
ptr = getResourceAddress(rtRoom, _roomResource);
if (ptr)
@@ -1288,23 +1288,23 @@ const byte *ScummEngine::getOBIMFromObjectData(const ObjectData &od) {
}
static const uint32 IMxx_tags[] = {
- MKID_BE('IM00'),
- MKID_BE('IM01'),
- MKID_BE('IM02'),
- MKID_BE('IM03'),
- MKID_BE('IM04'),
- MKID_BE('IM05'),
- MKID_BE('IM06'),
- MKID_BE('IM07'),
- MKID_BE('IM08'),
- MKID_BE('IM09'),
- MKID_BE('IM0A'),
- MKID_BE('IM0B'),
- MKID_BE('IM0C'),
- MKID_BE('IM0D'),
- MKID_BE('IM0E'),
- MKID_BE('IM0F'),
- MKID_BE('IM10')
+ MKTAG('I','M','0','0'),
+ MKTAG('I','M','0','1'),
+ MKTAG('I','M','0','2'),
+ MKTAG('I','M','0','3'),
+ MKTAG('I','M','0','4'),
+ MKTAG('I','M','0','5'),
+ MKTAG('I','M','0','6'),
+ MKTAG('I','M','0','7'),
+ MKTAG('I','M','0','8'),
+ MKTAG('I','M','0','9'),
+ MKTAG('I','M','0','A'),
+ MKTAG('I','M','0','B'),
+ MKTAG('I','M','0','C'),
+ MKTAG('I','M','0','D'),
+ MKTAG('I','M','0','E'),
+ MKTAG('I','M','0','F'),
+ MKTAG('I','M','1','0')
};
const byte *ScummEngine::getObjectImage(const byte *ptr, int state) {
@@ -1317,15 +1317,15 @@ const byte *ScummEngine::getObjectImage(const byte *ptr, int state) {
// The OBIM contains an IMAG, which in turn contains a WRAP, which contains
// an OFFS chunk and multiple BOMP/SMAP chunks. To find the right BOMP/SMAP,
// we use the offsets in the OFFS chunk,
- ptr = findResource(MKID_BE('IMAG'), ptr);
+ ptr = findResource(MKTAG('I','M','A','G'), ptr);
if (!ptr)
return 0;
- ptr = findResource(MKID_BE('WRAP'), ptr);
+ ptr = findResource(MKTAG('W','R','A','P'), ptr);
if (!ptr)
return 0;
- ptr = findResource(MKID_BE('OFFS'), ptr);
+ ptr = findResource(MKTAG('O','F','F','S'), ptr);
if (!ptr)
return 0;
@@ -1348,7 +1348,7 @@ int ScummEngine::getObjectImageCount(int object) {
return 0;
ptr = getOBIMFromObjectData(_objs[objnum]);
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), ptr);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), ptr);
if (!imhd)
return 0;
@@ -1365,7 +1365,7 @@ int ScummEngine::getObjectImageCount(int object) {
int ScummEngine_v8::getObjectIdFromOBIM(const byte *obim) {
// In V8, IMHD has no obj_id, but rather a name string. We map the name
// back to an object id using a table derived from the DOBJ resource.
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
ObjectNameId *found = (ObjectNameId *)bsearch(imhd->v8.name, _objectIDMap, _objectIDMapSize,
sizeof(ObjectNameId), (int (*)(const void*, const void*))strcmp);
assert(found);
@@ -1373,7 +1373,7 @@ int ScummEngine_v8::getObjectIdFromOBIM(const byte *obim) {
}
int ScummEngine_v7::getObjectIdFromOBIM(const byte *obim) {
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
return READ_LE_UINT16(&imhd->v7.obj_id);
}
#endif
@@ -1382,7 +1382,7 @@ int ScummEngine::getObjectIdFromOBIM(const byte *obim) {
if (_game.features & GF_SMALL_HEADER)
return READ_LE_UINT16(obim + 6);
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
return READ_LE_UINT16(&imhd->old.obj_id);
}
@@ -1400,7 +1400,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (findWhat & foCodeHeader) {
fo->obcd = obcdptr = getOBCDFromObject(id);
assert(obcdptr);
- fo->cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), obcdptr);
+ fo->cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), obcdptr);
}
if (findWhat & foImageHeader) {
fo->obim = obimptr = getOBIMFromObjectData(_objs[id2]);
@@ -1416,7 +1416,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (_game.features & GF_OLD_BUNDLE) {
numobj = roomptr[20];
} else {
- const RoomHeader *roomhdr = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr);
+ const RoomHeader *roomhdr = (const RoomHeader *)findResourceData(MKTAG('R','M','H','D'), roomptr);
if (_game.version == 8)
numobj = READ_LE_UINT32(&(roomhdr->v8.numObjects));
@@ -1467,10 +1467,10 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
assert(searchptr);
ResourceIterator obcds(searchptr, (_game.features & GF_SMALL_HEADER) != 0);
for (i = 0; i < numobj; i++) {
- obcdptr = obcds.findNext(MKID_BE('OBCD'));
+ obcdptr = obcds.findNext(MKTAG('O','B','C','D'));
if (obcdptr == NULL)
error("findObjectInRoom: Not enough code blocks in room %d", room);
- cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), obcdptr);
+ cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), obcdptr);
if (_game.features & GF_SMALL_HEADER)
id2 = READ_LE_UINT16(obcdptr + 6);
@@ -1495,7 +1495,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (findWhat & foImageHeader) {
ResourceIterator obims(roomptr, (_game.features & GF_SMALL_HEADER) != 0);
for (i = 0; i < numobj; i++) {
- obimptr = obims.findNext(MKID_BE('OBIM'));
+ obimptr = obims.findNext(MKTAG('O','B','I','M'));
if (obimptr == NULL)
error("findObjectInRoom: Not enough image blocks in room %d", room);
obim_id = getObjectIdFromOBIM(obimptr);
@@ -1699,7 +1699,7 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) {
if (!img)
img = getObjectImage(ptr, 1); // Backward compatibility with samnmax blast objects
assert(img);
- bomp = findResourceData(MKID_BE('BOMP'), img);
+ bomp = findResourceData(MKTAG('B','O','M','P'), img);
}
if (!bomp)
@@ -1843,7 +1843,7 @@ void ScummEngine::loadFlObject(uint object, uint room) {
char buf[32];
const byte *ptr = foir.obcd;
sprintf(buf, "roomobj-%d-", room);
- ptr = findResource(MKID_BE('VERB'), ptr);
+ ptr = findResource(MKTAG('V','E','R','B'), ptr);
dumpResource(buf, object, ptr);
}
@@ -1869,7 +1869,7 @@ void ScummEngine::loadFlObject(uint object, uint room) {
assert(flob);
// Copy object code + object image to floating object
- WRITE_UINT32(flob, MKID_BE('FLOB'));
+ WRITE_UINT32(flob, MKTAG('F','L','O','B'));
WRITE_BE_UINT32(flob + 4, flob_size);
memcpy(flob + 8, foir.obcd, obcd_size);
memcpy(flob + 8 + obcd_size, foir.obim, obim_size);
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 52592cd90e..e81212fec8 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -1029,7 +1029,7 @@ void ScummEngine::setCurrentPalette(int palindex) {
void ScummEngine::setRoomPalette(int palindex, int room) {
const byte *roomptr = getResourceAddress(rtRoom, room);
assert(roomptr);
- const byte *pals = findResource(MKID_BE('PALS'), roomptr);
+ const byte *pals = findResource(MKTAG('P','A','L','S'), roomptr);
assert(pals);
const byte *rgbs = findPalInPals(pals, palindex);
assert(rgbs);
@@ -1040,11 +1040,11 @@ const byte *ScummEngine::findPalInPals(const byte *pal, int idx) {
const byte *offs;
uint32 size;
- pal = findResource(MKID_BE('WRAP'), pal);
+ pal = findResource(MKTAG('W','R','A','P'), pal);
if (pal == NULL)
return NULL;
- offs = findResourceData(MKID_BE('OFFS'), pal);
+ offs = findResourceData(MKTAG('O','F','F','S'), pal);
if (offs == NULL)
return NULL;
@@ -1081,7 +1081,7 @@ void ScummEngine::updatePalette() {
int num = _palDirtyMax - first + 1;
int i;
- byte palette_colors[1024];
+ byte palette_colors[3 * 256];
byte *p = palette_colors;
for (i = _palDirtyMin; i <= _palDirtyMax; i++) {
@@ -1108,12 +1108,10 @@ void ScummEngine::updatePalette() {
*p++ = brightness;
*p++ = brightness;
*p++ = brightness;
- *p++ = 0;
} else {
*p++ = data[0];
*p++ = data[1];
*p++ = data[2];
- *p++ = 0;
}
}
@@ -1126,7 +1124,7 @@ void ScummEngine::updatePalette() {
p = palette_colors;
for (i = first; i < first + num; ++i) {
_16BitPalette[i] = get16BitColor(p[0], p[1], p[2]);
- p += 4;
+ p += 3;
}
return;
}
diff --git a/engines/scumm/player_pce.cpp b/engines/scumm/player_pce.cpp
index 4236fb2d6b..46d976773d 100644
--- a/engines/scumm/player_pce.cpp
+++ b/engines/scumm/player_pce.cpp
@@ -515,7 +515,7 @@ int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
int sampleCopyCnt;
int samplesLeft = numSamples;
- _mutex.lock();
+ Common::StackLock lock(_mutex);
while (true) {
// copy samples to output buffer
@@ -543,8 +543,6 @@ int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
_sampleBufferCnt * sizeof(int16));
}
- _mutex.unlock();
-
return numSamples;
}
diff --git a/engines/scumm/player_sid.cpp b/engines/scumm/player_sid.cpp
index 34654a68c5..0d5832a5fb 100644
--- a/engines/scumm/player_sid.cpp
+++ b/engines/scumm/player_sid.cpp
@@ -1287,7 +1287,7 @@ uint8 *Player_SID::getResource(int resID) {
int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
int samplesLeft = numSamples;
- _mutex.lock();
+ Common::StackLock lock(_mutex);
while (samplesLeft > 0) {
// update SID status after each frame
@@ -1301,8 +1301,6 @@ int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
buffer += sampleCount;
}
- _mutex.unlock();
-
return numSamples;
}
@@ -1337,7 +1335,7 @@ void Player_SID::startSound(int nr) {
// prio 7 is never used in any sound file use this byte for auto-detection.
bool isMusic = (data[4] == 0x07);
- _mutex.lock();
+ Common::StackLock lock(_mutex);
if (isMusic) {
initMusic(nr);
@@ -1345,29 +1343,25 @@ void Player_SID::startSound(int nr) {
stopSound_intern(nr);
initSound(nr);
}
-
- _mutex.unlock();
}
void Player_SID::stopSound(int nr) {
if (nr == -1)
return;
- _mutex.lock();
+ Common::StackLock lock(_mutex);
stopSound_intern(nr);
- _mutex.unlock();
}
void Player_SID::stopAllSounds() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
stopAllSounds_intern();
- _mutex.unlock();
}
int Player_SID::getSoundStatus(int nr) const {
int result = 0;
- //_mutex.lock();
+ //Common::StackLock lock(_mutex);
if (resID_song == nr && isMusicPlaying) {
result = 1;
@@ -1379,8 +1373,6 @@ int Player_SID::getSoundStatus(int nr) const {
}
}
- //_mutex.unlock();
-
return result;
}
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index 06f97fd671..8922ff1730 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -622,7 +622,7 @@ int Player_Towns_v2::getSoundStatus(int sound) const {
void Player_Towns_v2::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
- if (READ_BE_UINT32(ptr) == MKID_BE('TOWS')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) {
_soundOverride[sound].type = 7;
uint8 velo = _soundOverride[sound].velo ? _soundOverride[sound].velo - 1: (ptr[10] + ptr[11] + 1) >> 1;
uint8 pan = _soundOverride[sound].pan ? _soundOverride[sound].pan - 1 : 64;
@@ -630,7 +630,7 @@ void Player_Towns_v2::startSound(int sound) {
_soundOverride[sound].velo = _soundOverride[sound].pan = 0;
playPcmTrack(sound, ptr + 8, velo, pan, ptr[52], pri);
- } else if (READ_BE_UINT32(ptr) == MKID_BE('SBL ')) {
+ } else if (READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
_soundOverride[sound].type = 5;
playVocTrack(ptr + 27);
@@ -680,7 +680,7 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) {
case 258:
if (_soundOverride[args[1]].type == 0) {
ptr = _vm->getResourceAddress(rtSound, args[1]);
- if (READ_BE_UINT32(ptr) == MKID_BE('TOWS'))
+ if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S'))
_soundOverride[args[1]].type = 7;
}
if (_soundOverride[args[1]].type == 7) {
@@ -692,7 +692,7 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) {
case 259:
if (_soundOverride[args[1]].type == 0) {
ptr = _vm->getResourceAddress(rtSound, args[1]);
- if (READ_BE_UINT32(ptr) == MKID_BE('TOWS'))
+ if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S'))
_soundOverride[args[1]].type = 7;
}
if (_soundOverride[args[1]].type == 7) {
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 5aae59d987..c872a83d14 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -167,8 +167,6 @@ void ScummEngine::deleteRoomOffsets() {
/** Read room offsets */
void ScummEngine::readRoomsOffsets() {
- int num, room;
-
debug(9, "readRoomOffsets()");
if (_game.features & GF_SMALL_HEADER) {
@@ -177,13 +175,12 @@ void ScummEngine::readRoomsOffsets() {
_fileHandle->seek(16, SEEK_SET);
}
- num = _fileHandle->readByte();
+ int num = _fileHandle->readByte();
while (num--) {
- room = _fileHandle->readByte();
+ int room = _fileHandle->readByte();
+ int offset = _fileHandle->readUint32LE();
if (_res->roomoffs[rtRoom][room] != RES_INVALID_OFFSET) {
- _res->roomoffs[rtRoom][room] = _fileHandle->readUint32LE();
- } else {
- _fileHandle->readUint32LE();
+ _res->roomoffs[rtRoom][room] = offset;
}
}
}
@@ -262,26 +259,26 @@ void ScummEngine::readIndexFile() {
if (_fileHandle->eos() || _fileHandle->err())
break;
switch (blocktype) {
- case MKID_BE('DOBJ'):
+ case MKTAG('D','O','B','J'):
_numGlobalObjects = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DROO'):
+ case MKTAG('D','R','O','O'):
_numRooms = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DSCR'):
+ case MKTAG('D','S','C','R'):
_numScripts = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DCOS'):
+ case MKTAG('D','C','O','S'):
_numCostumes = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DSOU'):
+ case MKTAG('D','S','O','U'):
_numSounds = _fileHandle->readUint16LE();
itemsize -= 2;
break;
@@ -354,7 +351,7 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) {
int num;
char *ptr;
switch (blocktype) {
- case MKID_BE('ANAM'): // Used by: The Dig, FT
+ case MKTAG('A','N','A','M'): // Used by: The Dig, FT
debug(9, "found ANAM block, reading audio names");
num = _fileHandle->readUint16LE();
ptr = (char*)malloc(num * 9);
@@ -362,7 +359,7 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) {
_imuseDigital->setAudioNames(num, ptr);
break;
- case MKID_BE('DRSC'): // Used by: COMI
+ case MKTAG('D','R','S','C'): // Used by: COMI
readResTypeList(rtRoomScripts);
break;
@@ -375,37 +372,37 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) {
void ScummEngine_v70he::readIndexBlock(uint32 blocktype, uint32 itemsize) {
int i;
switch (blocktype) {
- case MKID_BE('DIRI'):
+ case MKTAG('D','I','R','I'):
readResTypeList(rtRoomImage);
break;
- case MKID_BE('DIRM'):
+ case MKTAG('D','I','R','M'):
readResTypeList(rtImage);
break;
- case MKID_BE('DIRT'):
+ case MKTAG('D','I','R','T'):
readResTypeList(rtTalkie);
break;
- case MKID_BE('DLFL'):
+ case MKTAG('D','L','F','L'):
i = _fileHandle->readUint16LE();
_fileHandle->seek(-2, SEEK_CUR);
_heV7RoomOffsets = (byte *)calloc(2 + (i * 4), 1);
_fileHandle->read(_heV7RoomOffsets, (2 + (i * 4)) );
break;
- case MKID_BE('DISK'):
+ case MKTAG('D','I','S','K'):
i = _fileHandle->readUint16LE();
_heV7DiskOffsets = (byte *)calloc(i, 1);
_fileHandle->read(_heV7DiskOffsets, i);
break;
- case MKID_BE('SVER'):
+ case MKTAG('S','V','E','R'):
// Index version number
_fileHandle->seek(itemsize - 8, SEEK_CUR);
break;
- case MKID_BE('INIB'):
+ case MKTAG('I','N','I','B'):
_fileHandle->seek(itemsize - 8, SEEK_CUR);
debug(2, "INIB index block not yet handled, skipping");
break;
@@ -418,17 +415,17 @@ void ScummEngine_v70he::readIndexBlock(uint32 blocktype, uint32 itemsize) {
void ScummEngine::readIndexBlock(uint32 blocktype, uint32 itemsize) {
int i;
switch (blocktype) {
- case MKID_BE('DCHR'):
- case MKID_BE('DIRF'):
+ case MKTAG('D','C','H','R'):
+ case MKTAG('D','I','R','F'):
readResTypeList(rtCharset);
break;
- case MKID_BE('DOBJ'):
+ case MKTAG('D','O','B','J'):
debug(9, "found DOBJ block, reading object table");
readGlobalObjects();
break;
- case MKID_BE('RNAM'):
+ case MKTAG('R','N','A','M'):
// Names of rooms. Maybe we should put them into a table, for use by the debugger?
if (_game.heversion >= 80) {
for (int room; (room = _fileHandle->readUint16LE()); ) {
@@ -452,32 +449,32 @@ void ScummEngine::readIndexBlock(uint32 blocktype, uint32 itemsize) {
}
break;
- case MKID_BE('DROO'):
- case MKID_BE('DIRR'):
+ case MKTAG('D','R','O','O'):
+ case MKTAG('D','I','R','R'):
readResTypeList(rtRoom);
break;
- case MKID_BE('DSCR'):
- case MKID_BE('DIRS'):
+ case MKTAG('D','S','C','R'):
+ case MKTAG('D','I','R','S'):
readResTypeList(rtScript);
break;
- case MKID_BE('DCOS'):
- case MKID_BE('DIRC'):
+ case MKTAG('D','C','O','S'):
+ case MKTAG('D','I','R','C'):
readResTypeList(rtCostume);
break;
- case MKID_BE('MAXS'):
+ case MKTAG('M','A','X','S'):
readMAXS(itemsize);
allocateArrays();
break;
- case MKID_BE('DIRN'):
- case MKID_BE('DSOU'):
+ case MKTAG('D','I','R','N'):
+ case MKTAG('D','S','O','U'):
readResTypeList(rtSound);
break;
- case MKID_BE('AARY'):
+ case MKTAG('A','A','R','Y'):
readArrayFromIndexFile();
break;
@@ -491,7 +488,7 @@ void ScummEngine::readArrayFromIndexFile() {
error("readArrayFromIndexFile() not supported in pre-V6 games");
}
-void ScummEngine::readResTypeList(int id) {
+int ScummEngine::readResTypeList(int id) {
int num;
int i;
@@ -511,16 +508,27 @@ void ScummEngine::readResTypeList(int id) {
}
for (i = 0; i < num; i++) {
_res->roomoffs[id][i] = _fileHandle->readUint32LE();
-
- if (id == rtRoom && _game.heversion >= 70)
- _heV7RoomIntOffsets[i] = _res->roomoffs[id][i];
}
- if (_game.heversion >= 70) {
+ return num;
+}
+
+int ScummEngine_v70he::readResTypeList(int id) {
+ int num;
+ int i;
+
+ num = ScummEngine::readResTypeList(id);
+
+ if (id == rtRoom)
for (i = 0; i < num; i++) {
- _res->globsize[id][i] = _fileHandle->readUint32LE();
+ _heV7RoomIntOffsets[i] = _res->roomoffs[rtRoom][i];
}
+
+ for (i = 0; i < num; i++) {
+ _res->globsize[id][i] = _fileHandle->readUint32LE();
}
+
+ return num;
}
void ResourceManager::allocResTypeData(int id, uint32 tag, int num_, const char *name_, int mode_) {
@@ -635,18 +643,9 @@ int ScummEngine::loadResource(int type, int idx) {
if (roomNr == 0)
roomNr = _roomResource;
- if (type == rtRoom) {
- if (_game.version == 8)
- fileOffs = 8;
- else if (_game.heversion >= 70)
- fileOffs = _heV7RoomIntOffsets[idx];
- else
- fileOffs = 0;
- } else {
- fileOffs = _res->roomoffs[type][idx];
- if (fileOffs == RES_INVALID_OFFSET)
- return 0;
- }
+ fileOffs = getResourceRoomOffset(type, idx);
+ if (fileOffs == RES_INVALID_OFFSET)
+ return 0;
openRoom(roomNr);
@@ -691,13 +690,11 @@ int ScummEngine::loadResource(int type, int idx) {
dumpResource("script-", idx, getResourceAddress(rtScript, idx));
}
- if (!_fileHandle->err() && !_fileHandle->eos()) {
- return 1;
+ if (_fileHandle->err() || _fileHandle->eos()) {
+ error("Cannot read resource");
}
- _res->nukeResource(type, idx);
-
- error("Cannot read resource");
+ return 1;
}
int ScummEngine::getResourceRoomNr(int type, int idx) {
@@ -706,6 +703,20 @@ int ScummEngine::getResourceRoomNr(int type, int idx) {
return _res->roomno[type][idx];
}
+uint32 ScummEngine::getResourceRoomOffset(int type, int idx) {
+ if (type == rtRoom) {
+ return (_game.version == 8) ? 8 : 0;
+ }
+ return _res->roomoffs[type][idx];
+}
+
+uint32 ScummEngine_v70he::getResourceRoomOffset(int type, int idx) {
+ if (type == rtRoom) {
+ return _heV7RoomIntOffsets[idx];
+ }
+ return _res->roomoffs[type][idx];
+}
+
int ScummEngine::getResourceSize(int type, int idx) {
byte *ptr = getResourceAddress(type, idx);
assert(ptr);
@@ -1276,14 +1287,14 @@ void ScummEngine::allocateArrays() {
_arraySlot = (byte *)calloc(_numArray, 1);
}
- _res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKID_BE('AKOS') : MKID_BE('COST'),
+ _res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKTAG('A','K','O','S') : MKTAG('C','O','S','T'),
_numCostumes, "costume", 1);
- _res->allocResTypeData(rtRoom, MKID_BE('ROOM'), _numRooms, "room", 1);
- _res->allocResTypeData(rtRoomImage, MKID_BE('RMIM'), _numRooms, "room image", 1);
- _res->allocResTypeData(rtRoomScripts, MKID_BE('RMSC'), _numRooms, "room script", 1);
- _res->allocResTypeData(rtSound, MKID_BE('SOUN'), _numSounds, "sound", 2);
- _res->allocResTypeData(rtScript, MKID_BE('SCRP'), _numScripts, "script", 1);
- _res->allocResTypeData(rtCharset, MKID_BE('CHAR'), _numCharsets, "charset", 1);
+ _res->allocResTypeData(rtRoom, MKTAG('R','O','O','M'), _numRooms, "room", 1);
+ _res->allocResTypeData(rtRoomImage, MKTAG('R','M','I','M'), _numRooms, "room image", 1);
+ _res->allocResTypeData(rtRoomScripts, MKTAG('R','M','S','C'), _numRooms, "room script", 1);
+ _res->allocResTypeData(rtSound, MKTAG('S','O','U','N'), _numSounds, "sound", 2);
+ _res->allocResTypeData(rtScript, MKTAG('S','C','R','P'), _numScripts, "script", 1);
+ _res->allocResTypeData(rtCharset, MKTAG('C','H','A','R'), _numCharsets, "charset", 1);
_res->allocResTypeData(rtObjectName, 0, _numNewNames, "new name", 0);
_res->allocResTypeData(rtInventory, 0, _numInventory, "inventory", 0);
_res->allocResTypeData(rtTemp, 0, 10, "temp", 0);
@@ -1293,15 +1304,18 @@ void ScummEngine::allocateArrays() {
_res->allocResTypeData(rtString, 0, _numArray, "array", 0);
_res->allocResTypeData(rtFlObject, 0, _numFlObject, "flobject", 0);
_res->allocResTypeData(rtMatrix, 0, 10, "boxes", 0);
- _res->allocResTypeData(rtImage, MKID_BE('AWIZ'), _numImages, "images", 1);
- _res->allocResTypeData(rtTalkie, MKID_BE('TLKE'), _numTalkies, "talkie", 1);
+ _res->allocResTypeData(rtImage, MKTAG('A','W','I','Z'), _numImages, "images", 1);
+ _res->allocResTypeData(rtTalkie, MKTAG('T','L','K','E'), _numTalkies, "talkie", 1);
+}
- if (_game.heversion >= 70) {
- _res->allocResTypeData(rtSpoolBuffer, 0, 9, "spool buffer", 1);
- _heV7RoomIntOffsets = (uint32 *)calloc(_numRooms, sizeof(uint32));
- }
+void ScummEngine_v70he::allocateArrays() {
+ ScummEngine::allocateArrays();
+
+ _res->allocResTypeData(rtSpoolBuffer, 0, 9, "spool buffer", 1);
+ _heV7RoomIntOffsets = (uint32 *)calloc(_numRooms, sizeof(uint32));
}
+
void ScummEngine::dumpResource(const char *tag, int idx, const byte *ptr, int length) {
char buf[256];
Common::DumpFile out;
@@ -1450,35 +1464,35 @@ const byte *findResourceSmall(uint32 tag, const byte *searchin) {
uint16 newTag2Old(uint32 newTag) {
switch (newTag) {
- case (MKID_BE('RMHD')):
+ case (MKTAG('R','M','H','D')):
return (0x4448); // HD
- case (MKID_BE('IM00')):
+ case (MKTAG('I','M','0','0')):
return (0x4D42); // BM
- case (MKID_BE('EXCD')):
+ case (MKTAG('E','X','C','D')):
return (0x5845); // EX
- case (MKID_BE('ENCD')):
+ case (MKTAG('E','N','C','D')):
return (0x4E45); // EN
- case (MKID_BE('SCAL')):
+ case (MKTAG('S','C','A','L')):
return (0x4153); // SA
- case (MKID_BE('LSCR')):
+ case (MKTAG('L','S','C','R')):
return (0x534C); // LS
- case (MKID_BE('OBCD')):
+ case (MKTAG('O','B','C','D')):
return (0x434F); // OC
- case (MKID_BE('OBIM')):
+ case (MKTAG('O','B','I','M')):
return (0x494F); // OI
- case (MKID_BE('SMAP')):
+ case (MKTAG('S','M','A','P')):
return (0x4D42); // BM
- case (MKID_BE('CLUT')):
+ case (MKTAG('C','L','U','T')):
return (0x4150); // PA
- case (MKID_BE('BOXD')):
+ case (MKTAG('B','O','X','D')):
return (0x5842); // BX
- case (MKID_BE('CYCL')):
+ case (MKTAG('C','Y','C','L')):
return (0x4343); // CC
- case (MKID_BE('EPAL')):
+ case (MKTAG('E','P','A','L')):
return (0x5053); // SP
- case (MKID_BE('TILE')):
+ case (MKTAG('T','I','L','E')):
return (0x4C54); // TL
- case (MKID_BE('ZP00')):
+ case (MKTAG('Z','P','0','0')):
return (0x505A); // ZP
default:
return (0);
diff --git a/engines/scumm/resource_v3.cpp b/engines/scumm/resource_v3.cpp
index 0728395055..5f23720ce9 100644
--- a/engines/scumm/resource_v3.cpp
+++ b/engines/scumm/resource_v3.cpp
@@ -32,7 +32,7 @@ namespace Scumm {
extern const char *resTypeFromId(int id);
-void ScummEngine_v3old::readResTypeList(int id) {
+int ScummEngine_v3old::readResTypeList(int id) {
int num;
int i;
@@ -57,6 +57,8 @@ void ScummEngine_v3old::readResTypeList(int id) {
if (_res->roomoffs[id][i] == 0xFFFF)
_res->roomoffs[id][i] = (uint32)RES_INVALID_OFFSET;
}
+
+ return num;
}
void ScummEngine_v3old::readIndexFile() {
diff --git a/engines/scumm/resource_v4.cpp b/engines/scumm/resource_v4.cpp
index 808fcbd73e..b1d98494d4 100644
--- a/engines/scumm/resource_v4.cpp
+++ b/engines/scumm/resource_v4.cpp
@@ -33,7 +33,7 @@ namespace Scumm {
extern const char *resTypeFromId(int id);
-void ScummEngine_v4::readResTypeList(int id) {
+int ScummEngine_v4::readResTypeList(int id) {
int num;
int i;
@@ -49,6 +49,8 @@ void ScummEngine_v4::readResTypeList(int id) {
_res->roomno[id][i] = _fileHandle->readByte();
_res->roomoffs[id][i] = _fileHandle->readUint32LE();
}
+
+ return num;
}
void ScummEngine_v4::readIndexFile() {
diff --git a/engines/scumm/room.cpp b/engines/scumm/room.cpp
index 02b2482e40..06fa0f2c39 100644
--- a/engines/scumm/room.cpp
+++ b/engines/scumm/room.cpp
@@ -264,7 +264,7 @@ void ScummEngine::setupRoomSubBlocks() {
//
// Determine the room dimensions (width/height)
//
- rmhd = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr);
+ rmhd = (const RoomHeader *)findResourceData(MKTAG('R','M','H','D'), roomptr);
if (_game.version == 8) {
_roomWidth = READ_LE_UINT32(&(rmhd->v8.width));
@@ -286,18 +286,18 @@ void ScummEngine::setupRoomSubBlocks() {
if (_game.version == 8) {
_IM00_offs = getObjectImage(roomptr, 1) - roomptr;
} else if (_game.features & GF_SMALL_HEADER) {
- _IM00_offs = findResourceData(MKID_BE('IM00'), roomptr) - roomptr;
+ _IM00_offs = findResourceData(MKTAG('I','M','0','0'), roomptr) - roomptr;
} else if (_game.heversion >= 70) {
byte *roomImagePtr = getResourceAddress(rtRoomImage, _roomResource);
- _IM00_offs = findResource(MKID_BE('IM00'), roomImagePtr) - roomImagePtr;
+ _IM00_offs = findResource(MKTAG('I','M','0','0'), roomImagePtr) - roomImagePtr;
} else {
- _IM00_offs = findResource(MKID_BE('IM00'), findResource(MKID_BE('RMIM'), roomptr)) - roomptr;
+ _IM00_offs = findResource(MKTAG('I','M','0','0'), findResource(MKTAG('R','M','I','M'), roomptr)) - roomptr;
}
//
// Look for an exit script
//
- ptr = findResourceData(MKID_BE('EXCD'), roomResPtr);
+ ptr = findResourceData(MKTAG('E','X','C','D'), roomResPtr);
if (ptr)
_EXCD_offs = ptr - roomResPtr;
if (_dumpScripts && _EXCD_offs)
@@ -306,7 +306,7 @@ void ScummEngine::setupRoomSubBlocks() {
//
// Look for an entry script
//
- ptr = findResourceData(MKID_BE('ENCD'), roomResPtr);
+ ptr = findResourceData(MKTAG('E','N','C','D'), roomResPtr);
if (ptr)
_ENCD_offs = ptr - roomResPtr;
if (_dumpScripts && _ENCD_offs)
@@ -326,7 +326,7 @@ void ScummEngine::setupRoomSubBlocks() {
if (_game.features & GF_SMALL_HEADER) {
ResourceIterator localScriptIterator(searchptr, true);
- while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
+ while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
id = ptr[0];
@@ -341,7 +341,7 @@ void ScummEngine::setupRoomSubBlocks() {
}
} else if (_game.heversion >= 90) {
ResourceIterator localScriptIterator2(searchptr, false);
- while ((ptr = localScriptIterator2.findNext(MKID_BE('LSC2'))) != NULL) {
+ while ((ptr = localScriptIterator2.findNext(MKTAG('L','S','C','2'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -359,7 +359,7 @@ void ScummEngine::setupRoomSubBlocks() {
}
ResourceIterator localScriptIterator(searchptr, false);
- while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
+ while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -376,7 +376,7 @@ void ScummEngine::setupRoomSubBlocks() {
} else {
ResourceIterator localScriptIterator(searchptr, false);
- while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
+ while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -403,18 +403,18 @@ void ScummEngine::setupRoomSubBlocks() {
}
// Locate the EGA palette (currently unused).
- ptr = findResourceData(MKID_BE('EPAL'), roomptr);
+ ptr = findResourceData(MKTAG('E','P','A','L'), roomptr);
if (ptr)
_EPAL_offs = ptr - roomptr;
// Locate the standard room palette (for V3-V5 games).
- ptr = findResourceData(MKID_BE('CLUT'), roomptr);
+ ptr = findResourceData(MKTAG('C','L','U','T'), roomptr);
if (ptr)
_CLUT_offs = ptr - roomptr;
// Locate the standard room palettes (for V6+ games).
if (_game.version >= 6) {
- ptr = findResource(MKID_BE('PALS'), roomptr);
+ ptr = findResource(MKTAG('P','A','L','S'), roomptr);
if (ptr) {
_PALS_offs = ptr - roomptr;
}
@@ -425,7 +425,7 @@ void ScummEngine::setupRoomSubBlocks() {
if (_game.version == 8)
trans = (byte)READ_LE_UINT32(&(rmhd->v8.transparency));
else {
- ptr = findResourceData(MKID_BE('TRNS'), roomptr);
+ ptr = findResourceData(MKTAG('T','R','N','S'), roomptr);
if (ptr)
trans = ptr[0];
else
@@ -434,7 +434,7 @@ void ScummEngine::setupRoomSubBlocks() {
// Actor Palette in HE 70 games
if (_game.heversion == 70) {
- ptr = findResourceData(MKID_BE('REMP'), roomptr);
+ ptr = findResourceData(MKTAG('R','E','M','P'), roomptr);
if (ptr) {
for (i = 0; i < 256; i++)
_HEV7ActorPalette[i] = *ptr++;
@@ -485,7 +485,7 @@ void ScummEngine::resetRoomSubBlocks() {
_res->nukeResource(rtMatrix, 1);
_res->nukeResource(rtMatrix, 2);
if (_game.features & GF_SMALL_HEADER) {
- ptr = findResourceData(MKID_BE('BOXD'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','D'), roomptr);
if (ptr) {
byte numOfBoxes = *ptr;
int size;
@@ -506,21 +506,21 @@ void ScummEngine::resetRoomSubBlocks() {
}
} else {
- ptr = findResourceData(MKID_BE('BOXD'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','D'), roomptr);
if (ptr) {
int size = getResourceDataSize(ptr);
_res->createResource(rtMatrix, 2, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
- ptr = findResourceData(MKID_BE('BOXD'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','D'), roomptr);
memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
}
- ptr = findResourceData(MKID_BE('BOXM'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','M'), roomptr);
if (ptr) {
int size = getResourceDataSize(ptr);
_res->createResource(rtMatrix, 1, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
- ptr = findResourceData(MKID_BE('BOXM'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','M'), roomptr);
memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
}
}
@@ -531,7 +531,7 @@ void ScummEngine::resetRoomSubBlocks() {
for (i = 1; i < _res->num[rtScaleTable]; i++)
_res->nukeResource(rtScaleTable, i);
- ptr = findResourceData(MKID_BE('SCAL'), roomptr);
+ ptr = findResourceData(MKTAG('S','C','A','L'), roomptr);
if (ptr) {
int s1, s2, y1, y2;
if (_game.version == 8) {
@@ -558,7 +558,7 @@ void ScummEngine::resetRoomSubBlocks() {
// Color cycling
// HE 7.0 games load resources but don't use them.
if (_game.version >= 4 && _game.heversion <= 62) {
- ptr = findResourceData(MKID_BE('CYCL'), roomptr);
+ ptr = findResourceData(MKTAG('C','Y','C','L'), roomptr);
if (ptr) {
initCycl(ptr);
}
@@ -567,7 +567,7 @@ void ScummEngine::resetRoomSubBlocks() {
#ifdef ENABLE_HE
// Polygons in HE 80+ games
if (_game.heversion >= 80) {
- ptr = findResourceData(MKID_BE('POLD'), roomptr);
+ ptr = findResourceData(MKTAG('P','O','L','D'), roomptr);
if (ptr) {
((ScummEngine_v71he *)this)->_wiz->polygonLoad(ptr);
}
@@ -581,7 +581,7 @@ void ScummEngine::resetRoomSubBlocks() {
void ScummEngine_v3old::setupRoomSubBlocks() {
const byte *ptr;
- byte *roomptr, *searchptr = 0;
+ byte *roomptr;
const RoomHeader *rmhd;
_ENCD_offs = 0;
@@ -669,7 +669,6 @@ void ScummEngine_v3old::setupRoomSubBlocks() {
// Determine the room script base address
roomptr = getResourceAddress(rtRoom, _roomResource);
- searchptr = roomptr;
memset(_localScriptOffsets, 0, sizeof(_localScriptOffsets));
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index bdae4c5f6a..3bfe51a77b 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -154,7 +154,7 @@ void ScummEngine::requestLoad(int slot) {
}
static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) {
- hdr.type = MKID_BE('SCVM');
+ hdr.type = MKTAG('S','C','V','M');
hdr.size = 0;
hdr.ver = CURRENT_VER;
@@ -308,7 +308,7 @@ static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &h
hdr.size = in->readUint32LE();
hdr.ver = in->readUint32LE();
in->read(hdr.name, sizeof(hdr.name));
- return !in->err() && hdr.type == MKID_BE('SCVM');
+ return !in->err() && hdr.type == MKTAG('S','C','V','M');
}
bool ScummEngine::loadState(int slot, bool compat) {
@@ -373,7 +373,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
// Since version 56 we save additional information about the creation of
// the save game and the save time.
if (hdr.ver >= VER(56)) {
- InfoStuff infos;
+ SaveStateMetaInfos infos;
if (!loadInfos(in, &infos)) {
warning("Info section could not be found");
delete in;
@@ -703,7 +703,7 @@ Graphics::Surface *ScummEngine::loadThumbnailFromSlot(const char *target, int sl
return thumb;
}
-bool ScummEngine::loadInfosFromSlot(const char *target, int slot, InfoStuff *stuff) {
+bool ScummEngine::loadInfosFromSlot(const char *target, int slot, SaveStateMetaInfos *stuff) {
Common::SeekableReadStream *in;
SaveGameHeader hdr;
@@ -741,12 +741,12 @@ bool ScummEngine::loadInfosFromSlot(const char *target, int slot, InfoStuff *stu
return true;
}
-bool ScummEngine::loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff) {
- memset(stuff, 0, sizeof(InfoStuff));
+bool ScummEngine::loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos *stuff) {
+ memset(stuff, 0, sizeof(SaveStateMetaInfos));
SaveInfoSection section;
section.type = file->readUint32BE();
- if (section.type != MKID_BE('INFO')) {
+ if (section.type != MKTAG('I','N','F','O')) {
return false;
}
@@ -793,7 +793,7 @@ bool ScummEngine::loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff)
void ScummEngine::saveInfos(Common::WriteStream* file) {
SaveInfoSection section;
- section.type = MKID_BE('INFO');
+ section.type = MKTAG('I','N','F','O');
section.version = INFOSECTION_VERSION;
section.size = SaveInfoSectionSize;
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index eac2061560..9e02f126cd 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -174,7 +174,7 @@ int ScummEngine::getVerbEntrypoint(int obj, int entry) {
else if (_game.features & GF_SMALL_HEADER)
verbptr = objptr + 19;
else
- verbptr = findResource(MKID_BE('VERB'), objptr);
+ verbptr = findResource(MKTAG('V','E','R','B'), objptr);
assert(verbptr);
@@ -261,8 +261,7 @@ void ScummEngine::stopScript(int script) {
/* Stop an object script 'script'*/
void ScummEngine::stopObjectScript(int script) {
ScriptSlot *ss;
- NestedScript *nest;
- int i, num;
+ int i;
if (script == 0)
return;
@@ -282,19 +281,14 @@ void ScummEngine::stopObjectScript(int script) {
}
}
- nest = vm.nest;
- num = vm.numNestedScripts;
-
- while (num > 0) {
- if (nest->number == script &&
- (nest->where == WIO_ROOM || nest->where == WIO_INVENTORY || nest->where == WIO_FLOBJECT)) {
- nukeArrays(nest->slot);
- nest->number = 0xFF;
- nest->slot = 0xFF;
- nest->where = 0xFF;
+ for (i = 0; i < vm.numNestedScripts; ++i) {
+ if (vm.nest[i].number == script &&
+ (vm.nest[i].where == WIO_ROOM || vm.nest[i].where == WIO_INVENTORY || vm.nest[i].where == WIO_FLOBJECT)) {
+ nukeArrays(vm.nest[i].slot);
+ vm.nest[i].number = 0xFF;
+ vm.nest[i].slot = 0xFF;
+ vm.nest[i].where = 0xFF;
}
- nest++;
- num--;
}
}
@@ -319,6 +313,9 @@ void ScummEngine::runScriptNested(int script) {
updateScriptPtr();
+ if (vm.numNestedScripts >= kMaxScriptNesting)
+ error("Too many nested scripts");
+
nest = &vm.nest[vm.numNestedScripts];
if (_currentScript == 0xFF) {
@@ -334,9 +331,6 @@ void ScummEngine::runScriptNested(int script) {
vm.numNestedScripts++;
- if (vm.numNestedScripts > ARRAYSIZE(vm.nest))
- error("Too many nested scripts");
-
_currentScript = script;
getScriptBaseAddress();
resetScriptPointer();
@@ -927,7 +921,7 @@ void ScummEngine::runExitScript() {
// be limiting ourselves to strictly reading the size from the header?
if (_game.id == GID_INDY3 && !(_game.features & GF_OLD_BUNDLE)) {
byte *roomptr = getResourceAddress(rtRoom, _roomResource);
- const byte *excd = findResourceData(MKID_BE('EXCD'), roomptr) - _resourceHeaderSize;
+ const byte *excd = findResourceData(MKTAG('E','X','C','D'), roomptr) - _resourceHeaderSize;
if (!excd || (getResourceDataSize(excd) < 1)) {
debug(2, "Exit-%d is empty", _roomResource);
return;
@@ -1283,7 +1277,8 @@ void ScummEngine::beginCutscene(int *args) {
int scr = _currentScript;
vm.slot[scr].cutsceneOverride++;
- if (++vm.cutSceneStackPointer > ARRAYSIZE(vm.cutSceneData))
+ ++vm.cutSceneStackPointer;
+ if (vm.cutSceneStackPointer >= kMaxCutsceneNum)
error("Cutscene stack overflow");
vm.cutSceneData[vm.cutSceneStackPointer] = args[0];
@@ -1313,6 +1308,9 @@ void ScummEngine::endCutscene() {
vm.cutSceneScript[vm.cutSceneStackPointer] = 0;
vm.cutScenePtr[vm.cutSceneStackPointer] = 0;
+
+ if (0 == vm.cutSceneStackPointer)
+ error("Cutscene stack underflow");
vm.cutSceneStackPointer--;
if (VAR(VAR_CUTSCENE_END_SCRIPT))
@@ -1321,7 +1319,7 @@ void ScummEngine::endCutscene() {
void ScummEngine::abortCutscene() {
const int idx = vm.cutSceneStackPointer;
- assert(0 <= idx && idx < 5);
+ assert(0 <= idx && idx < kMaxCutsceneNum);
uint32 offs = vm.cutScenePtr[idx];
if (offs) {
@@ -1340,7 +1338,7 @@ void ScummEngine::abortCutscene() {
void ScummEngine::beginOverride() {
const int idx = vm.cutSceneStackPointer;
- assert(0 <= idx && idx < 5);
+ assert(0 <= idx && idx < kMaxCutsceneNum);
vm.cutScenePtr[idx] = _scriptPointer - _scriptOrgPointer;
vm.cutSceneScript[idx] = _currentScript;
@@ -1357,7 +1355,7 @@ void ScummEngine::beginOverride() {
void ScummEngine::endOverride() {
const int idx = vm.cutSceneStackPointer;
- assert(0 <= idx && idx < 5);
+ assert(0 <= idx && idx < kMaxCutsceneNum);
vm.cutScenePtr[idx] = 0;
vm.cutSceneScript[idx] = 0;
diff --git a/engines/scumm/script.h b/engines/scumm/script.h
index dbfa2630e5..39d5d802b4 100644
--- a/engines/scumm/script.h
+++ b/engines/scumm/script.h
@@ -98,16 +98,29 @@ struct NestedScript {
uint8 slot;
};
+enum {
+ /**
+ * The maximal number of cutscenes that can be active
+ * in parallel (i.e. nested).
+ */
+ kMaxCutsceneNum = 5,
+
+ /**
+ * The maximal 'nesting' level for scripts.
+ */
+ kMaxScriptNesting = 15
+};
+
struct VirtualMachineState {
- uint32 cutScenePtr[5];
- byte cutSceneScript[5];
- int16 cutSceneData[5];
+ uint32 cutScenePtr[kMaxCutsceneNum];
+ byte cutSceneScript[kMaxCutsceneNum];
+ int16 cutSceneData[kMaxCutsceneNum];
int16 cutSceneScriptIndex;
byte cutSceneStackPointer;
ScriptSlot slot[NUM_SCRIPT_SLOT];
int32 localvar[NUM_SCRIPT_SLOT][26];
- NestedScript nest[15];
+ NestedScript nest[kMaxScriptNesting];
byte numNestedScripts;
};
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 9e245aa168..ee790f7876 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -530,11 +530,20 @@ void ScummEngine_v5::o5_actorOps() {
void ScummEngine_v5::o5_setClass() {
int obj = getVarOrDirectWord(PARAM_1);
- int newClass;
+ int cls;
while ((_opcode = fetchScriptByte()) != 0xFF) {
- newClass = getVarOrDirectWord(PARAM_1);
- if (newClass == 0) {
+ cls = getVarOrDirectWord(PARAM_1);
+
+ // WORKAROUND bug #1668393: Due to a script bug, the wrong opcode is
+ // used to test and set the state of various objects (e.g. the inside
+ // door (object 465) of the of the Hostel on Mars), when opening the
+ // Hostel door from the outside.
+ if (_game.id == GID_ZAK && _game.platform == Common::kPlatformFMTowns &&
+ vm.slot[_currentScript].number == 205 && _currentRoom == 185 &&
+ (cls == 0 || cls == 1)) {
+ putState(obj, cls);
+ } else if (cls == 0) {
// Class '0' means: clean all class data
_classData[obj] = 0;
if ((_game.features & GF_SMALL_HEADER) && obj <= _numActors) {
@@ -543,7 +552,7 @@ void ScummEngine_v5::o5_setClass() {
a->_forceClip = 0;
}
} else
- putClass(obj, newClass, (newClass & 0x80) ? true : false);
+ putClass(obj, cls, (cls & 0x80) ? true : false);
}
}
@@ -1148,9 +1157,10 @@ void ScummEngine_v5::o5_ifClassOfIs() {
while ((_opcode = fetchScriptByte()) != 0xFF) {
cls = getVarOrDirectWord(PARAM_1);
- // WORKAROUND bug #1668393: Due to a script bug, the wrong opcode is used
- // to check the state of the inside door (object 465) of the Hostel on Mars,
- // when opening the Hostel door from the outside.
+ // WORKAROUND bug #1668393: Due to a script bug, the wrong opcode is
+ // used to test and set the state of various objects (e.g. the inside
+ // door (object 465) of the of the Hostel on Mars), when opening the
+ // Hostel door from the outside.
if (_game.id == GID_ZAK && _game.platform == Common::kPlatformFMTowns &&
vm.slot[_currentScript].number == 205 && _currentRoom == 185 &&
obj == 465 && cls == 0) {
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index 30187937f3..b2df1d0baa 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -1228,11 +1228,11 @@ void ScummEngine_v6::o6_animateActor() {
}
void ScummEngine_v6::o6_doSentence() {
- int verb, objectA, objectB, dummy = 0;
+ int verb, objectA, objectB;
objectB = pop();
if (_game.version < 8)
- dummy = pop(); // dummy pop (in Sam&Max, seems to be always 0 or 130)
+ pop(); // dummy pop (in Sam&Max, seems to be always 0 or 130)
objectA = pop();
verb = pop();
@@ -3014,7 +3014,7 @@ void ScummEngine_v6::o6_setBoxSet() {
ResourceIterator boxds(room, false);
for (i = 0; i < arg; i++)
- boxd = boxds.findNext(MKID_BE('BOXD'));
+ boxd = boxds.findNext(MKTAG('B','O','X','D'));
if (!boxd)
error("ScummEngine_v6::o6_setBoxSet: Can't find dboxes for set %d", arg);
@@ -3027,7 +3027,7 @@ void ScummEngine_v6::o6_setBoxSet() {
ResourceIterator boxms(room, false);
for (i = 0; i < arg; i++)
- boxm = boxms.findNext(MKID_BE('BOXM'));
+ boxm = boxms.findNext(MKTAG('B','O','X','M'));
if (!boxm)
error("ScummEngine_v6::o6_setBoxSet: Can't find mboxes for set %d", arg);
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 83df53d8d0..5aea36ef66 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -201,8 +201,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_bootParam = 0;
_dumpScripts = false;
_debugMode = 0;
- _heV7DiskOffsets = NULL;
- _heV7RoomIntOffsets = NULL;
_objectOwnerTable = NULL;
_objectRoomTable = NULL;
_objectStateTable = NULL;
@@ -284,9 +282,9 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_16BitPalette = NULL;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_townsScreen = 0;
-#endif
_cjkFont = 0;
_cjkChar = 0;
+#endif
_shadowPalette = NULL;
_shadowPaletteSize = 0;
memset(_currentPalette, 0, sizeof(_currentPalette));
@@ -320,11 +318,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_V1TalkingActor = 0;
_NESStartStrip = 0;
- _actorClipOverride.top = 0;
- _actorClipOverride.bottom = 480;
- _actorClipOverride.left = 0;
- _actorClipOverride.right = 640;
-
_skipDrawObject = 0;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
@@ -637,8 +630,8 @@ ScummEngine::~ScummEngine() {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
delete _townsScreen;
-#endif
delete _cjkFont;
+#endif
delete _debugger;
@@ -767,6 +760,12 @@ ScummEngine_v60he::ScummEngine_v60he(OSystem *syst, const DetectorResult &dr)
: ScummEngine_v6(syst, dr) {
memset(_hInFileTable, 0, sizeof(_hInFileTable));
memset(_hOutFileTable, 0, sizeof(_hOutFileTable));
+
+ _actorClipOverride.top = 0;
+ _actorClipOverride.bottom = 480;
+ _actorClipOverride.left = 0;
+ _actorClipOverride.right = 640;
+
memset(_heTimers, 0, sizeof(_heTimers));
if (_game.heversion >= 61)
@@ -787,7 +786,9 @@ ScummEngine_v70he::ScummEngine_v70he(OSystem *syst, const DetectorResult &dr)
else
_resExtractor = new Win32ResExtractor(this);
+ _heV7DiskOffsets = NULL;
_heV7RoomOffsets = NULL;
+ _heV7RoomIntOffsets = NULL;
_heSndSoundId = 0;
_heSndOffset = 0;
@@ -804,8 +805,8 @@ ScummEngine_v70he::ScummEngine_v70he(OSystem *syst, const DetectorResult &dr)
ScummEngine_v70he::~ScummEngine_v70he() {
delete _resExtractor;
free(_heV7DiskOffsets);
- free(_heV7RoomIntOffsets);
free(_heV7RoomOffsets);
+ free(_heV7RoomIntOffsets);
free(_storedFlObjects);
}
@@ -1576,7 +1577,7 @@ void ScummEngine_v3::resetScumm() {
// Load tile set and palette for the distaff
byte *roomptr = getResourceAddress(rtRoom, 90);
assert(roomptr);
- const byte *palPtr = findResourceData(MKID_BE('CLUT'), roomptr);
+ const byte *palPtr = findResourceData(MKTAG('C','L','U','T'), roomptr);
assert(palPtr - 4);
setPCEPaletteFromPtr(palPtr);
_gdi->_distaff = true;
@@ -1858,27 +1859,25 @@ void ScummEngine::setupMusic(int midi) {
if (ConfMan.hasKey("tempo"))
_imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo"));
// YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS
- if (/*(midi != MDT_TOWNS) && (*/midi != MDT_NONE/*)*/) {
+ if (midi != MDT_NONE) {
_imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32);
if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized
_imuse->property(IMuse::PROP_GS, _enable_gs);
}
- if (_game.heversion >= 60 /*|| midi == MDT_TOWNS*/) {
+ if (_game.heversion >= 60) {
_imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1);
_imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1);
}
- /*if (midi == MDT_TOWNS)
- _imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1);*/
}
}
}
void ScummEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
// Sync the engine with the config manager
int soundVolumeMusic = ConfMan.getInt("music_volume");
int soundVolumeSfx = ConfMan.getInt("sfx_volume");
- int soundVolumeSpeech = ConfMan.getInt("speech_volume");
bool mute = false;
@@ -1886,7 +1885,7 @@ void ScummEngine::syncSoundSettings() {
mute = ConfMan.getBool("mute");
if (mute)
- soundVolumeMusic = soundVolumeSfx = soundVolumeSpeech = 0;
+ soundVolumeMusic = soundVolumeSfx = 0;
}
if (_musicEngine) {
@@ -1897,10 +1896,6 @@ void ScummEngine::syncSoundSettings() {
_townsPlayer->setSfxVolume(soundVolumeSfx);
}
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSfx);
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
-
if (ConfMan.getBool("speech_mute"))
_voiceMode = 2;
else
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 587d1be776..f3af84bb04 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -308,24 +308,7 @@ enum WhereIsObject {
WIO_FLOBJECT = 4
};
-struct AuxBlock {
- bool visible;
- Common::Rect r;
-
- void reset() {
- visible = false;
- r.left = r.top = 0;
- r.right = r.bottom = -1;
- }
-};
-
-struct AuxEntry {
- int actorNum;
- int subIndex;
-};
-
-// TODO: Rename InfoStuff to something more descriptive
-struct InfoStuff {
+struct SaveStateMetaInfos {
uint32 date;
uint16 time;
uint32 playtime;
@@ -630,7 +613,7 @@ public:
FilenamePattern _filenamePattern;
- Common::String generateFilename(const int room) const;
+ virtual Common::String generateFilename(const int room) const;
protected:
Common::KeyState _keyPressed;
@@ -694,11 +677,11 @@ public:
}
static Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot);
- static bool loadInfosFromSlot(const char *target, int slot, InfoStuff *stuff);
+ static bool loadInfosFromSlot(const char *target, int slot, SaveStateMetaInfos *stuff);
protected:
void saveInfos(Common::WriteStream* file);
- static bool loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff);
+ static bool loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos *stuff);
protected:
/* Script VM - should be in Script class */
@@ -790,8 +773,6 @@ public:
protected:
int _resourceHeaderSize;
byte _resourceMapper[128];
- byte *_heV7DiskOffsets;
- uint32 *_heV7RoomIntOffsets;
const byte *_resourceLastSearchBuf; // FIXME: need to put it to savefile?
uint32 _resourceLastSearchSize; // FIXME: need to put it to savefile?
@@ -804,11 +785,13 @@ protected:
bool openResourceFile(const Common::String &filename, byte encByte); // TODO: Use Common::String
void loadPtrToResource(int type, int i, const byte *ptr);
- virtual void readResTypeList(int id);
+ virtual int readResTypeList(int id);
// void allocResTypeData(int id, uint32 tag, int num, const char *name, int mode);
// byte *createResource(int type, int index, uint32 size);
int loadResource(int type, int i);
// void nukeResource(int type, int i);
+ int getResourceRoomNr(int type, int idx);
+ virtual uint32 getResourceRoomOffset(int type, int idx);
int getResourceSize(int type, int idx);
public:
@@ -816,7 +799,6 @@ public:
virtual byte *getStringAddress(int i);
byte *getStringAddressVar(int i);
void ensureResourceLoaded(int type, int i);
- int getResourceRoomNr(int type, int index);
protected:
int readSoundResource(int index);
@@ -972,8 +954,6 @@ public:
// Generic costume code
bool isCostumeInUse(int i) const;
- Common::Rect _actorClipOverride; // HE specific
-
protected:
/* Should be in Graphics class? */
uint16 _screenB, _screenH;
diff --git a/engines/scumm/scumm_v3.h b/engines/scumm/scumm_v3.h
index abe75cd64d..6e8d593a35 100644
--- a/engines/scumm/scumm_v3.h
+++ b/engines/scumm/scumm_v3.h
@@ -62,7 +62,7 @@ public:
ScummEngine_v3old(OSystem *syst, const DetectorResult &dr);
protected:
- virtual void readResTypeList(int id);
+ virtual int readResTypeList(int id);
virtual void readIndexFile();
virtual void setupRoomSubBlocks();
virtual void resetRoomSubBlocks();
diff --git a/engines/scumm/scumm_v4.h b/engines/scumm/scumm_v4.h
index be3f6cb47e..653cfc228e 100644
--- a/engines/scumm/scumm_v4.h
+++ b/engines/scumm/scumm_v4.h
@@ -59,7 +59,7 @@ protected:
virtual void scummLoop_handleSaveLoad();
- virtual void readResTypeList(int id);
+ virtual int readResTypeList(int id);
virtual void readIndexFile();
virtual void loadCharset(int no);
virtual void resetRoomObjects();
diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp
index a838fdba56..32fa99a870 100644
--- a/engines/scumm/smush/imuse_channel.cpp
+++ b/engines/scumm/smush/imuse_channel.cpp
@@ -29,6 +29,7 @@
#include "scumm/scumm.h" // For DEBUG_SMUSH
#include "scumm/util.h"
#include "scumm/smush/channel.h"
+#include "scumm/imuse_digi/dimuse_codecs.h" // for decode12BitsSample
namespace Scumm {
@@ -64,7 +65,7 @@ bool ImuseChannel::appendData(Common::SeekableReadStream &b, int32 size) {
assert(size > 8);
uint32 imus_type = b.readUint32BE();
/*uint32 imus_size =*/ b.readUint32BE();
- if (imus_type != MKID_BE('iMUS'))
+ if (imus_type != MKTAG('i','M','U','S'))
error("Invalid Chunk for imuse_channel");
size -= 8;
_tbufferSize = size;
@@ -115,7 +116,7 @@ bool ImuseChannel::handleMap(byte *data) {
size -= 8;
switch (subType) {
- case MKID_BE('FRMT'):
+ case MKTAG('F','R','M','T'):
if (subSize != 20)
error("invalid size for FRMT Chunk");
//uint32 imuse_start = READ_BE_UINT32(data);
@@ -125,14 +126,14 @@ bool ImuseChannel::handleMap(byte *data) {
_channels = READ_BE_UINT32(data+16);
assert(_channels == 1 || _channels == 2);
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
// Ignore this
break;
- case MKID_BE('REGN'):
+ case MKTAG('R','E','G','N'):
if (subSize != 8)
error("invalid size for REGN Chunk");
break;
- case MKID_BE('STOP'):
+ case MKTAG('S','T','O','P'):
if (subSize != 4)
error("invalid size for STOP Chunk");
break;
@@ -171,28 +172,10 @@ void ImuseChannel::decode() {
}
}
- // FIXME: Code duplication! See decode12BitsSample() in imuse_digi/dimuse_codecs.cpp
-
- int loop_size = _sbufferSize / 3;
- int new_size = loop_size * 4;
- byte *keep, *decoded;
- uint32 value;
- keep = decoded = (byte *)malloc(new_size);
- assert(keep);
- unsigned char * source = _sbuffer;
-
- while (loop_size--) {
- byte v1 = *source++;
- byte v2 = *source++;
- byte v3 = *source++;
- value = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000;
- WRITE_BE_UINT16(decoded, value); decoded += 2;
- value = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000;
- WRITE_BE_UINT16(decoded, value); decoded += 2;
- }
+ byte *keep;
+ _sbufferSize = BundleCodecs::decode12BitsSample(_sbuffer, &keep, _sbufferSize);
free(_sbuffer);
_sbuffer = (byte *)keep;
- _sbufferSize = new_size;
}
bool ImuseChannel::handleSubTags(int32 &offset) {
@@ -201,13 +184,13 @@ bool ImuseChannel::handleSubTags(int32 &offset) {
uint32 size = READ_BE_UINT32(_tbuffer + offset + 4);
uint32 available_size = _tbufferSize - offset;
switch (type) {
- case MKID_BE('MAP '):
+ case MKTAG('M','A','P',' '):
_inData = false;
if (available_size >= (size + 8)) {
handleMap((byte *)_tbuffer + offset);
}
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
_inData = true;
_dataSize = size;
offset += 8;
diff --git a/engines/scumm/smush/saud_channel.cpp b/engines/scumm/smush/saud_channel.cpp
index 94df70633f..04ed955224 100644
--- a/engines/scumm/smush/saud_channel.cpp
+++ b/engines/scumm/smush/saud_channel.cpp
@@ -50,7 +50,7 @@ bool SaudChannel::handleSubTags(int32 &offset) {
uint32 available_size = _tbufferSize - offset;
switch (type) {
- case MKID_BE('STRK'):
+ case MKTAG('S','T','R','K'):
_inData = false;
if (available_size >= (size + 8)) {
int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
@@ -60,14 +60,14 @@ bool SaudChannel::handleSubTags(int32 &offset) {
} else
return false;
break;
- case MKID_BE('SMRK'):
+ case MKTAG('S','M','R','K'):
_inData = false;
if (available_size >= (size + 8))
_markReached = true;
else
return false;
break;
- case MKID_BE('SHDR'):
+ case MKTAG('S','H','D','R'):
_inData = false;
if (available_size >= (size + 8)) {
int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
@@ -76,7 +76,7 @@ bool SaudChannel::handleSubTags(int32 &offset) {
} else
return false;
break;
- case MKID_BE('SDAT'):
+ case MKTAG('S','D','A','T'):
_inData = true;
_dataSize = size;
offset += 8;
@@ -123,7 +123,7 @@ bool SaudChannel::appendData(Common::SeekableReadStream &b, int32 size) {
assert(size > 8);
uint32 saud_type = b.readUint32BE();
/*uint32 saud_size =*/ b.readUint32BE();
- if (saud_type != MKID_BE('SAUD'))
+ if (saud_type != MKTAG('S','A','U','D'))
error("Invalid Chunk for SaudChannel : %X", saud_type);
size -= 8;
_dataSize = -2;
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index ad8a135a7c..0e4f588593 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -190,7 +190,7 @@ static StringResource *getStrings(ScummEngine *vm, const char *file, bool is_enc
theFile.read(filebuffer, length);
filebuffer[length] = 0;
- if (is_encoded && READ_BE_UINT32(filebuffer) == MKID_BE('ETRS')) {
+ if (is_encoded && READ_BE_UINT32(filebuffer) == MKTAG('E','T','R','S')) {
assert(length > ETRS_HEADER_LENGTH);
length -= ETRS_HEADER_LENGTH;
for (int i = 0; i < length; ++i) {
@@ -507,7 +507,7 @@ void SmushPlayer::handleTextResource(uint32 subType, int32 subSize, Common::Seek
const char *str;
char *string = NULL, *string2 = NULL;
- if (subType == MKID_BE('TEXT')) {
+ if (subType == MKTAG('T','E','X','T')) {
string = (char *)malloc(subSize - 16);
str = string;
b.read(string, subSize - 16);
@@ -845,40 +845,40 @@ void SmushPlayer::handleFrame(int32 frameSize, Common::SeekableReadStream &b) {
const int32 subSize = b.readUint32BE();
const int32 subOffset = b.pos();
switch (subType) {
- case MKID_BE('NPAL'):
+ case MKTAG('N','P','A','L'):
handleNewPalette(subSize, b);
break;
- case MKID_BE('FOBJ'):
+ case MKTAG('F','O','B','J'):
handleFrameObject(subSize, b);
break;
#ifdef USE_ZLIB
- case MKID_BE('ZFOB'):
+ case MKTAG('Z','F','O','B'):
handleZlibFrameObject(subSize, b);
break;
#endif
- case MKID_BE('PSAD'):
+ case MKTAG('P','S','A','D'):
if (!_compressedFileMode)
handleSoundFrame(subSize, b);
break;
- case MKID_BE('TRES'):
+ case MKTAG('T','R','E','S'):
handleTextResource(subType, subSize, b);
break;
- case MKID_BE('XPAL'):
+ case MKTAG('X','P','A','L'):
handleDeltaPalette(subSize, b);
break;
- case MKID_BE('IACT'):
+ case MKTAG('I','A','C','T'):
handleIACT(subSize, b);
break;
- case MKID_BE('STOR'):
+ case MKTAG('S','T','O','R'):
handleStore(subSize, b);
break;
- case MKID_BE('FTCH'):
+ case MKTAG('F','T','C','H'):
handleFetch(subSize, b);
break;
- case MKID_BE('SKIP'):
+ case MKTAG('S','K','I','P'):
_vm->_insane->procSKIP(subSize, b);
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
handleTextResource(subType, subSize, b);
break;
default:
@@ -990,7 +990,7 @@ void SmushPlayer::parseNextFrame() {
const uint32 subType = _base->readUint32BE();
const int32 subSize = _base->readUint32BE();
const int32 subOffset = _base->pos();
- assert(subType == MKID_BE('AHDR'));
+ assert(subType == MKTAG('A','H','D','R'));
handleAnimHeader(subSize, *_base);
_base->seek(subOffset + subSize, SEEK_SET);
@@ -1029,10 +1029,10 @@ void SmushPlayer::parseNextFrame() {
debug(3, "Chunk: %s at %x", tag2str(subType), subOffset);
switch (subType) {
- case MKID_BE('AHDR'): // FT INSANE may seek file to the beginning
+ case MKTAG('A','H','D','R'): // FT INSANE may seek file to the beginning
handleAnimHeader(subSize, *_base);
break;
- case MKID_BE('FRME'):
+ case MKTAG('F','R','M','E'):
handleFrame(subSize, *_base);
break;
default:
@@ -1217,19 +1217,7 @@ void SmushPlayer::play(const char *filename, int32 speed, int32 offset, int32 st
_vm->parseEvents();
_vm->processInput();
if (_palDirtyMax >= _palDirtyMin) {
- byte palette_colors[1024];
- byte *p = palette_colors;
-
- for (int i = _palDirtyMin; i <= _palDirtyMax; i++) {
- byte *data = _pal + i * 3;
-
- *p++ = data[0];
- *p++ = data[1];
- *p++ = data[2];
- *p++ = 0;
- }
-
- _vm->_system->getPaletteManager()->setPalette(palette_colors, _palDirtyMin, _palDirtyMax - _palDirtyMin + 1);
+ _vm->_system->getPaletteManager()->setPalette(_pal + _palDirtyMin * 3, _palDirtyMin, _palDirtyMax - _palDirtyMin + 1);
_palDirtyMax = -1;
_palDirtyMin = 256;
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index cff1618c18..54f35c1969 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -195,8 +195,7 @@ void Sound::playSound(int soundID) {
return;
}
- debugC(DEBUG_SOUND, "playSound #%d (room %d)", soundID,
- _vm->getResourceRoomNr(rtSound, soundID));
+ debugC(DEBUG_SOUND, "playSound #%d", soundID);
ptr = _vm->getResourceAddress(rtSound, soundID);
@@ -207,7 +206,7 @@ void Sound::playSound(int soundID) {
// Support for SFX in Monkey Island 1, Mac version
// This is rather hackish right now, but works OK. SFX are not sounding
// 100% correct, though, not sure right now what is causing this.
- else if (READ_BE_UINT32(ptr) == MKID_BE('Mac1')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('M','a','c','1')) {
// Read info from the header
size = READ_BE_UINT32(ptr+0x60);
rate = READ_BE_UINT16(ptr+0x64);
@@ -246,7 +245,7 @@ void Sound::playSound(int soundID) {
_mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID);
}
// Support for sampled sound effects in Monkey Island 1 and 2
- else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKID_BE('SBL ')) {
+ else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
debugC(DEBUG_SOUND, "Using SBL sound effect");
// SBL resources essentially contain VOC sound data.
@@ -317,7 +316,7 @@ void Sound::playSound(int soundID) {
stream = Audio::makeRawStream(sound, size, rate, Audio::FLAG_UNSIGNED);
_mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID);
}
- else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKID_BE('SOUN')) {
+ else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','O','U','N')) {
if (_vm->_game.version != 3)
ptr += 2;
@@ -416,7 +415,7 @@ void Sound::playSound(int soundID) {
// Rather it seems that starting a new music is supposed to
// automatically stop the old song.
if (_vm->_imuse) {
- if (READ_BE_UINT32(ptr) != MKID_BE('ASFX'))
+ if (READ_BE_UINT32(ptr) != MKTAG('A','S','F','X'))
_vm->_imuse->stopAllSounds();
}
}
@@ -1091,15 +1090,15 @@ int ScummEngine::readSoundResource(int idx) {
debugC(DEBUG_RESOURCE, " basetag: %s, total_size=%d", tag2str(basetag), total_size);
switch (basetag) {
- case MKID_BE('MIDI'):
- case MKID_BE('iMUS'):
+ case MKTAG('M','I','D','I'):
+ case MKTAG('i','M','U','S'):
if (_musicType != MDT_PCSPK && _musicType != MDT_PCJR) {
_fileHandle->seek(-8, SEEK_CUR);
_fileHandle->read(_res->createResource(rtSound, idx, total_size + 8), total_size + 8);
return 1;
}
break;
- case MKID_BE('SOU '):
+ case MKTAG('S','O','U',' '):
best_pri = -1;
while (pos < total_size) {
tag = _fileHandle->readUint32BE();
@@ -1109,32 +1108,32 @@ int ScummEngine::readSoundResource(int idx) {
pri = -1;
switch (tag) {
- case MKID_BE('TOWS'):
+ case MKTAG('T','O','W','S'):
pri = 16;
break;
- case MKID_BE('SBL '):
+ case MKTAG('S','B','L',' '):
pri = 15;
break;
- case MKID_BE('ADL '):
+ case MKTAG('A','D','L',' '):
pri = 1;
if (_musicType == MDT_ADLIB)
pri = 10;
break;
- case MKID_BE('AMI '):
+ case MKTAG('A','M','I',' '):
pri = 3;
break;
- case MKID_BE('ROL '):
+ case MKTAG('R','O','L',' '):
pri = 3;
if (_native_mt32)
pri = 5;
break;
- case MKID_BE('GMD '):
+ case MKTAG('G','M','D',' '):
pri = 4;
break;
- case MKID_BE('MAC '): // Occurs in Mac MI2, FOA
+ case MKTAG('M','A','C',' '): // Occurs in Mac MI2, FOA
pri = 2;
break;
- case MKID_BE('SPK '):
+ case MKTAG('S','P','K',' '):
pri = -1;
// if (_musicType == MDT_PCSPK || _musicType == MDT_PCJR)
// pri = 11;
@@ -1164,7 +1163,7 @@ int ScummEngine::readSoundResource(int idx) {
return 1;
}
break;
- case MKID_BE('Mac0'):
+ case MKTAG('M','a','c','0'):
_fileHandle->seek(-12, SEEK_CUR);
total_size = _fileHandle->readUint32BE() - 8;
ptr = (byte *)calloc(total_size, 1);
@@ -1174,11 +1173,11 @@ int ScummEngine::readSoundResource(int idx) {
free(ptr);
return 1;
- case MKID_BE('Mac1'):
- case MKID_BE('RIFF'):
- case MKID_BE('TALK'):
- case MKID_BE('DIGI'):
- case MKID_BE('Crea'):
+ case MKTAG('M','a','c','1'):
+ case MKTAG('R','I','F','F'):
+ case MKTAG('T','A','L','K'):
+ case MKTAG('D','I','G','I'):
+ case MKTAG('C','r','e','a'):
case 0x460e200d: // WORKAROUND bug # 1311447
_fileHandle->seek(-12, SEEK_CUR);
total_size = _fileHandle->readUint32BE();
@@ -1187,7 +1186,7 @@ int ScummEngine::readSoundResource(int idx) {
//dumpResource("sound-", idx, ptr);
return 1;
- case MKID_BE('HSHD'):
+ case MKTAG('H','S','H','D'):
// HE sound type without SOUN header
_fileHandle->seek(-16, SEEK_CUR);
total_size = max_total_size + 8;
@@ -1196,7 +1195,7 @@ int ScummEngine::readSoundResource(int idx) {
//dumpResource("sound-", idx, ptr);
return 1;
- case MKID_BE('FMUS'): {
+ case MKTAG('F','M','U','S'): {
// Used in 3DO version of puttputt joins the parade and probably others
// Specifies a separate file to be used for music from what I gather.
int tmpsize;
@@ -1223,7 +1222,7 @@ int ScummEngine::readSoundResource(int idx) {
if (!dmuFile.open(buffer)) {
error("Can't open music file %s", buffer);
- _res->roomoffs[rtSound][idx] = (uint32)RES_INVALID_OFFSET;
+ _res->roomoffs[rtSound][idx] = RES_INVALID_OFFSET;
return 0;
}
dmuFile.seek(4, SEEK_SET);
@@ -1247,7 +1246,7 @@ int ScummEngine::readSoundResource(int idx) {
}
error("Unrecognized base tag 0x%08x in sound %d", basetag, idx);
}
- _res->roomoffs[rtSound][idx] = (uint32)RES_INVALID_OFFSET;
+ _res->roomoffs[rtSound][idx] = RES_INVALID_OFFSET;
return 0;
}
@@ -1407,20 +1406,20 @@ static byte *writeVLQ(byte *ptr, int value) {
static byte Mac0ToGMInstrument(uint32 type, int &transpose) {
transpose = 0;
switch (type) {
- case MKID_BE('MARI'): return 12;
- case MKID_BE('PLUC'): return 45;
- case MKID_BE('HARM'): return 22;
- case MKID_BE('PIPE'): return 19;
- case MKID_BE('TROM'): transpose = -12; return 57;
- case MKID_BE('STRI'): return 48;
- case MKID_BE('HORN'): return 60;
- case MKID_BE('VIBE'): return 11;
- case MKID_BE('SHAK'): return 77;
- case MKID_BE('PANP'): return 75;
- case MKID_BE('WHIS'): return 76;
- case MKID_BE('ORGA'): return 17;
- case MKID_BE('BONG'): return 115;
- case MKID_BE('BASS'): transpose = -24; return 35;
+ case MKTAG('M','A','R','I'): return 12;
+ case MKTAG('P','L','U','C'): return 45;
+ case MKTAG('H','A','R','M'): return 22;
+ case MKTAG('P','I','P','E'): return 19;
+ case MKTAG('T','R','O','M'): transpose = -12; return 57;
+ case MKTAG('S','T','R','I'): return 48;
+ case MKTAG('H','O','R','N'): return 60;
+ case MKTAG('V','I','B','E'): return 11;
+ case MKTAG('S','H','A','K'): return 77;
+ case MKTAG('P','A','N','P'): return 75;
+ case MKTAG('W','H','I','S'): return 76;
+ case MKTAG('O','R','G','A'): return 17;
+ case MKTAG('B','O','N','G'): return 115;
+ case MKTAG('B','A','S','S'): transpose = -24; return 35;
default:
error("Unknown Mac0 instrument %s found", tag2str(type));
}
@@ -1505,13 +1504,13 @@ static void convertMac0Resource(ResourceManager *res, int idx, byte *src_ptr, in
// Parse the three channels
for (i = 0; i < 3; i++) {
- assert(READ_BE_UINT32(src_ptr) == MKID_BE('Chan'));
+ assert(READ_BE_UINT32(src_ptr) == MKTAG('C','h','a','n'));
len = READ_BE_UINT32(src_ptr + 4);
track_len[i] = len - 24;
track_instr[i] = Mac0ToGMInstrument(READ_BE_UINT32(src_ptr + 8), track_transpose[i]);
track_data[i] = src_ptr + 12;
src_ptr += len;
- looped = (READ_BE_UINT32(src_ptr - 8) == MKID_BE('Loop'));
+ looped = (READ_BE_UINT32(src_ptr - 8) == MKTAG('L','o','o','p'));
// For each note event, we need up to 6 bytes for the
// Note On (3 VLQ, 3 event), and 6 bytes for the Note
@@ -2122,7 +2121,7 @@ int ScummEngine::readSoundResourceSmallHeader(int idx) {
_fileHandle->read(_res->createResource(rtSound, idx, ro_size - 4), ro_size - 4);
return 1;
}
- _res->roomoffs[rtSound][idx] = (uint32)RES_INVALID_OFFSET;
+ _res->roomoffs[rtSound][idx] = RES_INVALID_OFFSET;
return 0;
}
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index e8f75dd901..6d5eb3fad7 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -1499,7 +1499,7 @@ void ScummEngine::drawVerbBitmap(int verb, int x, int y) {
}
imptr = getObjectImage(obim, 1);
} else {
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
if (_game.version >= 7) {
imgw = READ_LE_UINT16(&imhd->v7.width) / 8;
imgh = READ_LE_UINT16(&imhd->v7.height) / 8;
diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp
index 7b59fa2726..55ba6039c3 100644
--- a/engines/sky/control.cpp
+++ b/engines/sky/control.cpp
@@ -115,7 +115,7 @@ void TextResource::flushForRedraw() {
}
void TextResource::drawToScreen(bool doMask) {
- doMask = true;
+ (void)doMask;
uint16 cnty, cntx, cpWidth, cpHeight;
if ((_oldX == _x) && (_oldY == _y) && (_spriteData))
return;
diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp
index b43ec917fe..2839665ff8 100644
--- a/engines/sky/debug.cpp
+++ b/engines/sky/debug.cpp
@@ -1071,11 +1071,11 @@ void Debug::logic(uint32 logic) {
void Debug::script(uint32 command, uint16 *scriptData) {
debug(6, "SCRIPT: %s", opcodes[command]);
if (command == 0 || command == 6)
- debug(6, " %s", scriptVars[READ_LE_UINT16(scriptData)/4]);
+ debug(6, " %s", scriptVars[(*scriptData)/4]);
else {
int i;
for (i = 0; i < opcode_par[command]; i++) {
- debug(6, " %d", READ_LE_UINT16(scriptData + i));
+ debug(6, " %d", *(scriptData + i));
}
}
debug(6, " "); // Print an empty line as separator
diff --git a/engines/sky/intro.cpp b/engines/sky/intro.cpp
index 129de9c129..cf1910c5b1 100644
--- a/engines/sky/intro.cpp
+++ b/engines/sky/intro.cpp
@@ -644,8 +644,10 @@ Intro::Intro(Disk *disk, Screen *screen, MusicBase *music, Sound *sound, Text *t
Intro::~Intro() {
if (_skyScreen->sequenceRunning())
_skyScreen->stopSequence();
+
free(_textBuf);
free(_saveBuf);
+ _mixer->stopID(SOUND_BG);
free(_bgBuf);
}
@@ -658,6 +660,7 @@ bool Intro::doIntro(bool floppyIntro) {
if (!escDelay(3000))
return false;
+
if (floppyIntro)
_skyMusic->startMusic(1);
@@ -817,6 +820,7 @@ bool Intro::floppyScrollFlirt() {
bool Intro::commandFlirt(uint16 *&data) {
_skyScreen->startSequence(*data++);
+
while ((*data != COMMANDEND) || _skyScreen->sequenceRunning()) {
while ((_skyScreen->seqFramesLeft() < *data)) {
data++;
@@ -844,11 +848,13 @@ bool Intro::commandFlirt(uint16 *&data) {
error("Unknown FLIRT command %X", command);
}
}
+
if (!escDelay(50)) {
_skyScreen->stopSequence();
return false;
}
}
+
data++; // move pointer over "COMMANDEND"
return true;
}
@@ -893,6 +899,7 @@ void Intro::restoreScreen() {
bool Intro::escDelay(uint32 msecs) {
Common::EventManager *eventMan = _system->getEventManager();
Common::Event event;
+
if (_relDelay == 0) // first call, init with system time
_relDelay = (int32)_system->getMillis();
@@ -911,11 +918,15 @@ bool Intro::escDelay(uint32 msecs) {
nDelay = _relDelay - _system->getMillis();
if (nDelay < 0)
nDelay = 0;
- else if (nDelay > 40)
- nDelay = 40;
+ else if (nDelay > 20)
+ nDelay = 20;
+
_system->delayMillis(nDelay);
+
+ _skyScreen->processSequence();
_system->updateScreen();
- } while (nDelay == 40);
+ } while (nDelay == 20);
+
return true;
}
diff --git a/engines/sky/music/gmmusic.cpp b/engines/sky/music/gmmusic.cpp
index 22964f3f56..8818c5b711 100644
--- a/engines/sky/music/gmmusic.cpp
+++ b/engines/sky/music/gmmusic.cpp
@@ -53,8 +53,8 @@ GmMusic::~GmMusic() {
stopMusic();
// Send All Sound Off and All Notes Off (for external synths)
for (int i = 0; i < 16; i++) {
- _midiDrv->send ((120 << 8) | 0xB0 | i);
- _midiDrv->send ((123 << 8) | 0xB0 | i);
+ _midiDrv->send((120 << 8) | 0xB0 | i);
+ _midiDrv->send((123 << 8) | 0xB0 | i);
}
_midiDrv->close();
delete _midiDrv;
diff --git a/engines/sky/music/musicbase.cpp b/engines/sky/music/musicbase.cpp
index 0d3cb65e1b..e1044a9505 100644
--- a/engines/sky/music/musicbase.cpp
+++ b/engines/sky/music/musicbase.cpp
@@ -44,7 +44,7 @@ MusicBase::~MusicBase() {
}
void MusicBase::loadSection(uint8 pSection) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
if (_currentMusic)
stopMusicInternal();
free(_musicData);
@@ -58,7 +58,6 @@ void MusicBase::loadSection(uint8 pSection) {
_numberOfChannels = _currentMusic = 0;
setupPointers();
startDriver();
- _mutex.unlock();
}
bool MusicBase::musicIsPlaying() {
@@ -69,9 +68,8 @@ bool MusicBase::musicIsPlaying() {
}
void MusicBase::stopMusic() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
stopMusicInternal();
- _mutex.unlock();
}
void MusicBase::stopMusicInternal() {
@@ -113,7 +111,7 @@ void MusicBase::loadNewMusic() {
}
void MusicBase::pollMusic() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
uint8 newTempo;
if (_onNextPoll.musicToProcess != _currentMusic)
loadNewMusic();
@@ -127,7 +125,6 @@ void MusicBase::pollMusic() {
updateTempo();
}
}
- _mutex.unlock();
_aktTime &= 0xFFFF;
}
diff --git a/engines/sky/screen.cpp b/engines/sky/screen.cpp
index 76b4b24f51..a77017de38 100644
--- a/engines/sky/screen.cpp
+++ b/engines/sky/screen.cpp
@@ -63,7 +63,7 @@ Screen::Screen(OSystem *pSystem, Disk *pDisk, SkyCompact *skyCompact) {
_skyCompact = skyCompact;
int i;
- uint8 tmpPal[1024];
+ uint8 tmpPal[VGA_COLOURS * 3];
_gameGrid = (uint8 *)malloc(GRID_X * GRID_Y * 2);
forceRefresh();
@@ -72,21 +72,20 @@ Screen::Screen(OSystem *pSystem, Disk *pDisk, SkyCompact *skyCompact) {
_scrollScreen = NULL;
//blank the first 240 colors of the palette
- memset(tmpPal, 0, GAME_COLOURS * 4);
+ memset(tmpPal, 0, GAME_COLOURS * 3);
//set the remaining colors
for (i = 0; i < (VGA_COLOURS-GAME_COLOURS); i++) {
- tmpPal[4 * GAME_COLOURS + i * 4] = (_top16Colours[i * 3] << 2) + (_top16Colours[i * 3] >> 4);
- tmpPal[4 * GAME_COLOURS + i * 4 + 1] = (_top16Colours[i * 3 + 1] << 2) + (_top16Colours[i * 3 + 1] >> 4);
- tmpPal[4 * GAME_COLOURS + i * 4 + 2] = (_top16Colours[i * 3 + 2] << 2) + (_top16Colours[i * 3 + 2] >> 4);
- tmpPal[4 * GAME_COLOURS + i * 4 + 3] = 0x00;
+ tmpPal[3 * GAME_COLOURS + i * 3 + 0] = (_top16Colours[i * 3 + 0] << 2) + (_top16Colours[i * 3 + 0] >> 4);
+ tmpPal[3 * GAME_COLOURS + i * 3 + 1] = (_top16Colours[i * 3 + 1] << 2) + (_top16Colours[i * 3 + 1] >> 4);
+ tmpPal[3 * GAME_COLOURS + i * 3 + 2] = (_top16Colours[i * 3 + 2] << 2) + (_top16Colours[i * 3 + 2] >> 4);
}
//set the palette
_system->getPaletteManager()->setPalette(tmpPal, 0, VGA_COLOURS);
_currentPalette = 0;
- _seqInfo.framesLeft = 0;
+ _seqInfo.nextFrame = _seqInfo.framesLeft = 0;
_seqInfo.seqData = _seqInfo.seqDataPos = NULL;
_seqInfo.running = false;
}
@@ -116,8 +115,8 @@ void Screen::setPalette(uint8 *pal) {
void Screen::setPaletteEndian(uint8 *pal) {
#ifdef SCUMM_BIG_ENDIAN
- uint8 endPalette[256 * 3];
- for (uint16 cnt = 0; cnt < 256 * 3; cnt++)
+ uint8 endPalette[VGA_COLOURS * 3];
+ for (uint16 cnt = 0; cnt < VGA_COLOURS * 3; cnt++)
endPalette[cnt] = pal[cnt ^ 1];
convertPalette(endPalette, _palette);
#else
@@ -128,12 +127,12 @@ void Screen::setPaletteEndian(uint8 *pal) {
}
void Screen::halvePalette() {
- uint8 halfPalette[1024];
+ uint8 halfPalette[VGA_COLOURS * 3];
+
for (uint8 cnt = 0; cnt < GAME_COLOURS; cnt++) {
- halfPalette[(cnt << 2) | 0] = _palette[(cnt << 2) | 0] >> 1;
- halfPalette[(cnt << 2) | 1] = _palette[(cnt << 2) | 1] >> 1;
- halfPalette[(cnt << 2) | 2] = _palette[(cnt << 2) | 2] >> 1;
- halfPalette[(cnt << 2) | 3] = 0;
+ halfPalette[cnt * 3 + 0] = _palette[cnt * 3 + 0] >> 1;
+ halfPalette[cnt * 3 + 1] = _palette[cnt * 3 + 1] >> 1;
+ halfPalette[cnt * 3 + 2] = _palette[cnt * 3 + 2] >> 1;
}
_system->getPaletteManager()->setPalette(halfPalette, 0, GAME_COLOURS);
}
@@ -165,14 +164,14 @@ void Screen::showScreen(uint8 *pScreen) {
_system->updateScreen();
}
-void Screen::convertPalette(uint8 *inPal, uint8* outPal) { //convert 3 byte 0..63 rgb to 4byte 0..255 rgbx
+//convert 3 byte 0..63 rgb to 3 byte 0..255 rgb
+void Screen::convertPalette(uint8 *inPal, uint8* outPal) {
int i;
for (i = 0; i < VGA_COLOURS; i++) {
- outPal[4 * i] = (inPal[3 * i] << 2) + (inPal[3 * i] >> 4);
- outPal[4 * i + 1] = (inPal[3 * i + 1] << 2) + (inPal[3 * i + 1] >> 4);
- outPal[4 * i + 2] = (inPal[3 * i + 2] << 2) + (inPal[3 * i + 2] >> 4);
- outPal[4 * i + 3] = 0x00;
+ outPal[3 * i + 0] = (inPal[3 * i + 0] << 2) + (inPal[3 * i + 0] >> 4);
+ outPal[3 * i + 1] = (inPal[3 * i + 1] << 2) + (inPal[3 * i + 1] >> 4);
+ outPal[3 * i + 2] = (inPal[3 * i + 2] << 2) + (inPal[3 * i + 2] >> 4);
}
}
@@ -248,7 +247,7 @@ void Screen::fnFadeDown(uint32 scroll) {
uint32 delayTime = _system->getMillis();
for (uint8 cnt = 0; cnt < 32; cnt++) {
delayTime += 20;
- palette_fadedown_helper((uint32 *)_palette, GAME_COLOURS);
+ palette_fadedown_helper(_palette, GAME_COLOURS);
_system->getPaletteManager()->setPalette(_palette, 0, GAME_COLOURS);
_system->updateScreen();
int32 waitTime = (int32)delayTime - _system->getMillis();
@@ -266,23 +265,24 @@ void Screen::fnFadeDown(uint32 scroll) {
}
}
-void Screen::palette_fadedown_helper(uint32 *pal, uint num) {
- byte *p = (byte *)pal;
-
+void Screen::palette_fadedown_helper(uint8 *pal, uint num) {
do {
- if (p[0] >= 8)
- p[0] -= 8;
+ if (pal[0] >= 8)
+ pal[0] -= 8;
else
- p[0] = 0;
- if (p[1] >= 8)
- p[1] -= 8;
+ pal[0] = 0;
+
+ if (pal[1] >= 8)
+ pal[1] -= 8;
else
- p[1] = 0;
- if (p[2] >= 8)
- p[2] -= 8;
+ pal[1] = 0;
+
+ if (pal[2] >= 8)
+ pal[2] -= 8;
else
- p[2] = 0;
- p += sizeof(uint32);
+ pal[2] = 0;
+
+ pal += 3;
} while (--num);
}
@@ -296,20 +296,23 @@ void Screen::paletteFadeUp(uint16 fileNr) {
}
void Screen::paletteFadeUp(uint8 *pal) {
- byte tmpPal[1024];
+ byte tmpPal[VGA_COLOURS * 3];
convertPalette(pal, tmpPal);
uint32 delayTime = _system->getMillis();
for (uint8 cnt = 1; cnt <= 32; cnt++) {
delayTime += 20;
+
for (uint8 colCnt = 0; colCnt < GAME_COLOURS; colCnt++) {
- _palette[(colCnt << 2) | 0] = (tmpPal[(colCnt << 2) | 0] * cnt) >> 5;
- _palette[(colCnt << 2) | 1] = (tmpPal[(colCnt << 2) | 1] * cnt) >> 5;
- _palette[(colCnt << 2) | 2] = (tmpPal[(colCnt << 2) | 2] * cnt) >> 5;
+ _palette[colCnt * 3 + 0] = (tmpPal[colCnt * 3 + 0] * cnt) >> 5;
+ _palette[colCnt * 3 + 1] = (tmpPal[colCnt * 3 + 1] * cnt) >> 5;
+ _palette[colCnt * 3 + 2] = (tmpPal[colCnt * 3 + 2] * cnt) >> 5;
}
+
_system->getPaletteManager()->setPalette(_palette, 0, GAME_COLOURS);
_system->updateScreen();
+
int32 waitTime = (int32)delayTime - _system->getMillis();
if (waitTime < 0)
waitTime = 0;
@@ -328,8 +331,8 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) {
if (palette == NULL)
error("Screen::fnFadeUp: can't fetch compact %X", palNum);
#ifdef SCUMM_BIG_ENDIAN
- byte tmpPal[256 * 3];
- for (uint16 cnt = 0; cnt < 256*3; cnt++)
+ byte tmpPal[VGA_COLOURS * 3];
+ for (uint16 cnt = 0; cnt < VGA_COLOURS * 3; cnt++)
tmpPal[cnt] = palette[cnt ^ 1];
paletteFadeUp(tmpPal);
#else
@@ -348,7 +351,7 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) {
scrOldPtr += GAME_SCREEN_WIDTH;
}
showScreen(_scrollScreen);
- waitForTimer();
+ waitForTick();
}
showScreen(_currentScreen);
} else if (scroll == 321) { // scroll right (going left)
@@ -364,7 +367,7 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) {
scrOldPtr += GAME_SCREEN_WIDTH;
}
showScreen(_scrollScreen);
- waitForTimer();
+ waitForTick();
}
showScreen(_currentScreen);
}
@@ -374,22 +377,39 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) {
}
}
-void Screen::waitForTimer() {
+void Screen::waitForTick() {
+ uint32 start = _system->getMillis();
+ uint32 end = start + 20 - (start % 20);
+ uint32 remain;
+
Common::EventManager *eventMan = _system->getEventManager();
- _gotTick = false;
- while (!_gotTick) {
- Common::Event event;
+ Common::Event event;
- _system->delayMillis(10);
+ while (true) {
while (eventMan->pollEvent(event))
;
+
+ start = _system->getMillis();
+
+ if (start >= end)
+ return;
+
+ remain = end - start;
+ if (remain < 10) {
+ _system->delayMillis(remain);
+ return;
+ }
+
+ _system->delayMillis(10);
}
}
void Screen::waitForSequence() {
Common::EventManager *eventMan = _system->getEventManager();
+ Common::Event event;
+
while (_seqInfo.running) {
- Common::Event event;
+ processSequence();
_system->delayMillis(20);
while (eventMan->pollEvent(event))
@@ -397,106 +417,106 @@ void Screen::waitForSequence() {
}
}
-void Screen::handleTimer() {
- _gotTick = true;
- if (_seqInfo.running)
- processSequence();
-}
-
void Screen::startSequence(uint16 fileNum) {
_seqInfo.seqData = _skyDisk->loadFile(fileNum);
+ _seqInfo.nextFrame = _system->getMillis() + 60;
_seqInfo.framesLeft = _seqInfo.seqData[0];
_seqInfo.seqDataPos = _seqInfo.seqData + 1;
- _seqInfo.delay = SEQ_DELAY;
_seqInfo.running = true;
_seqInfo.runningItem = false;
}
void Screen::startSequenceItem(uint16 itemNum) {
_seqInfo.seqData = (uint8 *)SkyEngine::fetchItem(itemNum);
+ _seqInfo.nextFrame = _system->getMillis() + 60;
_seqInfo.framesLeft = _seqInfo.seqData[0] - 1;
_seqInfo.seqDataPos = _seqInfo.seqData + 1;
- _seqInfo.delay = SEQ_DELAY;
_seqInfo.running = true;
_seqInfo.runningItem = true;
}
void Screen::stopSequence() {
_seqInfo.running = false;
- waitForTimer();
- waitForTimer();
- _seqInfo.framesLeft = 0;
+ waitForTick();
+ waitForTick();
+ _seqInfo.nextFrame = _seqInfo.framesLeft = 0;
free(_seqInfo.seqData);
_seqInfo.seqData = _seqInfo.seqDataPos = NULL;
}
void Screen::processSequence() {
- uint32 screenPos = 0;
+ if (!_seqInfo.running)
+ return;
+
+ if (_system->getMillis() < _seqInfo.nextFrame)
+ return;
+
+ _seqInfo.nextFrame += 60;
- _seqInfo.delay--;
- if (_seqInfo.delay == 0) {
- _seqInfo.delay = SEQ_DELAY;
- memset(_seqGrid, 0, 12 * 20);
+ memset(_seqGrid, 0, 12 * 20);
- uint8 nrToSkip, nrToDo, cnt;
+ uint32 screenPos = 0;
+
+ uint8 nrToSkip, nrToDo, cnt;
+ do {
do {
- do {
- nrToSkip = _seqInfo.seqDataPos[0];
- _seqInfo.seqDataPos++;
- screenPos += nrToSkip;
- } while (nrToSkip == 0xFF);
- do {
- nrToDo = _seqInfo.seqDataPos[0];
- _seqInfo.seqDataPos++;
+ nrToSkip = _seqInfo.seqDataPos[0];
+ _seqInfo.seqDataPos++;
+ screenPos += nrToSkip;
+ } while (nrToSkip == 0xFF);
- uint8 gridSta = (uint8)((screenPos / (GAME_SCREEN_WIDTH * 16))*20 + ((screenPos % GAME_SCREEN_WIDTH) >> 4));
- uint8 gridEnd = (uint8)(((screenPos+nrToDo) / (GAME_SCREEN_WIDTH * 16))*20 + (((screenPos+nrToDo) % GAME_SCREEN_WIDTH) >> 4));
- gridSta = MIN(gridSta, (uint8)(12 * 20 - 1));
- gridEnd = MIN(gridEnd, (uint8)(12 * 20 - 1));
- if (gridEnd >= gridSta)
- for (cnt = gridSta; cnt <= gridEnd; cnt++)
- _seqGrid[cnt] = 1;
- else {
- for (cnt = gridSta; cnt < (gridSta / 20 + 1) * 20; cnt++)
- _seqGrid[cnt] = 1;
- for (cnt = (gridEnd / 20) * 20; cnt <= gridEnd; cnt++)
- _seqGrid[cnt] = 1;
- }
+ do {
+ nrToDo = _seqInfo.seqDataPos[0];
+ _seqInfo.seqDataPos++;
+
+ uint8 gridSta = (uint8)((screenPos / (GAME_SCREEN_WIDTH * 16))*20 + ((screenPos % GAME_SCREEN_WIDTH) >> 4));
+ uint8 gridEnd = (uint8)(((screenPos+nrToDo) / (GAME_SCREEN_WIDTH * 16))*20 + (((screenPos+nrToDo) % GAME_SCREEN_WIDTH) >> 4));
+ gridSta = MIN(gridSta, (uint8)(12 * 20 - 1));
+ gridEnd = MIN(gridEnd, (uint8)(12 * 20 - 1));
+ if (gridEnd >= gridSta)
+ for (cnt = gridSta; cnt <= gridEnd; cnt++)
+ _seqGrid[cnt] = 1;
+ else {
+ for (cnt = gridSta; cnt < (gridSta / 20 + 1) * 20; cnt++)
+ _seqGrid[cnt] = 1;
+ for (cnt = (gridEnd / 20) * 20; cnt <= gridEnd; cnt++)
+ _seqGrid[cnt] = 1;
+ }
- for (cnt = 0; cnt < nrToDo; cnt++) {
- _currentScreen[screenPos] = _seqInfo.seqDataPos[0];
- _seqInfo.seqDataPos++;
- screenPos++;
- }
- } while (nrToDo == 0xFF);
- } while (screenPos < (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT));
- uint8 *gridPtr = _seqGrid; uint8 *scrPtr = _currentScreen; uint8 *rectPtr = NULL;
- uint8 rectWid = 0, rectX = 0, rectY = 0;
- for (uint8 cnty = 0; cnty < 12; cnty++) {
- for (uint8 cntx = 0; cntx < 20; cntx++) {
- if (*gridPtr) {
- if (!rectWid) {
- rectX = cntx;
- rectY = cnty;
- rectPtr = scrPtr;
- }
- rectWid++;
- } else if (rectWid) {
- _system->copyRectToScreen(rectPtr, GAME_SCREEN_WIDTH, rectX << 4, rectY << 4, rectWid << 4, 16);
- rectWid = 0;
- }
- scrPtr += 16;
- gridPtr++;
+ for (cnt = 0; cnt < nrToDo; cnt++) {
+ _currentScreen[screenPos] = _seqInfo.seqDataPos[0];
+ _seqInfo.seqDataPos++;
+ screenPos++;
}
- if (rectWid) {
+ } while (nrToDo == 0xFF);
+ } while (screenPos < (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT));
+ uint8 *gridPtr = _seqGrid; uint8 *scrPtr = _currentScreen; uint8 *rectPtr = NULL;
+ uint8 rectWid = 0, rectX = 0, rectY = 0;
+ for (uint8 cnty = 0; cnty < 12; cnty++) {
+ for (uint8 cntx = 0; cntx < 20; cntx++) {
+ if (*gridPtr) {
+ if (!rectWid) {
+ rectX = cntx;
+ rectY = cnty;
+ rectPtr = scrPtr;
+ }
+ rectWid++;
+ } else if (rectWid) {
_system->copyRectToScreen(rectPtr, GAME_SCREEN_WIDTH, rectX << 4, rectY << 4, rectWid << 4, 16);
rectWid = 0;
}
- scrPtr += 15 * GAME_SCREEN_WIDTH;
+ scrPtr += 16;
+ gridPtr++;
}
- _system->updateScreen();
- _seqInfo.framesLeft--;
+ if (rectWid) {
+ _system->copyRectToScreen(rectPtr, GAME_SCREEN_WIDTH, rectX << 4, rectY << 4, rectWid << 4, 16);
+ rectWid = 0;
+ }
+ scrPtr += 15 * GAME_SCREEN_WIDTH;
}
+ _system->updateScreen();
+ _seqInfo.framesLeft--;
+
if (_seqInfo.framesLeft == 0) {
_seqInfo.running = false;
if (!_seqInfo.runningItem)
diff --git a/engines/sky/screen.h b/engines/sky/screen.h
index e587958c7b..69a9a2fc8f 100644
--- a/engines/sky/screen.h
+++ b/engines/sky/screen.h
@@ -46,7 +46,6 @@ struct DataFileHeader;
#define SCROLL_JUMP 16
#define VGA_COLOURS 256
#define GAME_COLOURS 240
-#define SEQ_DELAY 3
#define FORE 1
#define BACK 0
@@ -75,6 +74,7 @@ public:
void startSequenceItem(uint16 itemNum);
void stopSequence();
bool sequenceRunning() { return _seqInfo.running; }
+ void processSequence();
void waitForSequence();
uint32 seqFramesLeft() { return _seqInfo.framesLeft; }
uint8 *giveCurrent() { return _currentScreen; }
@@ -100,21 +100,19 @@ private:
OSystem *_system;
Disk *_skyDisk;
SkyCompact *_skyCompact;
- static uint8 _top16Colours[16*3];
- uint8 _palette[1024];
+ static uint8 _top16Colours[16 * 3];
+ uint8 _palette[VGA_COLOURS * 3];
uint32 _currentPalette;
uint8 _seqGrid[20 * 12];
- bool volatile _gotTick;
- void waitForTimer();
- void processSequence();
+ void waitForTick();
uint8 *_gameGrid;
uint8 *_currentScreen;
uint8 *_scrollScreen;
struct {
+ uint32 nextFrame;
uint32 framesLeft;
- uint32 delay;
uint8 *seqData;
uint8 *seqDataPos;
volatile bool running;
@@ -123,7 +121,7 @@ private:
//- more regular screen.asm + layer.asm routines
void convertPalette(uint8 *inPal, uint8* outPal);
- void palette_fadedown_helper(uint32 *pal, uint num);
+ void palette_fadedown_helper(uint8 *pal, uint num);
//- sprite.asm routines
// fixme: get rid of these globals
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index 14d57465af..f3556c84b3 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -84,8 +84,6 @@ SkyEngine::SkyEngine(OSystem *syst)
}
SkyEngine::~SkyEngine() {
- _timer->removeTimerProc(&timerHandler);
-
delete _skyLogic;
delete _skySound;
delete _skyMusic;
@@ -102,6 +100,22 @@ SkyEngine::~SkyEngine() {
free(_itemList[i]);
}
+void SkyEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ if (ConfMan.getBool("sfx_mute"))
+ SkyEngine::_systemVars.systemFlags |= SF_FX_OFF;
+
+ if (ConfMan.getBool("music_mute"))
+ SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF;
+
+ _skyMusic->setVolume(mute ? 0: ConfMan.getInt("music_volume") >> 1);
+}
+
GUI::Debugger *SkyEngine::getDebugger() {
return _debugger;
}
@@ -207,6 +221,7 @@ Common::Error SkyEngine::go() {
}
_skyLogic->engine();
+ _skyScreen->processSequence();
_skyScreen->recreate();
_skyScreen->spriteEngine();
if (_debugger->showGrid()) {
@@ -243,16 +258,6 @@ Common::Error SkyEngine::go() {
Common::Error SkyEngine::init() {
initGraphics(320, 200, false);
- if (ConfMan.getBool("sfx_mute")) {
- SkyEngine::_systemVars.systemFlags |= SF_FX_OFF;
- }
- if (ConfMan.getBool("music_mute")) {
- SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF;
- }
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
-
_skyDisk = new Disk();
_skySound = new Sound(_mixer, _skyDisk, Audio::Mixer::kMaxChannelVolume);
@@ -300,9 +305,6 @@ Common::Error SkyEngine::init() {
_skyLogic = new Logic(_skyCompact, _skyScreen, _skyDisk, _skyText, _skyMusic, _skyMouse, _skySound);
_skyMouse->useLogicInstance(_skyLogic);
- // initialize timer *after* _skyScreen has been initialized.
- _timer->installTimerProc(&timerHandler, 1000000 / 50, this); //call 50 times per second
-
_skyControl = new Control(_saveFileMan, _skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _skySound, _skyCompact, _system);
_skyLogic->useControlInstance(_skyControl);
@@ -350,7 +352,8 @@ Common::Error SkyEngine::init() {
}
}
- _skyMusic->setVolume(ConfMan.getInt("music_volume") >> 1);
+ // Setup mixer
+ syncSoundSettings();
_debugger = new Debugger(_skyLogic, _skyMouse, _skyScreen, _skyCompact);
return Common::kNoError;
@@ -386,14 +389,6 @@ void *SkyEngine::fetchItem(uint32 num) {
return _itemList[num];
}
-void SkyEngine::timerHandler(void *refCon) {
- ((SkyEngine *)refCon)->gotTimerTick();
-}
-
-void SkyEngine::gotTimerTick() {
- _skyScreen->handleTimer();
-}
-
void SkyEngine::delay(int32 amount) {
Common::Event event;
diff --git a/engines/sky/sky.h b/engines/sky/sky.h
index 58c9d1de11..d8ced1e569 100644
--- a/engines/sky/sky.h
+++ b/engines/sky/sky.h
@@ -84,6 +84,8 @@ public:
SkyEngine(OSystem *syst);
virtual ~SkyEngine();
+ virtual void syncSoundSettings();
+
static bool isDemo();
static bool isCDVersion();
@@ -121,8 +123,6 @@ protected:
void initItemList();
void initVirgin();
- static void timerHandler(void *ptr);
- void gotTimerTick();
void loadFixedItems();
};
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index fa876b565f..60176be1a9 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -174,7 +174,7 @@ void MoviePlayer::play() {
// previous location would be momentarily drawn, before switching to
// the new one. Work around this by setting the palette to black.
- byte pal[4 * 256];
+ byte pal[3 * 256];
memset(pal, 0, sizeof(pal));
_system->getPaletteManager()->setPalette(pal, 0, 256);
}
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index c61d0b7c85..d4f6bfd1fe 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -248,13 +248,13 @@ void Control::askForCd() {
fontId = CZECH_SR_FONT;
_font = (uint8*)_resMan->openFetchRes(fontId);
uint8 *pal = (uint8*)_resMan->openFetchRes(SR_PALETTE);
- uint8 *palOut = (uint8*)malloc(256 * 4);
+ uint8 *palOut = (uint8*)malloc(256 * 3);
for (uint16 cnt = 1; cnt < 256; cnt++) {
- palOut[cnt * 4 + 0] = pal[cnt * 3 + 0] << 2;
- palOut[cnt * 4 + 1] = pal[cnt * 3 + 1] << 2;
- palOut[cnt * 4 + 2] = pal[cnt * 3 + 2] << 2;
+ palOut[cnt * 3 + 0] = pal[cnt * 3 + 0] << 2;
+ palOut[cnt * 3 + 1] = pal[cnt * 3 + 1] << 2;
+ palOut[cnt * 3 + 2] = pal[cnt * 3 + 2] << 2;
}
- palOut[0] = palOut[1] = palOut[2] = palOut[3] = 0;
+ palOut[0] = palOut[1] = palOut[2] = 0;
_resMan->resClose(SR_PALETTE);
_system->getPaletteManager()->setPalette(palOut, 0, 256);
free(palOut);
@@ -318,13 +318,13 @@ uint8 Control::runPanel() {
_redFont = (uint8*)_resMan->openFetchRes(redFontId);
uint8 *pal = (uint8*)_resMan->openFetchRes(SR_PALETTE);
- uint8 *palOut = (uint8*)malloc(256 * 4);
+ uint8 *palOut = (uint8*)malloc(256 * 3);
for (uint16 cnt = 1; cnt < 256; cnt++) {
- palOut[cnt * 4 + 0] = pal[cnt * 3 + 0] << 2;
- palOut[cnt * 4 + 1] = pal[cnt * 3 + 1] << 2;
- palOut[cnt * 4 + 2] = pal[cnt * 3 + 2] << 2;
+ palOut[cnt * 3 + 0] = pal[cnt * 3 + 0] << 2;
+ palOut[cnt * 3 + 1] = pal[cnt * 3 + 1] << 2;
+ palOut[cnt * 3 + 2] = pal[cnt * 3 + 2] << 2;
}
- palOut[0] = palOut[1] = palOut[2] = palOut[3] = 0;
+ palOut[0] = palOut[1] = palOut[2] = 0;
_resMan->resClose(SR_PALETTE);
_system->getPaletteManager()->setPalette(palOut, 0, 256);
free(palOut);
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index a6ccb09a04..2e5bfc7197 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -44,7 +44,7 @@ class Mouse;
class Music;
class Sound;
-#define SAVEGAME_HEADER MKID_BE('BS_1')
+#define SAVEGAME_HEADER MKTAG('B','S','_','1')
#define SAVEGAME_VERSION 2
#define MAX_BUTTONS 16
diff --git a/engines/sword1/mouse.cpp b/engines/sword1/mouse.cpp
index 751b27efc0..87e476e504 100644
--- a/engines/sword1/mouse.cpp
+++ b/engines/sword1/mouse.cpp
@@ -197,6 +197,7 @@ void Mouse::createPointer(uint32 ptrId, uint32 luggageId) {
free(_currentPtr);
_currentPtr = NULL;
}
+
if (ptrId) {
MousePtr *lugg = NULL;
MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId);
@@ -284,6 +285,7 @@ void Mouse::createPointer(uint32 ptrId, uint32 luggageId) {
void Mouse::setPointer(uint32 resId, uint32 rate) {
_currentPtrId = resId;
_frame = 0;
+ _activeFrame = -1;
createPointer(resId, _currentLuggageId);
@@ -298,15 +300,24 @@ void Mouse::setPointer(uint32 resId, uint32 rate) {
void Mouse::setLuggage(uint32 resId, uint32 rate) {
_currentLuggageId = resId;
_frame = 0;
+ _activeFrame = -1;
+
createPointer(_currentPtrId, resId);
}
void Mouse::animate() {
if ((Logic::_scriptVars[MOUSE_STATUS] == 1) || (_mouseOverride && _currentPtr)) {
_frame = (_frame + 1) % _currentPtr->numFrames;
+
+ if (_activeFrame == _frame)
+ return;
+
uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr);
ptrData += _frame * _currentPtr->sizeX * _currentPtr->sizeY;
+
CursorMan.replaceCursor(ptrData, _currentPtr->sizeX, _currentPtr->sizeY, _currentPtr->hotSpotX, _currentPtr->hotSpotY, 255);
+
+ _activeFrame = _frame;
}
}
diff --git a/engines/sword1/mouse.h b/engines/sword1/mouse.h
index 50b7431c48..1b4ca12183 100644
--- a/engines/sword1/mouse.h
+++ b/engines/sword1/mouse.h
@@ -99,8 +99,9 @@ private:
ObjectMan *_objMan;
Common::Point _mouse;
- uint32 _currentPtrId, _currentLuggageId, _frame;
+ uint32 _currentPtrId, _currentLuggageId;
MousePtr *_currentPtr;
+ int _frame, _activeFrame;
uint16 _numObjs;
uint16 _lastState, _state;
uint32 _getOff;
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 031ab74d9a..1906fcb7fd 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -144,19 +144,19 @@ void Screen::fnSetPalette(uint8 start, uint16 length, uint32 id, bool fadeUp) {
}
for (uint32 cnt = 0; cnt < length; cnt++) {
- _targetPalette[(start + cnt) * 4 + 0] = palData[cnt * 3 + 0] << 2;
- _targetPalette[(start + cnt) * 4 + 1] = palData[cnt * 3 + 1] << 2;
- _targetPalette[(start + cnt) * 4 + 2] = palData[cnt * 3 + 2] << 2;
+ _targetPalette[(start + cnt) * 3 + 0] = palData[cnt * 3 + 0] << 2;
+ _targetPalette[(start + cnt) * 3 + 1] = palData[cnt * 3 + 1] << 2;
+ _targetPalette[(start + cnt) * 3 + 2] = palData[cnt * 3 + 2] << 2;
}
_resMan->resClose(id);
_isBlack = false;
if (fadeUp) {
_fadingStep = 1;
_fadingDirection = FADE_UP;
- memset(_currentPalette, 0, 256 * 4);
+ memset(_currentPalette, 0, 256 * 3);
_system->getPaletteManager()->setPalette(_currentPalette, 0, 256);
} else
- _system->getPaletteManager()->setPalette(_targetPalette + 4 * start, start, length);
+ _system->getPaletteManager()->setPalette(_targetPalette + 3 * start, start, length);
}
void Screen::fullRefresh() {
@@ -899,7 +899,7 @@ uint8* Screen::psxShrinkedBackgroundToIndexed(uint8 *psxBackground, uint32 bakXr
uint8 *fullres_buffer = (uint8 *)malloc(bakXres * (yresInTiles + 1) * 32);
memset(fullres_buffer, 0, bakXres * (yresInTiles + 1) * 32);
- bool isCompressed = (READ_LE_UINT32(psxBackground) == MKID_BE('COMP'));
+ bool isCompressed = (READ_LE_UINT32(psxBackground) == MKTAG('C','O','M','P'));
totTiles -= xresInTiles;
psxBackground += 4; //We skip the id tag
@@ -1125,11 +1125,11 @@ void Screen::flushPsxCache() {
void Screen::fadePalette() {
if (_fadingStep == 16)
- memcpy(_currentPalette, _targetPalette, 256 * 4);
+ memcpy(_currentPalette, _targetPalette, 256 * 3);
else if ((_fadingStep == 1) && (_fadingDirection == FADE_DOWN)) {
- memset(_currentPalette, 0, 4 * 256);
+ memset(_currentPalette, 0, 3 * 256);
} else
- for (uint16 cnt = 0; cnt < 256 * 4; cnt++)
+ for (uint16 cnt = 0; cnt < 256 * 3; cnt++)
_currentPalette[cnt] = (_targetPalette[cnt] * _fadingStep) >> 4;
_fadingStep += _fadingDirection;
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index fc998c6f28..88326a730e 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -161,8 +161,8 @@ private:
static RoomDef _roomDefTable[TOTAL_ROOMS]; // from ROOMS.C (not const, see fnSetParallax)
- uint8 _targetPalette[256 * 4];
- uint8 _currentPalette[256 * 4]; // for fading
+ uint8 _targetPalette[256 * 3];
+ uint8 _currentPalette[256 * 3]; // for fading
uint8 _fadingStep;
int8 _fadingDirection; // 1 for fade up, -1 for fade down
bool _isBlack; // if the logic already faded down the palette, this is set to show the
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 537720401d..8768e62457 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -170,6 +170,8 @@ void SwordEngine::reinitialize() {
}
void SwordEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
uint musicVol = ConfMan.getInt("music_volume");
uint sfxVol = ConfMan.getInt("sfx_volume");
uint speechVol = ConfMan.getInt("speech_volume");
@@ -228,9 +230,6 @@ void SwordEngine::syncSoundSettings() {
_sound->setSpeechVol(speechVolL, speechVolR);
_sound->setSfxVol(sfxVolL, sfxVolR);
}
-
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume"));
}
void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 3c506c0dae..8d1a9836f4 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -110,7 +110,7 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
terminated = !playVideo();
- closeTextObject(_currentMovieText, NULL);
+ closeTextObject(_currentMovieText, NULL, 0);
if (terminated) {
_snd->stopHandle(*_bgSoundHandle);
@@ -165,7 +165,7 @@ void MoviePlayer::openTextObject(uint32 index) {
}
}
-void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
+void MoviePlayer::closeTextObject(uint32 index, byte *screen, uint16 pitch) {
if (index < _numMovieTexts) {
MovieText *text = &_movieTexts[index];
@@ -182,20 +182,21 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
int frameHeight = _decoder->getHeight();
int frameX = (_system->getWidth() - frameWidth) / 2;
int frameY = (_system->getHeight() - frameHeight) / 2;
+ byte black = findBlackPalIndex();
- byte *dst = screen + _textY * _system->getWidth();
+ byte *dst = screen + _textY * pitch;
for (int y = 0; y < text->_textSprite.h; y++) {
if (_textY + y < frameY || _textY + y >= frameY + frameHeight) {
- memset(dst + _textX, findBlackPalIndex(), text->_textSprite.w);
+ memset(dst + _textX, black, text->_textSprite.w);
} else {
if (frameX > _textX)
- memset(dst + _textX, findBlackPalIndex(), frameX - _textX);
+ memset(dst + _textX, black, frameX - _textX);
if (frameX + frameWidth < _textX + text->_textSprite.w)
- memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + text->_textSprite.w - (frameX + frameWidth));
+ memset(dst + frameX + frameWidth, black, _textX + text->_textSprite.w - (frameX + frameWidth));
}
- dst += _system->getWidth();
+ dst += pitch;
}
}
@@ -205,7 +206,7 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
}
}
-void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
+void MoviePlayer::drawTextObject(uint32 index, byte *screen, uint16 pitch) {
MovieText *text = &_movieTexts[index];
byte white = findWhitePalIndex();
@@ -217,14 +218,15 @@ void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
uint16 height = text->_textSprite.h;
// Resize text sprites for PSX version
+ byte *psxSpriteBuffer = 0;
if (Sword2Engine::isPsx()) {
height *= 2;
- byte *buffer = (byte *)malloc(width * height);
- Screen::resizePsxSprite(buffer, src, width, height);
- src = buffer;
+ psxSpriteBuffer = (byte *)malloc(width * height);
+ Screen::resizePsxSprite(psxSpriteBuffer, src, width, height);
+ src = psxSpriteBuffer;
}
- byte *dst = screen + _textY * RENDERWIDE + _textX;
+ byte *dst = screen + _textY * pitch + _textX;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
@@ -234,12 +236,16 @@ void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
dst[x] = white;
}
src += width;
- dst += RENDERWIDE;
+ dst += pitch;
}
+
+ // Free buffer used to resize psx sprite
+ if (Sword2Engine::isPsx())
+ free(psxSpriteBuffer);
}
}
-void MoviePlayer::performPostProcessing(byte *screen) {
+void MoviePlayer::performPostProcessing(byte *screen, uint16 pitch) {
MovieText *text;
int frame = _decoder->getCurFrame();
@@ -261,9 +267,9 @@ void MoviePlayer::performPostProcessing(byte *screen) {
_vm->_sound->playCompSpeech(text->_speechId, 16, 0);
}
if (frame < text->_endFrame) {
- drawTextObject(_currentMovieText, screen);
+ drawTextObject(_currentMovieText, screen, pitch);
} else {
- closeTextObject(_currentMovieText, screen);
+ closeTextObject(_currentMovieText, screen, pitch);
_currentMovieText++;
}
}
@@ -313,7 +319,7 @@ bool MoviePlayer::playVideo() {
}
Graphics::Surface *screen = _vm->_system->lockScreen();
- performPostProcessing((byte *)screen->pixels);
+ performPostProcessing((byte *)screen->pixels, screen->pitch);
_vm->_system->unlockScreen();
_vm->_system->updateScreen();
}
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index 550ac0fac4..afe7dfcc68 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -96,12 +96,12 @@ protected:
uint32 _leadOut;
int _leadOutFrame;
- void performPostProcessing(byte *screen);
+ void performPostProcessing(byte *screen, uint16 pitch);
bool playVideo();
void openTextObject(uint32 index);
- void closeTextObject(uint32 index, byte *screen);
- void drawTextObject(uint32 index, byte *screen);
+ void closeTextObject(uint32 index, byte *screen, uint16 pitch);
+ void drawTextObject(uint32 index, byte *screen, uint16 pitch);
byte findBlackPalIndex();
byte findWhitePalIndex();
diff --git a/engines/sword2/console.cpp b/engines/sword2/console.cpp
index 6f4665a34c..bca3cd6184 100644
--- a/engines/sword2/console.cpp
+++ b/engines/sword2/console.cpp
@@ -319,7 +319,7 @@ bool Debugger::Cmd_Starts(int argc, const char **argv) {
}
bool Debugger::Cmd_Start(int argc, const char **argv) {
- uint8 pal[4] = { 255, 255, 255, 0 };
+ uint8 pal[3] = { 255, 255, 255 };
if (argc != 2) {
DebugPrintf("Usage: %s number\n", argv[0]);
diff --git a/engines/sword2/function.cpp b/engines/sword2/function.cpp
index 5bc82b5f9e..5e570fbaad 100644
--- a/engines/sword2/function.cpp
+++ b/engines/sword2/function.cpp
@@ -1897,11 +1897,11 @@ int32 Logic::fnColour(int32 *params) {
#define GREEN 3
#define BLUE 4
-static const uint8 black[4] = { 0, 0, 0, 0 };
-static const uint8 white[4] = { 255, 255, 255, 0 };
-static const uint8 red[4] = { 255, 0, 0, 0 };
-static const uint8 green[4] = { 0, 255, 0, 0 };
-static const uint8 blue[4] = { 0, 0, 255, 0 };
+static const uint8 black[3] = { 0, 0, 0 };
+static const uint8 white[3] = { 255, 255, 255 };
+static const uint8 red[3] = { 255, 0, 0 };
+static const uint8 green[3] = { 0, 255, 0 };
+static const uint8 blue[3] = { 0, 0, 255 };
#endif
int32 Logic::fnFlash(int32 *params) {
@@ -2163,7 +2163,7 @@ int32 Logic::fnPlaySequence(int32 *params) {
// zero the entire palette in case we're about to fade up!
- byte pal[4 * 256];
+ byte pal[3 * 256];
memset(pal, 0, sizeof(pal));
_vm->_screen->setPalette(0, 256, pal, RDPAL_INSTANT);
diff --git a/engines/sword2/mouse.cpp b/engines/sword2/mouse.cpp
index 7998079944..c8e9387cb7 100644
--- a/engines/sword2/mouse.cpp
+++ b/engines/sword2/mouse.cpp
@@ -1410,8 +1410,8 @@ void Mouse::addHuman() {
// info
if (_vm->_debugger->_testingSnR) {
- uint8 black[4] = { 0, 0, 0, 0 };
- uint8 white[4] = { 255, 255, 255, 0 };
+ uint8 black[3] = { 0, 0, 0 };
+ uint8 white[3] = { 255, 255, 255 };
// Testing logic scripts by simulating instant Save & Restore
diff --git a/engines/sword2/palette.cpp b/engines/sword2/palette.cpp
index 2b9b5b7f49..b348fd6bb5 100644
--- a/engines/sword2/palette.cpp
+++ b/engines/sword2/palette.cpp
@@ -53,7 +53,8 @@ void Screen::startNewPalette() {
if (!Sword2Engine::isPsx())
memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(screenFile), PALTABLESIZE);
- setPalette(0, 256, _vm->fetchPalette(screenFile), RDPAL_FADE);
+ _vm->fetchPalette(screenFile, _palette);
+ setPalette(0, 256, _palette, RDPAL_FADE);
// Indicating that it's a screen palette
_lastPaletteRes = 0;
@@ -110,12 +111,17 @@ void Screen::setFullPalette(int32 palRes) {
// palettes have a bright colour 0 although it should come out
// as black in the game!
- pal[0] = 0;
- pal[1] = 0;
- pal[2] = 0;
- pal[3] = 0;
+ _palette[0] = 0;
+ _palette[1] = 0;
+ _palette[2] = 0;
- setPalette(0, 256, pal, RDPAL_INSTANT);
+ for (uint i = 4, j = 3; i < 4 * 256; i += 4, j += 3) {
+ _palette[j + 0] = pal[i + 0];
+ _palette[j + 1] = pal[i + 1];
+ _palette[j + 2] = pal[i + 2];
+ }
+
+ setPalette(0, 256, _palette, RDPAL_INSTANT);
_vm->_resman->closeResource(palRes);
} else {
if (_thisScreen.background_layer_id) {
@@ -126,7 +132,8 @@ void Screen::setFullPalette(int32 palRes) {
if (!Sword2Engine::isPsx())
memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(data), PALTABLESIZE);
- setPalette(0, 256, _vm->fetchPalette(data), RDPAL_INSTANT);
+ _vm->fetchPalette(data, _palette);
+ setPalette(0, 256, _palette, RDPAL_INSTANT);
_vm->_resman->closeResource(_thisScreen.background_layer_id);
} else
error("setFullPalette(0) called, but no current screen available");
@@ -162,7 +169,7 @@ uint8 Screen::quickMatch(uint8 r, uint8 g, uint8 b) {
void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, uint8 fadeNow) {
assert(noEntries > 0);
- memcpy(&_palette[4 * startEntry], colourTable, noEntries * 4);
+ memmove(&_palette[3 * startEntry], colourTable, noEntries * 3);
if (fadeNow == RDPAL_INSTANT) {
setSystemPalette(_palette, startEntry, noEntries);
@@ -232,7 +239,7 @@ void Screen::waitForFade() {
void Screen::fadeServer() {
static int32 previousTime = 0;
- byte fadePalette[256 * 4];
+ byte fadePalette[256 * 3];
byte *newPalette = fadePalette;
int32 currentTime;
int16 fadeMultiplier;
@@ -257,9 +264,9 @@ void Screen::fadeServer() {
} else {
fadeMultiplier = (int16)(((int32)(currentTime - _fadeStartTime) * 256) / _fadeTotalTime);
for (i = 0; i < 256; i++) {
- newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 2] = (_palette[i * 4 + 2] * fadeMultiplier) >> 8;
+ newPalette[i * 3 + 0] = (_palette[i * 3 + 0] * fadeMultiplier) >> 8;
+ newPalette[i * 3 + 1] = (_palette[i * 3 + 1] * fadeMultiplier) >> 8;
+ newPalette[i * 3 + 2] = (_palette[i * 3 + 2] * fadeMultiplier) >> 8;
}
}
} else {
@@ -269,9 +276,9 @@ void Screen::fadeServer() {
} else {
fadeMultiplier = (int16)(((int32)(_fadeTotalTime - (currentTime - _fadeStartTime)) * 256) / _fadeTotalTime);
for (i = 0; i < 256; i++) {
- newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 2] = (_palette[i * 4 + 2] * fadeMultiplier) >> 8;
+ newPalette[i * 3 + 0] = (_palette[i * 3 + 0] * fadeMultiplier) >> 8;
+ newPalette[i * 3 + 1] = (_palette[i * 3 + 1] * fadeMultiplier) >> 8;
+ newPalette[i * 3 + 2] = (_palette[i * 3 + 2] * fadeMultiplier) >> 8;
}
}
}
@@ -284,9 +291,9 @@ void Screen::setSystemPalette(const byte *colors, uint start, uint num) {
const byte *palette;
if (_dimPalette) {
- byte pal[256 * 4];
+ byte pal[256 * 3];
- for (uint i = start * 4; i < 4 * (start + num); i++)
+ for (uint i = start * 3; i < 3 * (start + num); i++)
pal[i] = colors[i] / 2;
palette = pal;
diff --git a/engines/sword2/protocol.cpp b/engines/sword2/protocol.cpp
index 6c47c07401..ef2c622287 100644
--- a/engines/sword2/protocol.cpp
+++ b/engines/sword2/protocol.cpp
@@ -40,7 +40,7 @@ namespace Sword2 {
* of the screen file.
*/
-byte *Sword2Engine::fetchPalette(byte *screenFile) {
+void Sword2Engine::fetchPalette(byte *screenFile, byte *palBuffer) {
byte *palette;
if (isPsx()) { // PSX version doesn't have a "MultiScreenHeader", instead there's a ScreenHeader and a tag
@@ -56,12 +56,15 @@ byte *Sword2Engine::fetchPalette(byte *screenFile) {
// palettes have a bright colour 0 it should come out as black in the
// game.
- palette[0] = 0;
- palette[1] = 0;
- palette[2] = 0;
- palette[3] = 0;
+ palBuffer[0] = 0;
+ palBuffer[1] = 0;
+ palBuffer[2] = 0;
- return palette;
+ for (uint i = 4, j = 3; i < 4 * 256; i += 4, j += 3) {
+ palBuffer[j + 0] = palette[i + 0];
+ palBuffer[j + 1] = palette[i + 1];
+ palBuffer[j + 2] = palette[i + 2];
+ }
}
/**
diff --git a/engines/sword2/render.cpp b/engines/sword2/render.cpp
index 99295be571..a71d503d95 100644
--- a/engines/sword2/render.cpp
+++ b/engines/sword2/render.cpp
@@ -194,21 +194,21 @@ void Screen::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16
}
if (!transparent) {
- uint32 r1 = _palette[c1 * 4 + 0];
- uint32 g1 = _palette[c1 * 4 + 1];
- uint32 b1 = _palette[c1 * 4 + 2];
+ uint32 r1 = _palette[c1 * 3 + 0];
+ uint32 g1 = _palette[c1 * 3 + 1];
+ uint32 b1 = _palette[c1 * 3 + 2];
- uint32 r2 = _palette[c2 * 4 + 0];
- uint32 g2 = _palette[c2 * 4 + 1];
- uint32 b2 = _palette[c2 * 4 + 2];
+ uint32 r2 = _palette[c2 * 3 + 0];
+ uint32 g2 = _palette[c2 * 3 + 1];
+ uint32 b2 = _palette[c2 * 3 + 2];
- uint32 r3 = _palette[c3 * 4 + 0];
- uint32 g3 = _palette[c3 * 4 + 1];
- uint32 b3 = _palette[c3 * 4 + 2];
+ uint32 r3 = _palette[c3 * 3 + 0];
+ uint32 g3 = _palette[c3 * 3 + 1];
+ uint32 b3 = _palette[c3 * 3 + 2];
- uint32 r4 = _palette[c4 * 4 + 0];
- uint32 g4 = _palette[c4 * 4 + 1];
- uint32 b4 = _palette[c4 * 4 + 2];
+ uint32 r4 = _palette[c4 * 3 + 0];
+ uint32 g4 = _palette[c4 * 3 + 1];
+ uint32 b4 = _palette[c4 * 3 + 2];
uint32 r5 = (r1 * xFrac + r2 * (dstWidth - xFrac)) / dstWidth;
uint32 g5 = (g1 * xFrac + g2 * (dstWidth - xFrac)) / dstWidth;
diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp
index 1e45c0fc1f..8c2db79297 100644
--- a/engines/sword2/screen.cpp
+++ b/engines/sword2/screen.cpp
@@ -355,8 +355,8 @@ void Screen::buildDisplay() {
*/
void Screen::displayMsg(byte *text, int time) {
- byte pal[256 * 4];
- byte oldPal[256 * 4];
+ byte pal[256 * 3];
+ byte oldPal[256 * 3];
debug(2, "DisplayMsg: %s", text);
@@ -402,9 +402,9 @@ void Screen::displayMsg(byte *text, int time) {
memcpy(oldPal, _palette, sizeof(oldPal));
memset(pal, 0, sizeof(pal));
- pal[187 * 4 + 0] = 255;
- pal[187 * 4 + 1] = 255;
- pal[187 * 4 + 2] = 255;
+ pal[187 * 3 + 0] = 255;
+ pal[187 * 3 + 1] = 255;
+ pal[187 * 3 + 2] = 255;
setPalette(0, 256, pal, RDPAL_FADE);
fadeUp();
@@ -926,17 +926,16 @@ void Screen::rollCredits() {
uint16 logoWidth = 0;
uint16 logoHeight = 0;
byte *logoData = NULL;
- byte palette[256 * 4];
+ byte palette[256 * 3];
if (f.open("credits.bmp")) {
logoWidth = f.readUint16LE();
logoHeight = f.readUint16LE();
for (i = 0; i < 256; i++) {
- palette[i * 4 + 0] = f.readByte() << 2;
- palette[i * 4 + 1] = f.readByte() << 2;
- palette[i * 4 + 2] = f.readByte() << 2;
- palette[i * 4 + 3] = 0;
+ palette[i * 3 + 0] = f.readByte() << 2;
+ palette[i * 3 + 1] = f.readByte() << 2;
+ palette[i * 3 + 2] = f.readByte() << 2;
}
logoData = (byte *)malloc(logoWidth * logoHeight);
@@ -946,10 +945,9 @@ void Screen::rollCredits() {
} else {
warning("Can't find credits.bmp");
memset(palette, 0, sizeof(palette));
- palette[14 * 4 + 0] = 252;
- palette[14 * 4 + 1] = 252;
- palette[14 * 4 + 2] = 252;
- palette[14 * 4 + 3] = 0;
+ palette[14 * 3 + 0] = 252;
+ palette[14 * 3 + 1] = 252;
+ palette[14 * 3 + 2] = 252;
}
setPalette(0, 256, palette, RDPAL_INSTANT);
@@ -1235,7 +1233,8 @@ void Screen::splashScreen() {
initialiseBackgroundLayer(NULL);
initialiseBackgroundLayer(NULL);
- setPalette(0, 256, _vm->fetchPalette(bgfile), RDPAL_FADE);
+ _vm->fetchPalette(bgfile, _palette);
+ setPalette(0, 256, _palette, RDPAL_FADE);
renderParallax(_vm->fetchBackgroundLayer(bgfile), 2);
closeBackgroundLayer();
diff --git a/engines/sword2/screen.h b/engines/sword2/screen.h
index 0abaebc5af..46eb53d0db 100644
--- a/engines/sword2/screen.h
+++ b/engines/sword2/screen.h
@@ -242,7 +242,7 @@ private:
uint16 _gridWide;
uint16 _gridDeep;
- byte _palette[256 * 4];
+ byte _palette[256 * 3];
byte _paletteMatch[PALTABLESIZE];
uint8 _fadeStatus;
diff --git a/engines/sword2/sprite.cpp b/engines/sword2/sprite.cpp
index 7d45f8df4e..255176292a 100644
--- a/engines/sword2/sprite.cpp
+++ b/engines/sword2/sprite.cpp
@@ -747,9 +747,9 @@ int32 Screen::drawSprite(SpriteInfo *s) {
for (i = 0; i < rs.height(); i++) {
for (j = 0; j < rs.width(); j++) {
if (src[j] && lightMap[j]) {
- uint8 r = ((32 - lightMap[j]) * _palette[src[j] * 4 + 0]) >> 5;
- uint8 g = ((32 - lightMap[j]) * _palette[src[j] * 4 + 1]) >> 5;
- uint8 b = ((32 - lightMap[j]) * _palette[src[j] * 4 + 2]) >> 5;
+ uint8 r = ((32 - lightMap[j]) * _palette[src[j] * 3 + 0]) >> 5;
+ uint8 g = ((32 - lightMap[j]) * _palette[src[j] * 3 + 1]) >> 5;
+ uint8 b = ((32 - lightMap[j]) * _palette[src[j] * 3 + 2]) >> 5;
src[j] = quickMatch(r, g, b);
}
}
@@ -787,12 +787,12 @@ int32 Screen::drawSprite(SpriteInfo *s) {
for (i = 0; i < rs.height(); i++) {
for (j = 0; j < rs.width(); j++) {
if (src[j]) {
- uint8 r1 = _palette[src[j] * 4 + 0];
- uint8 g1 = _palette[src[j] * 4 + 1];
- uint8 b1 = _palette[src[j] * 4 + 2];
- uint8 r2 = _palette[dst[j] * 4 + 0];
- uint8 g2 = _palette[dst[j] * 4 + 1];
- uint8 b2 = _palette[dst[j] * 4 + 2];
+ uint8 r1 = _palette[src[j] * 3 + 0];
+ uint8 g1 = _palette[src[j] * 3 + 1];
+ uint8 b1 = _palette[src[j] * 3 + 2];
+ uint8 r2 = _palette[dst[j] * 3 + 0];
+ uint8 g2 = _palette[dst[j] * 3 + 1];
+ uint8 b2 = _palette[dst[j] * 3 + 2];
uint8 r = (r1 * n + r2 * (8 - n)) >> 3;
uint8 g = (g1 * n + g2 * (8 - n)) >> 3;
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 9c67fcdf25..7ad021b3a5 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -319,11 +319,10 @@ void Sword2Engine::registerDefaultSettings() {
}
void Sword2Engine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
bool mute = ConfMan.getBool("mute");
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, mute ? 0 : ConfMan.getInt("music_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume"));
setSubtitles(ConfMan.getBool("subtitles"));
// Our own settings dialog can mute the music, speech and sound effects
diff --git a/engines/sword2/sword2.h b/engines/sword2/sword2.h
index 302627b635..e741c51ce1 100644
--- a/engines/sword2/sword2.h
+++ b/engines/sword2/sword2.h
@@ -206,7 +206,7 @@ public:
bool heldIsInInventory();
#endif
- byte *fetchPalette(byte *screenFile);
+ void fetchPalette(byte *screenFile, byte *palBuffer);
byte *fetchScreenHeader(byte *screenFile);
byte *fetchLayerHeader(byte *screenFile, uint16 layerNo);
byte *fetchShadingMask(byte *screenFile);
diff --git a/engines/sword25/gfx/graphicengine_script.cpp b/engines/sword25/gfx/graphicengine_script.cpp
index d67d0038c3..d8daaab32c 100644
--- a/engines/sword25/gfx/graphicengine_script.cpp
+++ b/engines/sword25/gfx/graphicengine_script.cpp
@@ -81,26 +81,6 @@ static ActionCallback *actionCallbackPtr = 0; // FIXME: should be turned into Gr
#define ANIMATION_TEMPLATE_CLASS_NAME "Gfx.AnimationTemplate"
static const char *GFX_LIBRARY_NAME = "Gfx";
-// Wie luaL_checkudata, nur ohne dass kein Fehler erzeugt wird.
-static void *my_checkudata(lua_State *L, int ud, const char *tname) {
- int top = lua_gettop(L);
-
- void *p = lua_touserdata(L, ud);
- if (p != NULL) { /* value is a userdata? */
- if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
- // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
- LuaBindhelper::getMetatable(L, tname);
- if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
- lua_settop(L, top);
- return p;
- }
- }
- }
-
- lua_settop(L, top);
- return NULL;
-}
-
static void newUintUserData(lua_State *L, uint value) {
void *userData = lua_newuserdata(L, sizeof(value));
memcpy(userData, &value, sizeof(value));
@@ -108,8 +88,8 @@ static void newUintUserData(lua_State *L, uint value) {
static AnimationTemplate *checkAnimationTemplate(lua_State *L, int idx = 1) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.AnimationTemplate
- uint animationTemplateHandle;
- if ((animationTemplateHandle = *reinterpret_cast<uint *>(my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME))) != 0) {
+ uint animationTemplateHandle = *reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME));
+ if (animationTemplateHandle != 0) {
AnimationTemplate *animationTemplatePtr = AnimationTemplateRegistry::instance().resolveHandle(animationTemplateHandle);
if (!animationTemplatePtr)
luaL_error(L, "The animation template with the handle %d does no longer exist.", animationTemplateHandle);
@@ -370,10 +350,10 @@ static const luaL_reg GFX_FUNCTIONS[] = {
static RenderObjectPtr<RenderObject> checkRenderObject(lua_State *L, bool errorIfRemoved = true) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable einer Klasse haben, die von Gfx.RenderObject "erbt".
uint *userDataPtr;
- if ((userDataPtr = (uint *) my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0 ||
- (userDataPtr = (uint *) my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0 ||
- (userDataPtr = (uint *) my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0 ||
- (userDataPtr = (uint *) my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0 ||
+ (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0 ||
+ (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0 ||
+ (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
if (roPtr.isValid())
return roPtr;
@@ -600,11 +580,11 @@ static const luaL_reg RENDEROBJECT_METHODS[] = {
static RenderObjectPtr<Panel> checkPanel(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Panel
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
- if (roPtr.isValid()) {
+ if (roPtr.isValid())
return roPtr->toPanel();
- } else
+ else
luaL_error(L, "The panel with the handle %d does no longer exist.", *userDataPtr);
} else {
luaL_argcheck(L, 0, 1, "'" PANEL_CLASS_NAME "' expected");
@@ -645,11 +625,11 @@ static const luaL_reg PANEL_METHODS[] = {
static RenderObjectPtr<Bitmap> checkBitmap(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Bitmap
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
- if (roPtr.isValid()) {
+ if (roPtr.isValid())
return roPtr->toBitmap();
- } else
+ else
luaL_error(L, "The bitmap with the handle %d does no longer exist.", *userDataPtr);
} else {
luaL_argcheck(L, 0, 1, "'" BITMAP_CLASS_NAME "' expected");
@@ -790,13 +770,12 @@ static const luaL_reg BITMAP_METHODS[] = {
static RenderObjectPtr<Animation> checkAnimation(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Animation
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
if (roPtr.isValid())
return roPtr->toAnimation();
- else {
+ else
luaL_error(L, "The animation with the handle %d does no longer exist.", *userDataPtr);
- }
} else {
luaL_argcheck(L, 0, 1, "'" ANIMATION_CLASS_NAME "' expected");
}
@@ -1064,7 +1043,7 @@ static const luaL_reg ANIMATION_METHODS[] = {
static RenderObjectPtr<Text> checkText(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Text
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
if (roPtr.isValid())
return roPtr->toText();
diff --git a/engines/sword25/gfx/image/art.cpp b/engines/sword25/gfx/image/art.cpp
index d30460901d..69f9425a53 100644
--- a/engines/sword25/gfx/image/art.cpp
+++ b/engines/sword25/gfx/image/art.cpp
@@ -1041,7 +1041,7 @@ static void art_pri_free(ArtPriQ *pq) {
free(pq);
}
-static art_boolean art_pri_empty(ArtPriQ *pq) {
+static bool art_pri_empty(ArtPriQ *pq) {
return pq->n_items == 0;
}
@@ -1122,7 +1122,7 @@ static int art_svp_writer_rewind_add_segment(ArtSvpWriter *self, int wind_left,
ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
ArtSVP *svp;
ArtSVPSeg *seg;
- art_boolean left_filled = 0, right_filled = 0;
+ bool left_filled = 0, right_filled = 0;
int wind_right = wind_left + delta_wind;
int seg_num;
const int init_n_points_max = 4;
@@ -1459,7 +1459,7 @@ static ArtActiveSeg *art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x,
ArtActiveSeg *seg, ArtBreakFlags break_flags) {
ArtActiveSeg *left, *right;
double x_min = x, x_max = x;
- art_boolean left_live, right_live;
+ bool left_live, right_live;
double d;
double new_x;
ArtActiveSeg *test, *result = NULL;
@@ -1490,9 +1490,9 @@ static ArtActiveSeg *art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x,
left = left->left;
left_live = (left != NULL);
} else
- left_live = ART_FALSE;
+ left_live = false;
} else
- left_live = ART_FALSE;
+ left_live = false;
} else if (right_live) {
if (x >= right->x[(right->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] &&
/* It may be that one of these conjuncts turns out to be always
@@ -1510,9 +1510,9 @@ static ArtActiveSeg *art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x,
right = right->right;
right_live = (right != NULL);
} else
- right_live = ART_FALSE;
+ right_live = false;
} else
- right_live = ART_FALSE;
+ right_live = false;
}
}
@@ -1571,7 +1571,7 @@ static void art_svp_intersect_swap_active(ArtIntersectCtx *ctx,
* Return value: True if the intersection took place at the current
* scan line, indicating further iteration is needed.
**/
-static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
+static bool art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
ArtActiveSeg *left_seg, ArtActiveSeg *right_seg,
ArtBreakFlags break_flags) {
double left_x0, left_y0, left_x1;
@@ -1597,17 +1597,17 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (left_x1 <
right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
left_y1 == right_seg->y0)
- return ART_FALSE;
+ return false;
d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
if (d < -EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d < EPSILON_A) {
/* I'm unsure about the break flags here. */
double right_x1 = art_svp_intersect_break(ctx, right_seg,
left_x1, left_y1,
ART_BREAK_RIGHT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else if (left_y1 > right_y1) {
/* Test right (x1, y1) against left segment */
@@ -1615,27 +1615,27 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
right_y1 == left_seg->y0)
- return ART_FALSE;
+ return false;
d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
if (d > EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d > -EPSILON_A) {
/* See above regarding break flags. */
left_x1 = art_svp_intersect_break(ctx, left_seg,
right_x1, right_y1,
ART_BREAK_LEFT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else { /* left_y1 == right_y1 */
left_x1 = left_seg->x[1];
double right_x1 = right_seg->x[1];
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
art_svp_intersect_swap_active(ctx, left_seg, right_seg);
- return ART_TRUE;
+ return true;
}
if (left_y1 < right_y1) {
@@ -1645,16 +1645,16 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (left_x1 <
right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
left_y1 == right_seg->y0)
- return ART_FALSE;
+ return false;
d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
if (d < -EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d < EPSILON_A) {
double right_x1 = art_svp_intersect_break(ctx, right_seg,
left_x1, left_y1,
ART_BREAK_RIGHT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else if (left_y1 > right_y1) {
/* Test right (x1, y1) against left segment */
@@ -1662,23 +1662,23 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
right_y1 == left_seg->y0)
- return ART_FALSE;
+ return false;
d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
if (d > EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d > -EPSILON_A) {
left_x1 = art_svp_intersect_break(ctx, left_seg,
right_x1, right_y1,
ART_BREAK_LEFT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else { /* left_y1 == right_y1 */
left_x1 = left_seg->x[1];
double right_x1 = right_seg->x[1];
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
/* The segments cross. Find the intersection point. */
@@ -1748,7 +1748,7 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
winner->horiz_delta_wind -= loser->delta_wind;
art_svp_intersect_swap_active(ctx, left_seg, right_seg);
- return ART_TRUE;
+ return true;
}
} else if (y == right_seg->y0) {
art_svp_intersect_push_pt(ctx, left_seg, x, y);
@@ -1764,7 +1764,7 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL)
art_svp_intersect_add_point(ctx, x, y, right_seg->right, break_flags);
}
- return ART_FALSE;
+ return false;
}
/**
@@ -1885,7 +1885,7 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
if (x0 > x1) {
ArtActiveSeg *left;
- art_boolean first = ART_TRUE;
+ bool first = true;
for (left = seg->left; left != NULL; left = seg->left) {
int left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG;
@@ -1902,12 +1902,12 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
if (first && left->right != NULL) {
art_svp_intersect_test_cross(ctx, left, left->right,
ART_BREAK_RIGHT);
- first = ART_FALSE;
+ first = false;
}
}
} else {
ArtActiveSeg *right;
- art_boolean first = ART_TRUE;
+ bool first = true;
for (right = seg->right; right != NULL; right = seg->right) {
int right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG;
@@ -1925,7 +1925,7 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
if (first && right->left != NULL) {
art_svp_intersect_test_cross(ctx, right->left, right,
ART_BREAK_RIGHT);
- first = ART_FALSE;
+ first = false;
}
}
}
@@ -2231,7 +2231,7 @@ void art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out) {
typedef double artfloat;
-struct _ArtSVPRenderAAIter {
+struct ArtSVPRenderAAIter {
const ArtSVP *svp;
int x0, x1;
int y;
diff --git a/engines/sword25/gfx/image/art.h b/engines/sword25/gfx/image/art.h
index 90baa770cf..fe3bbd4982 100644
--- a/engines/sword25/gfx/image/art.h
+++ b/engines/sword25/gfx/image/art.h
@@ -42,10 +42,6 @@
namespace Sword25 {
-typedef byte art_u8;
-typedef uint16 art_u16;
-typedef uint32 art_u32;
-
/* These aren't, strictly speaking, configuration macros, but they're
damn handy to have around, and may be worth playing with for
debugging. */
@@ -55,95 +51,55 @@ typedef uint32 art_u32;
/* This one must be used carefully - in particular, p and max should
be variables. They can also be pstruct->el lvalues. */
-#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0)
-
-typedef int art_boolean;
-#define ART_FALSE 0
-#define ART_TRUE 1
-
-/* define pi */
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif /* M_PI */
-
-#ifndef M_SQRT2
-#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
-#endif /* M_SQRT2 */
-
-/* Provide macros to feature the GCC function attribute.
- */
-#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
-#define ART_GNUC_PRINTF( format_idx, arg_idx ) \
- __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#define ART_GNUC_NORETURN \
- __attribute__((__noreturn__))
-#else /* !__GNUC__ */
-#define ART_GNUC_PRINTF( format_idx, arg_idx )
-#define ART_GNUC_NORETURN
-#endif /* !__GNUC__ */
-
-void ART_GNUC_NORETURN
-art_die(const char *fmt, ...) ART_GNUC_PRINTF(1, 2);
-
-void
-art_warn(const char *fmt, ...) ART_GNUC_PRINTF(1, 2);
-
-typedef struct _ArtDRect ArtDRect;
-typedef struct _ArtIRect ArtIRect;
-
-struct _ArtDRect {
+#define art_expand(p, type, max) \
+ do { \
+ if(max) {\
+ p = art_renew(p, type, max <<= 1); \
+ } else { \
+ max = 1; \
+ p = art_new(type, 1); \
+ } \
+ } while (0)
+
+struct ArtDRect {
/*< public >*/
double x0, y0, x1, y1;
};
-struct _ArtIRect {
- /*< public >*/
- int x0, y0, x1, y1;
-};
-
-typedef struct _ArtPoint ArtPoint;
-
-struct _ArtPoint {
+struct ArtPoint {
/*< public >*/
double x, y;
};
/* Basic data structures and constructors for sorted vector paths */
-typedef struct _ArtSVP ArtSVP;
-typedef struct _ArtSVPSeg ArtSVPSeg;
-
-struct _ArtSVPSeg {
+struct ArtSVPSeg {
int n_points;
int dir; /* == 0 for "up", 1 for "down" */
ArtDRect bbox;
ArtPoint *points;
};
-struct _ArtSVP {
+struct ArtSVP {
int n_segs;
ArtSVPSeg segs[1];
};
-void
-art_svp_free(ArtSVP *svp);
+void art_svp_free(ArtSVP *svp);
-int
-art_svp_seg_compare(const void *s1, const void *s2);
+int art_svp_seg_compare(const void *s1, const void *s2);
/* Basic data structures and constructors for bezier paths */
-typedef enum {
+enum ArtPathcode {
ART_MOVETO,
ART_MOVETO_OPEN,
ART_CURVETO,
ART_LINETO,
ART_END
-} ArtPathcode;
-
-typedef struct _ArtBpath ArtBpath;
+};
-struct _ArtBpath {
+struct ArtBpath {
/*< public >*/
ArtPathcode code;
double x1;
@@ -156,10 +112,8 @@ struct _ArtBpath {
/* Basic data structures and constructors for simple vector paths */
-typedef struct _ArtVpath ArtVpath;
-
/* CURVETO is not allowed! */
-struct _ArtVpath {
+struct ArtVpath {
ArtPathcode code;
double x;
double y;
@@ -167,8 +121,7 @@ struct _ArtVpath {
/* Some of the functions need to go into their own modules */
-void
-art_vpath_add_point(ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
+void art_vpath_add_point(ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
ArtPathcode code, double x, double y);
ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness);
@@ -177,57 +130,49 @@ ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness);
#ifndef ART_WIND_RULE_DEFINED
#define ART_WIND_RULE_DEFINED
-typedef enum {
+enum ArtWindRule {
ART_WIND_RULE_NONZERO,
ART_WIND_RULE_INTERSECT,
ART_WIND_RULE_ODDEVEN,
ART_WIND_RULE_POSITIVE
-} ArtWindRule;
+};
#endif
-typedef struct _ArtSvpWriter ArtSvpWriter;
-
-struct _ArtSvpWriter {
+struct ArtSvpWriter {
int (*add_segment)(ArtSvpWriter *self, int wind_left, int delta_wind,
double x, double y);
void (*add_point)(ArtSvpWriter *self, int seg_id, double x, double y);
void (*close_segment)(ArtSvpWriter *self, int seg_id);
};
-ArtSvpWriter *
-art_svp_writer_rewind_new(ArtWindRule rule);
+ArtSvpWriter *art_svp_writer_rewind_new(ArtWindRule rule);
-ArtSVP *
-art_svp_writer_rewind_reap(ArtSvpWriter *self);
+ArtSVP *art_svp_writer_rewind_reap(ArtSvpWriter *self);
-int
-art_svp_seg_compare(const void *s1, const void *s2);
+int art_svp_seg_compare(const void *s1, const void *s2);
-void
-art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out);
+void art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out);
/* Sort vector paths into sorted vector paths. */
-ArtSVP *
-art_svp_from_vpath(ArtVpath *vpath);
+ArtSVP *art_svp_from_vpath(ArtVpath *vpath);
/* Sort vector paths into sorted vector paths. */
-typedef enum {
+enum ArtPathStrokeJoinType {
ART_PATH_STROKE_JOIN_MITER,
ART_PATH_STROKE_JOIN_ROUND,
ART_PATH_STROKE_JOIN_BEVEL
-} ArtPathStrokeJoinType;
+};
-typedef enum {
+enum ArtPathStrokeCapType {
ART_PATH_STROKE_CAP_BUTT,
ART_PATH_STROKE_CAP_ROUND,
ART_PATH_STROKE_CAP_SQUARE
-} ArtPathStrokeCapType;
+};
-ArtSVP *
-art_svp_vpath_stroke(ArtVpath *vpath,
+ArtSVP *art_svp_vpath_stroke(ArtVpath *vpath,
ArtPathStrokeJoinType join,
ArtPathStrokeCapType cap,
double line_width,
@@ -235,8 +180,7 @@ art_svp_vpath_stroke(ArtVpath *vpath,
double flatness);
/* This version may have winding numbers exceeding 1. */
-ArtVpath *
-art_svp_vpath_stroke_raw(ArtVpath *vpath,
+ArtVpath *art_svp_vpath_stroke_raw(ArtVpath *vpath,
ArtPathStrokeJoinType join,
ArtPathStrokeCapType cap,
double line_width,
@@ -246,27 +190,22 @@ art_svp_vpath_stroke_raw(ArtVpath *vpath,
/* The spiffy antialiased renderer for sorted vector paths. */
-typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep;
-typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter;
-
-struct _ArtSVPRenderAAStep {
+struct ArtSVPRenderAAStep {
int x;
int delta; /* stored with 16 fractional bits */
};
-ArtSVPRenderAAIter *
-art_svp_render_aa_iter(const ArtSVP *svp,
+struct ArtSVPRenderAAIter;
+
+ArtSVPRenderAAIter *art_svp_render_aa_iter(const ArtSVP *svp,
int x0, int y0, int x1, int y1);
-void
-art_svp_render_aa_iter_step(ArtSVPRenderAAIter *iter, int *p_start,
+void art_svp_render_aa_iter_step(ArtSVPRenderAAIter *iter, int *p_start,
ArtSVPRenderAAStep **p_steps, int *p_n_steps);
-void
-art_svp_render_aa_iter_done(ArtSVPRenderAAIter *iter);
+void art_svp_render_aa_iter_done(ArtSVPRenderAAIter *iter);
-void
-art_svp_render_aa(const ArtSVP *svp,
+void art_svp_render_aa(const ArtSVP *svp,
int x0, int y0, int x1, int y1,
void (*callback)(void *callback_data,
int y,
diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h
index 5ac6d1ac25..7029402c4a 100644
--- a/engines/sword25/gfx/image/image.h
+++ b/engines/sword25/gfx/image/image.h
@@ -55,75 +55,72 @@ public:
// Enums
/**
- @brief Die mіglichen Flippingparameter fќr die Blit-Methode.
+ @brief The possible flipping parameters for the blit methode.
*/
enum FLIP_FLAGS {
- /// Das Bild wird nicht gespiegelt.
+ /// The image will not be flipped.
FLIP_NONE = 0,
- /// Das Bild wird an der horizontalen Achse gespiegelt.
+ /// The image will be flipped at the horizontal axis.
FLIP_H = 1,
- /// Das Bild wird an der vertikalen Achse gespiegelt.
+ /// The image will be flipped at the vertical axis.
FLIP_V = 2,
- /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
+ /// The image will be flipped at the horizontal and vertical axis.
FLIP_HV = FLIP_H | FLIP_V,
- /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
+ /// The image will be flipped at the horizontal and vertical axis.
FLIP_VH = FLIP_H | FLIP_V
};
//@{
- /** @name Accessor-Methoden */
+ /** @name Accessor methods */
/**
- @brief Gibt die Breite des Bildes in Pixeln zurќck
+ @brief Returns the width of the image in pixels
*/
virtual int getWidth() const = 0;
/**
- @brief Gibt die Hіhe des Bildes in Pixeln zurќck
+ @brief Returns the height of the image in pixels
*/
virtual int getHeight() const = 0;
/**
- @brief Gibt das Farbformat des Bildes zurќck
+ @brief Returns the color format of the image
*/
virtual GraphicEngine::COLOR_FORMATS getColorFormat() const = 0;
//@}
//@{
- /** @name Render-Methoden */
+ /** @name Render methodes */
/**
- @brief Rendert das Bild in den Framebuffer.
- @param pDest ein Pointer auf das Zielbild. In den meisten Fфllen ist dies der Framebuffer.
- @param PosX die Position auf der X-Achse im Zielbild in Pixeln, an der das Bild gerendert werden soll.<br>
- Der Standardwert ist 0.
- @param PosY die Position auf der Y-Achse im Zielbild in Pixeln, an der das Bild gerendert werden soll.<br>
- Der Standardwert ist 0.
- @param Flipping gibt an, wie das Bild gespiegelt werden soll.<br>
- Der Standardwert ist BS_Image::FLIP_NONE (keine Spiegelung)
- @param pSrcPartRect Pointer auf ein Common::Rect, welches den Ausschnitt des Quellbildes spezifiziert, der gerendert
- werden soll oder NULL, falls das gesamte Bild gerendert werden soll.<br>
- Dieser Ausschnitt bezieht sich auf das ungespiegelte und unskalierte Bild.<br>
- Der Standardwert ist NULL.
- @param Color ein ARGB Farbwert, der die Parameter fќr die Farbmodulation und fќrs Alphablending festlegt.<br>
- Die Alpha-Komponente der Farbe bestimmt den Alphablending Parameter (0 = keine Deckung, 255 = volle Deckung).<br>
- Die Farbkomponenten geben die Farbe fќr die Farbmodulation an.<br>
- Der Standardwert is BS_ARGB(255, 255, 255, 255) (volle Deckung, keine Farbmodulation).
- Zum Erzeugen des Farbwertes kіnnen die Makros BS_RGB und BS_ARGB benutzt werden.
- @param Width gibt die Ausgabebreite des Bildausschnittes an.
- Falls diese von der Breite des Bildausschnittes abweicht wird
- das Bild entsprechend Skaliert.<br>
- Der Wert -1 gibt an, dass das Bild nicht Skaliert werden soll.<br>
- Der Standardwert ist -1.
- @param Width gibt die Ausgabehіhe des Bildausschnittes an.
- Falls diese von der Hіhe des Bildauschnittes abweicht, wird
- das Bild entsprechend Skaliert.<br>
- Der Wert -1 gibt an, dass das Bild nicht Skaliert werden soll.<br>
- Der Standardwert ist -1.
- @return Gibt false zurќck, falls das Rendern fehlgeschlagen ist.
- @remark Er werden nicht alle Blitting-Operationen von allen BS_Image-Klassen unterstќtzt.<br>
- Mehr Informationen gibt es in der Klassenbeschreibung von BS_Image und durch folgende Methoden:
+ @brief renders the image in the framebuffer
+ @param pDest a pointer to the target image. In most cases this is the framebuffer.
+ @param PosX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.<br>
+ The default value is 0.
+ @param PosY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.<br>
+ The default value is 0.
+ @param Flipping how the the image should be flipped.<br>
+ The default value is BS_Image::FLIP_NONE (no flipping)
+ @param pSrcPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.<br>
+ This referes to the unflipped and unscaled image.<br>
+ The default value is NULL.
+ @param Color an ARGB color value, which determines the parameters for the color modulation und alpha blending.<br>
+ The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).<br>
+ The color components determines the color for color modulation.<br>
+ The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation).
+ The macros BS_RGB and BS_ARGB can be used for the creation of the color value.
+ @param Width the output width of the screen section.
+ The images will be scaled if the output width of the screen section differs from the image section.<br>
+ The value -1 determines that the image should not be scaled.<br>
+ The default value is -1.
+ @param Width the output height of the screen section.
+ The images will be scaled if the output width of the screen section differs from the image section.<br>
+ The value -1 determines that the image should not be scaled.<br>
+ The default value is -1.
+ @return returns false if the rendering failed.
+ @remark Not all blitting operations of all BS_Image classes are supported.<br>
+ More information can be find in the class description of BS_Image and the following methodes:
- IsBlitTarget()
- IsScalingAllowed()
- IsFillingAllowed()
@@ -138,79 +135,74 @@ public:
int width = -1, int height = -1) = 0;
/**
- @brief Fќllt einen Rechteckigen Bereich des Bildes mit einer Farbe.
- @param pFillRect Pointer auf ein Common::Rect, welches den Ausschnitt des Bildes spezifiziert, der gefќllt
- werden soll oder NULL, falls das gesamte Bild gefќllt werden soll.<br>
- Der Standardwert ist NULL.
- @param Color der 32 Bit Farbwert mit dem der Bildbereich gefќllt werden soll.
- @remark Es ist mіglich ќber die Methode transparente Rechtecke darzustellen, indem man eine Farbe mit einem Alphawert ungleich
- 255 angibt.
- @remark Unabhфngig vom Farbformat des Bildes muss ein 32 Bit Farbwert angegeben werden. Zur Erzeugung, kіnnen die Makros
- BS_RGB und BS_ARGB benutzt werden.
- @remark Falls das Rechteck nicht vіllig innerhalb des Bildschirms ist, wird es automatisch zurechtgestutzt.
+ @brief fills a rectangular section of the image with a color.
+ @param pFillRect Pointer on Common::Rect which specifies the section of the image which is supposed to be filled. If the whole image has to be filled this value is NULL.<br>
+ The default value is NULL.
+ @param Color the 32 Bit color value for filling the image section.
+ @remark It is possible to create transparent rectangulars by using a color with alpha value not equal to 255.
+ @remark Independent from the color format of the image, it must be given a 32 bit color value. The macros BS_RGB and BS_ARGB can be used for the creation of the color value.
+ @remark If the rectangular is not completely inside the screen area, it will be automatically trimmed.
*/
virtual bool fill(const Common::Rect *pFillRect = 0, uint color = BS_RGB(0, 0, 0)) = 0;
/**
- @brief Fќllt den Inhalt des Bildes mit Pixeldaten.
- @param Pixeldata ein Vector der die Pixeldaten enthфlt. Sie mќssen in dem Farbformat des Bildes vorliegen und es mќssen genќgend Daten
- vorhanden sein, um das ganze Bild zu fќllen.
- @param Offset der Offset in Byte im Pixeldata-Vector an dem sich der erste zu schreibende Pixel befindet.<br>
- Der Standardwert ist 0.
- @param Stride der Abstand in Byte zwischen dem Zeilenende und dem Beginn einer neuen Zeile im Pixeldata-Vector.<br>
- Der Standardwert ist 0.
- @return Gibt false zurќck, falls der Aufruf fehlgeschlagen ist.
- @remark Ein Aufruf dieser Methode ist nur erlaubt, wenn IsSetContentAllowed() true zurќckgibt.
+ @brief Fills the content of the image with pixel data.
+ @param Pixeldata a vector which cotains the pixel data. They must be present in the color format of the image and there must be enough data available for filling the whole image.
+ @param Offset the offset in Byte in Pixeldata-Vector on which the first pixel to write is located.<br>
+ The default value is 0.
+ @param Stride the distance in Byte between the end of line and the beginning of a new line in Pixeldata-Vector.<br>
+ The default value is 0.
+ @return returns false, if the call failed.
+ @remark A call of this methode is only allowd if IsSetContentAllowed() returns true.
*/
virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride) = 0;
/**
- @brief Liest einen Pixel des Bildes.
- @param X die X-Koordinate des Pixels.
- @param Y die Y-Koordinate des Pixels
- @return Gibt den 32-Bit Farbwert des Pixels an der ќbergebenen Koordinate zurќck.
- @remark Diese Methode sollte auf keine Fall benutzt werden um grіпere Teile des Bildes zu lesen, da sie sehr langsam ist. Sie ist
- eher dafќr gedacht einzelne Pixel des Bildes auszulesen.
+ @brief Reads out a pixel of the image.
+ @param X the X-coordinate of the pixel.
+ @param Y the y-coordinate of the pixel.
+ @return Returns the 32-bit color value of the pixel at the given position.
+ @remark This methode should not be used in no way to read out bigger parts of the image because the method is very slow. The method is rather intended for reading out single pixels of the image..
*/
virtual uint getPixel(int x, int y) = 0;
//@{
- /** @name Auskunfts-Methoden */
+ /** @name Information methodes */
/**
- @brief мberprќft, ob an dem BS_Image Blit() aufgerufen werden darf.
- @return Gibt false zurќck, falls ein Blit()-Aufruf an diesem Objekt nicht gestattet ist.
+ @brief Checks, if it is allowed to call BS_Image Blit().
+ @return Returns false, if a Blit() call is not allowed at this object.
*/
virtual bool isBlitSource() const = 0;
/**
- @brief мberprќft, ob das BS_Image ein Zielbild fќr einen Blit-Aufruf sein kann.
- @return Gibt false zurќck, falls ein Blit-Aufruf mit diesem Objekt als Ziel nicht gestattet ist.
+ @brief Checks, if the BS_Image can be a target image for a Blit call.
+ @return Returns false, if a Blit() call with this object as an target is not allowed.
*/
virtual bool isBlitTarget() const = 0;
/**
- @brief Gibt true zurќck, falls das BS_Image bei einem Aufruf von Blit() skaliert dargestellt werden kann.
+ @brief Returns true, if the BS_Image is allowed to be scaled by a Blit() call.
*/
virtual bool isScalingAllowed() const = 0;
/**
- @brief Gibt true zurќck, wenn das BS_Image mit einem Aufruf von Fill() gefќllt werden kann.
+ @brief Returns true, if the BS_Image is allowed to be filled by a Fill() call.
*/
virtual bool isFillingAllowed() const = 0;
/**
- @brief Gibt true zurќck, wenn das BS_Image bei einem Aufruf von Blit() mit einem Alphawert dargestellt werden kann.
+ @brief Returns true, if the BS_Image is allowed to be displayed with an alpha value.
*/
virtual bool isAlphaAllowed() const = 0;
/**
- @brief Gibt true zurќck, wenn das BS_Image bei einem Aufruf von Blit() mit Farbmodulation dargestellt werden kann.
+ @brief Return true, if the BS_Image is allowed to be displayed with color modulation by a Blit() call
*/
virtual bool isColorModulationAllowed() const = 0;
/**
- @brief Gibt true zurќck, wenn der Inhalt des BS_Image durch eine Aufruf von SetContent() ausgetauscht werden kann.
+ @brief Returns true, if the content of the BS_Image is allowed to be replaced by call of SetContent().
*/
virtual bool isSetContentAllowed() const = 0;
diff --git a/engines/sword25/gfx/image/pngloader.cpp b/engines/sword25/gfx/image/pngloader.cpp
index f54b45254b..f6c00b6968 100644
--- a/engines/sword25/gfx/image/pngloader.cpp
+++ b/engines/sword25/gfx/image/pngloader.cpp
@@ -84,7 +84,7 @@ static uint findEmbeddedPNG(const byte *fileDataPtr, uint fileSize) {
Common::MemoryReadStream stream(fileDataPtr, fileSize);
stream.seek(0, SEEK_SET);
- // Headerinformationen der Spielstandes einlesen.
+ // Read header information of savegame
uint compressedGamedataSize;
loadString(stream); // Marker
loadString(stream); // Version
@@ -124,7 +124,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
error("png_check_sig failed");
}
- // Die beiden PNG Strukturen erstellen
+ // Create both PNG structures
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
error("Could not create libpng read struct.");
@@ -135,31 +135,31 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
error("Could not create libpng info struct.");
}
- // Alternative Lesefunktion benutzen
+ // Use alternative reading function
const byte **ref = &fileDataPtr;
png_set_read_fn(png_ptr, (void *)ref, png_user_read_data);
- // PNG Header einlesen
+ // Read PNG header
png_read_info(png_ptr, info_ptr);
- // PNG Informationen auslesen
+ // Read out PNG informations
png_uint_32 w, h;
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
width = w;
height = h;
- // Pitch des Ausgabebildes berechnen
+ // Calculate pitch of output image
pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width);
- // Speicher fќr die endgќltigen Bilddaten reservieren
- // Dieses geschieht vor dem reservieren von Speicher fќr temporфre Bilddaten um die Fragmentierung des Speichers gering zu halten
+ // Allocate memory for the final image data.
+ // To keep memory framentation low this happens before allocating memory for temporary image data.
uncompressedDataPtr = new byte[pitch * height];
if (!uncompressedDataPtr) {
error("Could not allocate memory for output image.");
}
- // Bilder jeglicher Farbformate werden zunфchst in ARGB Bilder umgewandelt
+ // Images of all color formates will be transformed into ARGB images
if (bitDepth == 16)
png_set_strip_16(png_ptr);
if (colorType == PNG_COLOR_TYPE_PALETTE)
@@ -177,7 +177,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
if (colorType != PNG_COLOR_TYPE_RGB_ALPHA)
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
- // Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen
+ // After the transformations have been registered, the image data is read again.
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL);
width = w;
@@ -218,7 +218,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);
Graphics::PNG *png = new Graphics::PNG();
if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done
- error("Error while reading PNG image");
+ error("Error while reading PNG image");
Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
Graphics::Surface *pngSurface = png->getSurface(format);
@@ -251,7 +251,7 @@ bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &w
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
- // Die beiden PNG Strukturen erstellen
+ // Create both PNG structures
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
error("Could not create libpng read struct.");
@@ -262,14 +262,14 @@ bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &w
error("Could not create libpng info struct.");
}
- // Alternative Lesefunktion benutzen
+ // Use alternative reading function
const byte **ref = &fileDataPtr;
png_set_read_fn(png_ptr, (void *)ref, png_user_read_data);
- // PNG Header einlesen
+ // Read PNG Header
png_read_info(png_ptr, info_ptr);
- // PNG Informationen auslesen
+ // Read out PNG informations
int bitDepth;
int colorType;
png_uint_32 w, h;
@@ -278,7 +278,7 @@ bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &w
width = w;
height = h;
- // Die Strukturen freigeben
+ // Destroy libpng structures
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
#else
// We don't need to read the image properties here...
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index 0d2ffb5aee..ced3296e57 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -59,7 +59,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
_backSurface = Kernel::getInstance()->getGfx()->getSurface();
- // Datei laden
+ // Load file
byte *pFileData;
uint fileSize;
pFileData = pPackage->getFile(filename, &fileSize);
@@ -68,7 +68,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
return;
}
- // Bildeigenschaften bestimmen
+ // Determine image properties
int pitch;
if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) {
error("Could not read image properties.");
@@ -76,14 +76,14 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
return;
}
- // Das Bild dekomprimieren
+ // Uncompress the image
if (!PNGLoader::decodeImage(pFileData, fileSize, _data, _width, _height, pitch)) {
error("Could not decode image.");
delete[] pFileData;
return;
}
- // Dateidaten freigeben
+ // Cleanup FileData
delete[] pFileData;
_doCleanup = true;
@@ -134,7 +134,7 @@ bool RenderedImage::fill(const Common::Rect *pFillRect, uint color) {
// -----------------------------------------------------------------------------
bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) {
- // мberprќfen, ob PixelData ausreichend viele Pixel enthфlt um ein Bild der Grіпe Width * Height zu erzeugen
+ // Check if PixelData contains enough pixel to create an image with image size equals width * height
if (size < static_cast<uint>(_width * _height * 4)) {
error("PixelData vector is too small to define a 32 bit %dx%d image.", _width, _height);
return false;
@@ -198,11 +198,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
srcImage.w = pPartRect->right - pPartRect->left;
srcImage.h = pPartRect->bottom - pPartRect->top;
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping,
+ debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping,
pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height);
} else {
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0,
+ debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0,
srcImage.w, srcImage.h, color, width, height);
}
@@ -324,7 +324,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
ino += inoStep;
}
- g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
+ g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
img->w, img->h);
}
@@ -413,7 +413,7 @@ int *RenderedImage::scaleLine(int size, int srcSize) {
distCtr -= 100;
}
}
-
+
return v;
}
diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h
index 0375c7acbe..e3f23747da 100644
--- a/engines/sword25/gfx/image/renderedimage.h
+++ b/engines/sword25/gfx/image/renderedimage.h
@@ -50,12 +50,12 @@ public:
RenderedImage(const Common::String &filename, bool &result);
/**
- @brief Erzeugt ein leeres BS_RenderedImage
+ @brief Creates an empty BS_RenderedImage
- @param Width die Breite des zu erzeugenden Bildes.
- @param Height die Hіhe des zu erzeugenden Bildes
- @param Result gibt dem Aufrufer bekannt, ob der Konstruktor erfolgreich ausgefќhrt wurde. Wenn es nach dem Aufruf false enthalten sollte,
- dќrfen keine Methoden am Objekt aufgerufen werden und das Objekt ist sofort zu zerstіren.
+ @param Width The width of the image to be created.
+ @param Height The height of the image to be created
+ @param Result Informs the caller, whether the constructor is executed successfully. If it contains false
+ after the call, do not call methods on the object and destroy the object immediately.
*/
RenderedImage(uint width, uint height, bool &result);
RenderedImage();
@@ -84,25 +84,25 @@ public:
void replaceContent(byte *pixeldata, int width, int height);
virtual uint getPixel(int x, int y);
- virtual bool isBlitSource() const {
+ virtual bool isBlitSource() const {
return true;
}
- virtual bool isBlitTarget() const {
+ virtual bool isBlitTarget() const {
return false;
}
- virtual bool isScalingAllowed() const {
+ virtual bool isScalingAllowed() const {
return true;
}
- virtual bool isFillingAllowed() const {
+ virtual bool isFillingAllowed() const {
return false;
}
- virtual bool isAlphaAllowed() const {
+ virtual bool isAlphaAllowed() const {
return true;
}
- virtual bool isColorModulationAllowed() const {
+ virtual bool isColorModulationAllowed() const {
return true;
}
- virtual bool isSetContentAllowed() const {
+ virtual bool isSetContentAllowed() const {
return true;
}
diff --git a/engines/sword25/gfx/image/swimage.cpp b/engines/sword25/gfx/image/swimage.cpp
index ff06491b36..3b9b939eb3 100644
--- a/engines/sword25/gfx/image/swimage.cpp
+++ b/engines/sword25/gfx/image/swimage.cpp
@@ -47,7 +47,7 @@ SWImage::SWImage(const Common::String &filename, bool &result) :
PackageManager *pPackage = Kernel::getInstance()->getPackage();
assert(pPackage);
- // Datei laden
+ // Load file
byte *pFileData;
uint fileSize;
pFileData = pPackage->getFile(filename, &fileSize);
@@ -56,21 +56,21 @@ SWImage::SWImage(const Common::String &filename, bool &result) :
return;
}
- // Bildeigenschaften bestimmen
+ // Determine image properties
int pitch;
if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) {
error("Could not read image properties.");
return;
}
- // Das Bild dekomprimieren
+ // Uncompress the image
byte *pUncompressedData;
if (!PNGLoader::decodeImage(pFileData, fileSize, pUncompressedData, _width, _height, pitch)) {
error("Could not decode image.");
return;
}
- // Dateidaten freigeben
+ // Cleanup FileData
delete[] pFileData;
_imageDataPtr = (uint *)pUncompressedData;
diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp
index 094e6a59a8..241e80bad3 100644
--- a/engines/sword25/gfx/image/vectorimage.cpp
+++ b/engines/sword25/gfx/image/vectorimage.cpp
@@ -47,15 +47,15 @@ namespace Sword25 {
#define BEZSMOOTHNESS 0.5
// -----------------------------------------------------------------------------
-// SWF Datentypen
+// SWF datatype
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
-// Bitstream Hilfsklasse
+// Bitstream helper class
// -----------------------------------------------------------------------------
-// Das Parsen von SWF-Dateien erfordert sowohl bitweises Auslesen als auch an
-// Bytegrenzen ausgerichtetes Lesen.
-// Diese Klasse ist speziell dafќr ausgestattet.
+// The parsing of SWF files requires both bitwise readout and on Byte boundaries
+// oriented reading.
+// This class is specially equipped for this.
// -----------------------------------------------------------------------------
class VectorImage::SWFBitStream {
@@ -85,10 +85,10 @@ public:
}
inline int32 getSignedBits(uint bitCount) {
- // Bits einlesen
+ // readout bits
uint32 temp = getBits(bitCount);
- // Falls das Sign-Bit gesetzt ist, den Rest des Rќckgabewertes mit 1-Bits auffќllen (Sign Extension)
+ // If the sign-bit is set, fill the rest of the return value with 1-bit (sign extension)
if (temp & 1 << (bitCount - 1))
return (0xffffffff << bitCount) | temp;
else
@@ -151,28 +151,28 @@ private:
// -----------------------------------------------------------------------------
-// Konstanten und Hilfsfunktionen
+// Constants and utility functions
// -----------------------------------------------------------------------------
namespace {
// -----------------------------------------------------------------------------
-// Konstanten
+// Constants
// -----------------------------------------------------------------------------
-const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // Die hіchste Flash-Dateiversion, die vom Lader akzeptiert wird
+const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // The maximum flash file version that is accepted by the loader
// -----------------------------------------------------------------------------
-// Konvertiert SWF-Rechteckdaten in einem Bitstrom in Common::Rect-Objekte
+// Converts SWF rectangle data in a bit stream in Common::Rect objects
// -----------------------------------------------------------------------------
Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) {
bs.flushByte();
- // Feststellen mit wie vielen Bits die einzelnen Komponenten kodiert sind
+ // Determines how many bits of the single components are encoded
uint32 bitsPerValue = bs.getBits(5);
- // Die einzelnen Komponenten einlesen
+ // Readout the single components
int32 xMin = bs.getSignedBits(bitsPerValue);
int32 xMax = bs.getSignedBits(bitsPerValue);
int32 yMin = bs.getSignedBits(bitsPerValue);
@@ -182,7 +182,7 @@ Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) {
}
// -----------------------------------------------------------------------------
-// Berechnet die Bounding-Box eines BS_VectorImageElement
+// Calculate the bounding box of a BS_VectorImageElement
// -----------------------------------------------------------------------------
Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) {
@@ -214,17 +214,17 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement)
// -----------------------------------------------------------------------------
-// Konstruktion
+// Construction
// -----------------------------------------------------------------------------
VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, const Common::String &fname) : _pixelData(0), _fname(fname) {
success = false;
- // Bitstream-Objekt erzeugen
- // Im Folgenden werden die Dateidaten aus diesem ausgelesen.
+ // Create bitstream object
+ // In the following the file data will be readout of the bitstream object.
SWFBitStream bs(pFileData, fileSize);
- // SWF-Signatur ќberprќfen
+ // Check SWF signature
uint32 signature[3];
signature[0] = bs.getByte();
signature[1] = bs.getByte();
@@ -236,37 +236,37 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co
return;
}
- // Versionsangabe ќberprќfen
+ // Check the version
uint32 version = bs.getByte();
if (version > MAX_ACCEPTED_FLASH_VERSION) {
error("File is of version %d. Highest accepted version is %d.", version, MAX_ACCEPTED_FLASH_VERSION);
return;
}
- // Dateigrіпe auslesen und mit der tatsфchlichen Grіпe vergleichen
+ // Readout filesize and compare with the actual size
uint32 storedFileSize = bs.getUInt32();
if (storedFileSize != fileSize) {
error("File is not a valid SWF-file");
return;
}
- // SWF-Maпe auslesen
+ // readout SWF size
Common::Rect movieRect = flashRectToBSRect(bs);
- // Framerate und Frameanzahl auslesen
+ // Get frame rate and frame count
/* uint32 frameRate = */
bs.getUInt16();
/* uint32 frameCount = */
bs.getUInt16();
- // Tags parsen
- // Da wir uns nur fќr das erste DefineShape-Tag interessieren
+ // Parse tags
+ // Because we are only interested in the first DifneShape-Tag...
bool keepParsing = true;
while (keepParsing) {
- // Tags beginnen immer an Bytegrenzen
+ // Tags always begin on byte boundaries
bs.flushByte();
- // Tagtyp und Lфnge auslesen
+ // Readout tag type and length
uint16 tagTypeAndLength = bs.getUInt16();
uint32 tagType = tagTypeAndLength >> 6;
uint32 tagLength = tagTypeAndLength & 0x3f;
@@ -286,13 +286,13 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co
success = parseDefineShape(3, bs);
return;
default:
- // Unbekannte Tags ignorieren
+ // Ignore unknown tags
bs.skipBytes(tagLength);
}
}
- // Die Ausfќhrung darf nicht an dieser Stelle ankommen: Entweder es wird ein Shape gefunden, dann wird die Funktion mit vorher verlassen, oder
- // es wird keines gefunden, dann tritt eine Exception auf sobald ќber das Ende der Datei hinaus gelesen wird.
+ // The execution must not arrive at this point: Either a shape is found, then the function will be leaved before, or it is found none, then
+ // an exception occurs as soon as it is read beyond of the end of file.
assert(false);
}
@@ -336,13 +336,13 @@ ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, in
bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
/*uint32 shapeID = */bs.getUInt16();
- // Bounding Box auslesen
+ // readout bounding box
_boundingBox = flashRectToBSRect(bs);
- // Erstes Image-Element erzeugen
+ // create first image element
_elements.resize(1);
- // Styles einlesen
+ // read styles
uint numFillBits;
uint numLineBits;
if (!parseStyles(shapeType, bs, numFillBits, numLineBits))
@@ -352,7 +352,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
uint fillStyle0 = 0;
uint fillStyle1 = 0;
- // Shaperecord parsen
+ // parse shaperecord
// ------------------
double curX = 0;
@@ -367,7 +367,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
// Non-Edge Record
if (typeFlag == 0) {
- // Feststellen welche Parameter gesetzt werden
+ // Determines which parameters are set
uint32 stateNewStyles = bs.getBits(1);
uint32 stateLineStyle = bs.getBits(1);
uint32 stateFillStyle1 = bs.getBits(1);
@@ -378,10 +378,10 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
uint prevFillStyle0 = fillStyle0;
uint prevFillStyle1 = fillStyle1;
- // End der Shape-Definition erreicht?
+ // End of the shape definition is reached?
if (!stateNewStyles && !stateLineStyle && !stateFillStyle0 && !stateFillStyle1 && !stateMoveTo) {
endOfShapeDiscovered = true;
- // Parameter dekodieren
+ // Decode parameters
} else {
if (stateMoveTo) {
uint32 moveToBits = bs.getBits(5);
@@ -410,7 +410,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
numLineBits = 0;
}
- // Ein neuen Pfad erzeugen, es sei denn, es wurden nur neue Styles definiert
+ // Create a new path, unless there were only defined new styles
if (stateLineStyle || stateFillStyle0 || stateFillStyle1 || stateMoveTo) {
// Store previous curve if any
if (bezNodes) {
@@ -426,15 +426,15 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
}
if (stateNewStyles) {
- // An dieser Stelle werden in Flash die alten Style-Definitionen verworfen und mit den neuen ќberschrieben.
- // Es wird ein neues Element begonnen.
+ // The old style definitions will be discarded and overwritten with the new at this point in Flash.
+ // A new element will be started with a new element.
_elements.resize(_elements.size() + 1);
if (!parseStyles(shapeType, bs, numFillBits, numLineBits))
return false;
}
}
} else {
- // Edge Record
+ // Edge record
uint32 edgeFlag = bs.getBits(1);
uint32 numBits = bs.getBits(4) + 2;
@@ -499,7 +499,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
free(bez);
- // Bounding-Boxes der einzelnen Elemente berechnen
+ // Calculate the bounding boxes of each element
Common::Array<VectorImageElement>::iterator it = _elements.begin();
for (; it != _elements.end(); ++it)
it->_boundingBox = CalculateBoundingBox(*it);
@@ -513,16 +513,16 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBits, uint &numLineBits) {
bs.flushByte();
- // Fillstyles parsen
+ // Parse fill styles
// -----------------
- // Anzahl an Fillstyles bestimmen
+ // Determine number of fill styles
uint fillStyleCount = bs.getByte();
if (fillStyleCount == 0xff)
fillStyleCount = bs.getUInt16();
- // Alle Fillstyles einlesen, falls ein Fillstyle mit Typ != 0 gefunden wird, wird das Parsen abgebrochen.
- // Es wird nur "solid fill" (Typ 0) unterstќtzt.
+ // Readout all fill styles. If a fill style with Typ != 0 is found, the parsing is aborted.
+ // Only "solid fill" (Typ 0) is supported.
_elements.back()._fillStyles.reserve(fillStyleCount);
for (uint i = 0; i < fillStyleCount; ++i) {
byte type = bs.getByte();
@@ -543,15 +543,15 @@ bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBit
_elements.back()._fillStyles.push_back(color);
}
- // Linestyles parsen
+ // Line styles parsen
// -----------------
- // Anzahl an Linestyles bestimmen
+ // Determine number of line styles
uint lineStyleCount = bs.getByte();
if (lineStyleCount == 0xff)
lineStyleCount = bs.getUInt16();
- // Alle Linestyles einlesen
+ // Readout all line styles
_elements.back()._lineStyles.reserve(lineStyleCount);
for (uint i = 0; i < lineStyleCount; ++i) {
double width = bs.getUInt16();
@@ -569,7 +569,7 @@ bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBit
_elements.back()._lineStyles.push_back(VectorImageElement::LineStyleType(width, color));
}
- // Bitbreite fќr die folgenden Styleindizes auslesen
+ // Readout the bit width for the following style indices
numFillBits = bs.getBits(4);
numLineBits = bs.getBits(4);
@@ -608,11 +608,11 @@ bool VectorImage::blit(int posX, int posY,
static int oldWidth = -2;
static int oldHeight = -2;
- // Falls Breite oder Hіhe 0 sind, muss nichts dargestellt werden.
+ // If width or height to 0, nothing needs to be shown.
if (width == 0 || height == 0)
return true;
- // Feststellen, ob das alte Bild im Cache nicht wiederbenutzt werden kann und neu Berechnet werden muss
+ // Determine if the old image in the cache can not be reused and must be recalculated
if (!(oldThis == this && oldWidth == width && oldHeight == height)) {
render(width, height);
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp
index 7587aab4e5..e8acd08909 100644
--- a/engines/sword25/gfx/image/vectorimagerenderer.cpp
+++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp
@@ -48,7 +48,7 @@
namespace Sword25 {
-void art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) {
+void art_rgb_fill_run1(byte *buf, byte r, byte g, byte b, int n) {
int i;
if (r == g && g == b && r == 255) {
@@ -62,7 +62,7 @@ void art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) {
}
}
-void art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) {
+void art_rgb_run_alpha1(byte *buf, byte r, byte g, byte b, int alpha, int n) {
int i;
int v;
@@ -82,8 +82,8 @@ typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
struct _ArtRgbSVPAlphaData {
int alphatab[256];
- art_u8 r, g, b, alpha;
- art_u8 *buf;
+ byte r, g, b, alpha;
+ byte *buf;
int rowstride;
int x0, x1;
};
@@ -91,12 +91,12 @@ struct _ArtRgbSVPAlphaData {
static void art_rgb_svp_alpha_callback1(void *callback_data, int y,
int start, ArtSVPRenderAAStep *steps, int n_steps) {
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
- art_u8 *linebuf;
+ byte *linebuf;
int run_x0, run_x1;
- art_u32 running_sum = start;
+ uint32 running_sum = start;
int x0, x1;
int k;
- art_u8 r, g, b;
+ byte r, g, b;
int *alphatab;
int alpha;
@@ -146,12 +146,12 @@ static void art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y,
int start,
ArtSVPRenderAAStep *steps, int n_steps) {
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
- art_u8 *linebuf;
+ byte *linebuf;
int run_x0, run_x1;
- art_u32 running_sum = start;
+ uint32 running_sum = start;
int x0, x1;
int k;
- art_u8 r, g, b;
+ byte r, g, b;
int *alphatab;
int alpha;
@@ -216,7 +216,7 @@ static void art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y,
void art_rgb_svp_alpha1(const ArtSVP *svp,
int x0, int y0, int x1, int y1,
uint32 color,
- art_u8 *buf, int rowstride) {
+ byte *buf, int rowstride) {
ArtRgbSVPAlphaData data;
byte r, g, b, alpha;
int i;
@@ -320,7 +320,7 @@ ArtVpath *art_vpath_reverse_free(ArtVpath *a) {
return dest;
}
-void drawBez(ArtBpath *bez1, ArtBpath *bez2, art_u8 *buffer, int width, int height, int deltaX, int deltaY, double scaleX, double scaleY, double penWidth, unsigned int color) {
+void drawBez(ArtBpath *bez1, ArtBpath *bez2, byte *buffer, int width, int height, int deltaX, int deltaY, double scaleX, double scaleY, double penWidth, unsigned int color) {
ArtVpath *vec = NULL;
ArtVpath *vec1 = NULL;
ArtVpath *vec2 = NULL;
diff --git a/engines/sword25/math/geometry_script.cpp b/engines/sword25/math/geometry_script.cpp
index 6562a0f0a5..4b5e0550fe 100644
--- a/engines/sword25/math/geometry_script.cpp
+++ b/engines/sword25/math/geometry_script.cpp
@@ -51,27 +51,6 @@ namespace Sword25 {
#define REGION_CLASS_NAME "Geo.Region"
#define WALKREGION_CLASS_NAME "Geo.WalkRegion"
-// How luaL_checkudata, only without that no error is generated.
-static void *my_checkudata(lua_State *L, int ud, const char *tname) {
- int top = lua_gettop(L);
-
- void *p = lua_touserdata(L, ud);
- if (p != NULL) { /* value is a userdata? */
- if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
- // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
- LuaBindhelper::getMetatable(L, tname);
- /* does it have the correct mt? */
- if (lua_rawequal(L, -1, -2)) {
- lua_settop(L, top);
- return p;
- }
- }
- }
-
- lua_settop(L, top);
- return NULL;
-}
-
static void newUintUserData(lua_State *L, uint value) {
void *userData = lua_newuserdata(L, sizeof(value));
memcpy(userData, &value, sizeof(value));
@@ -276,9 +255,9 @@ static const luaL_reg GEO_FUNCTIONS[] = {
static Region *checkRegion(lua_State *L) {
// The first parameter must be of type 'userdata', and the Metatable class Geo.Region or Geo.WalkRegion
- uint *regionHandlePtr;
- if ((regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, REGION_CLASS_NAME))) != 0 ||
- (regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
+ uint *regionHandlePtr = reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, REGION_CLASS_NAME));
+ if (regionHandlePtr != 0 ||
+ (regionHandlePtr = reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return RegionRegistry::instance().resolveHandle(*regionHandlePtr);
} else {
luaL_argcheck(L, 0, 1, "'" REGION_CLASS_NAME "' expected");
@@ -398,7 +377,7 @@ static const luaL_reg REGION_METHODS[] = {
static WalkRegion *checkWalkRegion(lua_State *L) {
// The first parameter must be of type 'userdate', and the Metatable class Geo.WalkRegion
uint regionHandle;
- if ((regionHandle = *reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
+ if ((regionHandle = *reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return reinterpret_cast<WalkRegion *>(RegionRegistry::instance().resolveHandle(regionHandle));
} else {
luaL_argcheck(L, 0, 1, "'" WALKREGION_CLASS_NAME "' expected");
diff --git a/engines/sword25/script/luabindhelper.cpp b/engines/sword25/script/luabindhelper.cpp
index 5ff9708b95..03a1802a04 100644
--- a/engines/sword25/script/luabindhelper.cpp
+++ b/engines/sword25/script/luabindhelper.cpp
@@ -303,6 +303,27 @@ bool LuaBindhelper::getMetatable(lua_State *L, const Common::String &tableName)
return true;
}
+// Like luaL_checkudata, only without that no error is generated.
+void *LuaBindhelper::my_checkudata(lua_State *L, int ud, const char *tname) {
+ int top = lua_gettop(L);
+
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
+ LuaBindhelper::getMetatable(L, tname);
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_settop(L, top);
+ return p;
+ }
+ }
+ }
+
+ lua_settop(L, top);
+ return NULL;
+}
+
+
bool LuaBindhelper::createTable(lua_State *L, const Common::String &tableName) {
const char *partBegin = tableName.c_str();
diff --git a/engines/sword25/script/luabindhelper.h b/engines/sword25/script/luabindhelper.h
index dc45104d53..94f52743f3 100644
--- a/engines/sword25/script/luabindhelper.h
+++ b/engines/sword25/script/luabindhelper.h
@@ -110,6 +110,8 @@ public:
static bool getMetatable(lua_State *L, const Common::String &tableName);
+ static void *my_checkudata(lua_State *L, int ud, const char *tname);
+
private:
static bool createTable(lua_State *L, const Common::String &tableName);
};
diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp
index 55b9aa340d..aac21f4b55 100644
--- a/engines/sword25/sword25.cpp
+++ b/engines/sword25/sword25.cpp
@@ -56,6 +56,8 @@ const char *const DEFAULT_SCRIPT_FILE = "/system/boot.lua";
Sword25Engine::Sword25Engine(OSystem *syst, const ADGameDescription *gameDesc):
Engine(syst),
_gameDescription(gameDesc) {
+ // Setup mixer
+ syncSoundSettings();
DebugMan.addDebugChannel(kDebugScript, "Script", "Script debug level");
DebugMan.addDebugChannel(kDebugScript, "Scripts", "Script debug level");
diff --git a/engines/sword25/util/lua/lmathlib.cpp b/engines/sword25/util/lua/lmathlib.cpp
index ed50539f1f..7e64d75789 100644
--- a/engines/sword25/util/lua/lmathlib.cpp
+++ b/engines/sword25/util/lua/lmathlib.cpp
@@ -6,6 +6,11 @@
#include <stdlib.h>
+// MSVC does not define M_PI, M_SQRT2 and other math defines by default.
+// _USE_MATH_DEFINES must be defined in order to have these defined, thus
+// we enable it here. For more information, check:
+// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=VS.100).aspx
+#define _USE_MATH_DEFINES
#include <math.h>
#define lmathlib_c
@@ -16,12 +21,7 @@
#include "lauxlib.h"
#include "lualib.h"
-
-#undef PI
-#define PI (3.14159265358979323846)
-#define RADIANS_PER_DEGREE (PI/180.0)
-
-
+#define RADIANS_PER_DEGREE (M_PI/180.0)
static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
@@ -250,7 +250,7 @@ static const luaL_Reg mathlib[] = {
*/
LUALIB_API int luaopen_math (lua_State *L) {
luaL_register(L, LUA_MATHLIBNAME, mathlib);
- lua_pushnumber(L, PI);
+ lua_pushnumber(L, M_PI);
lua_setfield(L, -2, "pi");
#if defined(MACOSX) && defined(__GNUC__) && ! defined( __XLC__ )
// WORKAROUND for a bug in the Mac OS X 10.2.8 SDK. It defines
diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp
index 4b37576846..f9756b5b91 100644
--- a/engines/teenagent/scene.cpp
+++ b/engines/teenagent/scene.cpp
@@ -1177,12 +1177,10 @@ bool Scene::processEventQueue() {
void Scene::setPalette(unsigned mul) {
//debug(0, "setPalette(%u)", mul);
- byte p[1024];
+ byte p[3*256];
- memset(p, 0, 1024);
- for (int i = 0; i < 256; ++i) {
- for (int c = 0; c < 3; ++c)
- p[i * 4 + c] = (unsigned)palette[i * 3 + c] * mul;
+ for (int i = 0; i < 3*256; ++i) {
+ p[i] = (unsigned)palette[i] * mul;
}
_system->getPaletteManager()->setPalette(p, 0, 256);
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index a492237adb..e66de70079 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -290,18 +290,12 @@ bool TeenAgentEngine::showCDLogo() {
return true;
byte bg[0xfa00];
- byte palette[0x400];
+ byte palette[3*256];
cdlogo.read(bg, sizeof(bg));
- memset(palette, 0, sizeof(palette));
-
- for(uint c = 0; c < 0x100; ++c) {
- uint idx = c * 4;
- cdlogo.read(palette + idx, 3);
- palette[idx] *= 4;
- palette[idx + 1] *= 4;
- palette[idx + 2] *= 4;
- }
+ cdlogo.read(palette, sizeof(palette));
+ for (uint c = 0; c < 3*256; ++c)
+ palette[c] *= 4;
_system->getPaletteManager()->setPalette(palette, 0, 0x100);
_system->copyRectToScreen(bg, 320, 0, 0, 320, 200);
_system->updateScreen();
@@ -323,22 +317,16 @@ bool TeenAgentEngine::showLogo() {
return true;
byte bg[0xfa00];
- byte palette[0x400];
+ byte palette[3*256];
Common::ScopedPtr<Common::SeekableReadStream> frame(logo.getStream(1));
if (!frame)
return true;
frame->read(bg, sizeof(bg));
- memset(palette, 0, sizeof(palette));
-
- for(uint c = 0; c < 0x100; ++c) {
- uint idx = c * 4;
- frame->read(palette + idx, 3);
- palette[idx] *= 4;
- palette[idx + 1] *= 4;
- palette[idx + 2] *= 4;
- }
+ frame->read(palette, sizeof(palette));
+ for (uint c = 0; c < 3*256; ++c)
+ palette[c] *= 4;
_system->getPaletteManager()->setPalette(palette, 0, 0x100);
uint n = logo.fileCount();
@@ -375,16 +363,12 @@ bool TeenAgentEngine::showMetropolis() {
FilePack varia;
varia.open("varia.res");
- byte palette[0x400];
- memset(palette, 0, sizeof(palette));
+ byte palette[3*256];
{
Common::ScopedPtr<Common::SeekableReadStream> s(varia.getStream(5));
- for(uint c = 0; c < 0x400; c += 4) {
- s->read(palette + c, 3);
+ s->read(palette, sizeof(palette));
+ for (uint c = 0; c < 3*256; ++c)
palette[c] *= 4;
- palette[c + 1] *= 4;
- palette[c + 2] *= 4;
- }
}
_system->getPaletteManager()->setPalette(palette, 0, 0x100);
diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp
index ed51b33e94..588aad8248 100644
--- a/engines/testbed/graphics.cpp
+++ b/engines/testbed/graphics.cpp
@@ -38,7 +38,7 @@
namespace Testbed {
-byte GFXTestSuite::_palette[256 * 4] = {0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0};
+byte GFXTestSuite::_palette[256 * 3] = {0, 0, 0, 255, 255, 255, 255, 255, 255};
GFXTestSuite::GFXTestSuite() {
// Initialize color palettes
@@ -79,12 +79,12 @@ GFXTestSuite::GFXTestSuite() {
}
void GFXTestSuite::setCustomColor(uint r, uint g, uint b) {
- _palette[8] = r;
- _palette[9] = g;
- _palette[10] = b;
+ _palette[6] = r;
+ _palette[7] = g;
+ _palette[8] = b;
// Set colorNum kColorSpecial with a special color.
- int absIndx = kColorSpecial * 4;
+ int absIndx = kColorSpecial * 3;
_palette[absIndx + 1] = 173;
_palette[absIndx + 2] = 255;
_palette[absIndx + 3] = 47;
@@ -94,12 +94,12 @@ void GFXTestSuite::setCustomColor(uint r, uint g, uint b) {
// Helper functions used by GFX tests
void GFXtests::initMousePalette() {
- byte palette[3 * 4]; // Black, white and yellow
+ byte palette[3 * 3]; // Black, white and yellow
palette[0] = palette[1] = palette[2] = 0;
- palette[4] = palette[5] = palette[6] = 255;
- palette[8] = palette[9] = 255;
- palette[10] = 0;
+ palette[3] = palette[4] = palette[5] = 255;
+ palette[6] = palette[7] = 255;
+ palette[8] = 0;
CursorMan.replaceCursorPalette(palette, 0, 3);
}
@@ -229,16 +229,16 @@ void rotatePalette(byte *palette, int size) {
// Rotate the colors starting from address palette "size" times
// take a temporary palette color
- byte tColor[4] = {0};
+ byte tColor[3] = {0};
// save first color in it.
- memcpy(tColor, &palette[0], 4 * sizeof(byte));
+ memcpy(tColor, &palette[0], 3 * sizeof(byte));
// Move each color upward by 1
for (int i = 0; i < size - 1; i++) {
- memcpy(&palette[i * 4], &palette[(i + 1) * 4], 4 * sizeof(byte));
+ memcpy(&palette[i * 3], &palette[(i + 1) * 3], 3 * sizeof(byte));
}
// Assign last color to tcolor
- memcpy(&palette[(size - 1) * 4], tColor, 4 * sizeof(byte));
+ memcpy(&palette[(size - 1) * 3], tColor, 3 * sizeof(byte));
}
/**
@@ -360,7 +360,7 @@ void GFXtests::drawEllipse(int cx, int cy, int a, int b) {
// Illuminate the points lying on ellipse
- for (theta = 0; theta <= PI / 2; theta += PI / 360) {
+ for (theta = 0; theta <= M_PI / 2; theta += M_PI / 360) {
x = (int)(b * sin(theta) + 0.5);
y = (int)(a * cos(theta) + 0.5);
@@ -968,14 +968,14 @@ TestExitStatus GFXtests::paletteRotation() {
Testsuite::clearEntireScreen();
// Use 256 colors
- byte palette[256 * 4] = {0};
+ byte palette[256 * 3] = {0};
int r, g, b;
int colIndx;
for (int i = 0; i < 256; i++) {
HSVtoRGB(r, g, b, i, 1, 1);
- colIndx = i * 4;
+ colIndx = i * 3;
palette[colIndx] = r;
palette[colIndx + 1] = g;
palette[colIndx + 2] = b;
diff --git a/engines/testbed/graphics.h b/engines/testbed/graphics.h
index 4ab4ba65ab..a4e698b44c 100644
--- a/engines/testbed/graphics.h
+++ b/engines/testbed/graphics.h
@@ -79,14 +79,14 @@ public:
private:
/**
- * A Palette consists of 4 components RGBA.
+ * A Palette consists of 3 components RGB.
* As of now we only take 3 colors
* 0 (R:0, G:0, B:0) Black (kColorBlack)
* 1 (R:255, G:255, B:255) White (kColorWhite)
* 2 (R:255, G:255, B:255) your customized color (by default white) (kColorCustom)
* The remaining values are zero
*/
- static byte _palette[256 * 4];
+ static byte _palette[256 * 3];
};
} // End of namespace Testbed
diff --git a/engines/testbed/midi.cpp b/engines/testbed/midi.cpp
index 673f5d8547..7ec24aa670 100644
--- a/engines/testbed/midi.cpp
+++ b/engines/testbed/midi.cpp
@@ -96,7 +96,7 @@ TestExitStatus MidiTests::playMidiMusic() {
int errCode = driver->open();
if (errCode) {
- Common::String errMsg = driver->getErrorName(errCode);
+ Common::String errMsg = MidiDriver::getErrorName(errCode);
Testsuite::writeOnScreen(errMsg, Common::Point(0, 100));
Testsuite::logPrintf("Error! %s", errMsg.c_str());
return kTestFailed;
diff --git a/engines/tinsel/background.cpp b/engines/tinsel/background.cpp
index 560216aadb..f895ecd2da 100644
--- a/engines/tinsel/background.cpp
+++ b/engines/tinsel/background.cpp
@@ -39,9 +39,6 @@ namespace Tinsel {
// current background
const BACKGND *pCurBgnd = NULL;
-// FIXME: Not yet used
-static bool bEntireRedraw;
-
/**
* Called to initialise a background.
* @param pBgnd Pointer to data struct for current background
@@ -257,9 +254,4 @@ void DrawBackgnd() {
ResetClipRect();
}
-void ForceEntireRedraw() {
- bEntireRedraw = true;
-}
-
-
} // End of namespace Tinsel
diff --git a/engines/tinsel/background.h b/engines/tinsel/background.h
index 81b490488e..d0b27e6e40 100644
--- a/engines/tinsel/background.h
+++ b/engines/tinsel/background.h
@@ -110,8 +110,6 @@ OBJECT *GetBgObject();
SCNHANDLE BgPal();
-void ForceEntireRedraw();
-
int BgWidth();
int BgHeight();
diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp
index 3f56288aca..b5b84ceaee 100644
--- a/engines/tinsel/bmv.cpp
+++ b/engines/tinsel/bmv.cpp
@@ -1025,7 +1025,6 @@ bool BMVPlayer::DoSoundFrame() {
void BMVPlayer::CopyMovieToScreen() {
// Not if not up and running yet!
if (!screenBuffer || (currentFrame == 0)) {
- ForceEntireRedraw();
DrawBackgnd();
return;
}
@@ -1046,21 +1045,6 @@ void BMVPlayer::CopyMovieToScreen() {
}
/**
- * LookAtBuffers
- */
-void BMVPlayer::LookAtBuffers() {
- // FIXME: What's the point of this function???
- // Maybe to ensure the relevant data is loaded into cache by the CPU?
- static int junk; // FIXME: Avoid non-const global vars
- int i;
-
- if (bigBuffer) {
- for (i = 0; i < NUM_SLOTS; i++)
- junk += bigBuffer[i*SLOT_SIZE];
- }
-}
-
-/**
* Handles playback of any active movie. Called from the foreground 24 times a second.
*/
void BMVPlayer::FettleBMV() {
@@ -1078,8 +1062,6 @@ void BMVPlayer::FettleBMV() {
return;
}
- LookAtBuffers();
-
if (!stream.isOpen()) {
int i;
diff --git a/engines/tinsel/bmv.h b/engines/tinsel/bmv.h
index 2644504cab..99a43e0740 100644
--- a/engines/tinsel/bmv.h
+++ b/engines/tinsel/bmv.h
@@ -151,7 +151,6 @@ private:
bool MaintainBuffer();
bool DoBMVFrame();
bool DoSoundFrame();
- void LookAtBuffers();
};
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 22e8806e7e..70bf398baf 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -280,11 +280,9 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &
ADGameDescList matched;
int maxFilesMatched = 0;
- bool gotAnyMatchesWithAllFiles = false;
// MD5 based matching
- uint i;
- for (i = 0, g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) {
+ for (g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) {
if (strcmp(g->desc.gameid, "dw2") != 0)
continue;
@@ -327,9 +325,6 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &
}
}
- if (allFilesPresent)
- gotAnyMatchesWithAllFiles = true;
-
if (!fileMissing) {
// Count the number of matching files. Then, only keep those
// entries which match a maximal amount of files.
diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp
index 6e30caf006..ab606f3159 100644
--- a/engines/tinsel/drives.cpp
+++ b/engines/tinsel/drives.cpp
@@ -38,7 +38,6 @@ namespace Tinsel {
// FIXME: Avoid non-const global vars
char currentCD = '1';
-static uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 };
static bool bChangingCD = false;
static char nextCD = '\0';
@@ -75,6 +74,8 @@ int GetCurrentCD() {
return (currentCD - '1' + 1);
}
+static const uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 };
+
void SetCD(int flags) {
if (flags & cdFlags[currentCD - '1'])
return;
diff --git a/engines/tinsel/dw.h b/engines/tinsel/dw.h
index 8bd7ca1a4e..aed4c50408 100644
--- a/engines/tinsel/dw.h
+++ b/engines/tinsel/dw.h
@@ -42,8 +42,6 @@ typedef int HPOLYGON;
#define LF_CHAR '\x0a' // line feed
// file names
-#define SAMPLE_FILE "english.smp" // all samples
-#define SAMPLE_INDEX "english.idx" // sample index filename
#define MIDI_FILE "midi.dat" // all MIDI sequences
#define INDEX_FILENAME "index" // name of index file
#define PSX_INDEX_FILENAME "index.dat" // name of index file in psx version
diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp
index a48fd2ca1f..f2db42bede 100644
--- a/engines/tinsel/handle.cpp
+++ b/engines/tinsel/handle.cpp
@@ -65,8 +65,6 @@ enum {
fLoaded = 0x20000000L ///< set when file data has been loaded
};
#define FSIZE_MASK 0x00FFFFFFL ///< mask to isolate the filesize
-#define MALLOC_MASK 0xFF000000L ///< mask to isolate the memory allocation flags
-//#define HANDLEMASK 0xFF800000L ///< get handle of address
//----------------- LOCAL GLOBAL DATA --------------------
@@ -80,7 +78,6 @@ static uint numHandles = 0;
static uint32 cdPlayHandle = (uint32)-1;
-static int cdPlayFileNum, cdPlaySceneNum;
static SCNHANDLE cdBaseHandle = 0, cdTopHandle = 0;
static Common::File *cdGraphStream = 0;
@@ -235,7 +232,7 @@ void LoadCDGraphData(MEMHANDLE *pH) {
// clear the loading flag
// pH->filesize &= ~fLoading;
- if (bytes != ((cdTopHandle-cdBaseHandle) & OFFSETMASK))
+ if (bytes != ((cdTopHandle - cdBaseHandle) & OFFSETMASK))
// file is corrupt
error(FILE_READ_ERROR, "CD play file");
}
@@ -248,7 +245,7 @@ void LoadCDGraphData(MEMHANDLE *pH) {
* @param next Handle of end of range + 1
*/
void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) {
- if (cdPlayFileNum == cdPlaySceneNum && start == cdBaseHandle)
+ if (start == cdBaseHandle)
return;
OpenCDGraphFile();
@@ -264,7 +261,6 @@ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) {
}
void SetCdPlaySceneDetails(int fileNum, const char *fileName) {
- cdPlaySceneNum = fileNum;
strcpy(szCdPlayFile, fileName);
}
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 29d4dbc92d..49eacce9ae 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -65,10 +65,6 @@ struct SOUND_BUFFER {
// FIXME: Avoid non-const global vars
-// get set when music driver is installed
-//static MDI_DRIVER *mDriver;
-//static HSEQUENCE mSeqHandle;
-
// MIDI buffer
static SOUND_BUFFER midiBuffer = { 0, 0 };
@@ -115,26 +111,6 @@ static const int enhancedAudioSCNVersion[] = {
97, 98, 99, 99 // 151-154
};
-// TODO. This mapping is wrong
-static const int enhancedAudioSCNVersionALT[] = {
- 301, 302, 2, 1, 1, 301, 302, 3, 3, 4, // 1-10
- 4, 5, 6, 1, 7, 8, 9, 10, 8, 11, // 11-20
- 11, 12, 13, 13, 13, 13, 13, 14, 13, 13, // 21-30
- 15, 16, 17, 15, 18, 19, 20, 338, 21, 21, // 31-40
- 341, 342, 22, 22, 23, 24, 25, 26, 27, 28, // 41-50
- 29, 30, 31, 32, 33, 34, 35, 35, 36, 37, // 51-60
- 38, 39, 39, 39, 39, 40, 39, 41, 41, 42, // 61-70
- 43, 42, 44, 45, 41, 46, 48, 47, 48, 49, // 71-80
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 81-90
- 60, 61, 62, 63, 61, 64, 65, 66, 67, 68, // 91-100
- 69, 70, 68, 71, 72, 73, 74, 75, 12, 76, // 101-110
- 77, 78, 79, 80, 4, 4, 82, 83, 77, 4, // 111-120
- 84, 85, 86, 3124, 88, 89, 90, 88, 2, 2, // 121-130
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 131-140
- 3142, 91, 92, 93, 94, 94, 95, 96, 52, 4, // 141-150
- 97, 98, 99 // 151-153
-};
-
int GetTrackNumber(SCNHANDLE hMidi) {
for (int i = 0; i < ARRAYSIZE(midiOffsets); i++)
if (midiOffsets[i] == hMidi)
@@ -172,18 +148,18 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) {
// the index and length of the last tune loaded
static uint32 dwLastMidiIndex = 0; // FIXME: Avoid non-const global vars
- //static uint32 dwLastSeqLen;
-
uint32 dwSeqLen = 0; // length of the sequence
// Support for external music from the music enhancement project
if (_vm->getFeatures() & GF_ENHANCED_AUDIO_SUPPORT) {
int trackNumber = GetTrackNumber(dwFileOffset);
+ // Track 8 has been removed in the German CD re-release "Neon Edition"
+ if ((_vm->getFeatures() & GF_ALT_MIDI) && trackNumber >= 8)
+ trackNumber++;
+
int track = 0;
if (trackNumber >= 0) {
- if (_vm->getFeatures() & GF_ALT_MIDI)
- track = enhancedAudioSCNVersionALT[trackNumber];
- else if (_vm->getFeatures() & GF_SCNFILES)
+ if (_vm->getFeatures() & GF_SCNFILES)
track = enhancedAudioSCNVersion[trackNumber];
else
track = enhancedAudioGRAVersion[trackNumber];
@@ -404,112 +380,43 @@ void DeleteMidiBuffer() {
midiBuffer.pDat = NULL;
}
-MidiMusicPlayer::MidiMusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false) {
- memset(_channel, 0, sizeof(_channel));
- memset(_channelVolume, 0, sizeof(_channelVolume));
- _masterVolume = 0;
- this->open();
- _xmidiParser = MidiParser::createParser_XMIDI();
-}
-
-MidiMusicPlayer::~MidiMusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _xmidiParser->setMidiDriver(NULL);
- delete _xmidiParser;
-}
-
-void MidiMusicPlayer::setVolume(int volume) {
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
-
- if (_masterVolume == volume)
- return;
+MidiMusicPlayer::MidiMusicPlayer() {
+ MidiPlayer::createDriver();
- _masterVolume = volume;
-
- Common::StackLock lock(_mutex);
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
+ _driver->setTimerCallback(this, &timerCallback);
}
}
-int MidiMusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
+void MidiMusicPlayer::setVolume(int volume) {
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
-void MidiMusicPlayer::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
+ Audio::MidiPlayer::setVolume(volume);
}
void MidiMusicPlayer::send(uint32 b) {
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xFFF0) == 0x007BB0) {
- // Only respond to All Notes Off if this channel
- // has currently been allocated
- if (!_channel[b & 0x0F])
- return;
- }
-
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel]) {
- _channel[channel]->send(b);
+ Audio::MidiPlayer::send(b);
+ byte channel = (byte)(b & 0x0F);
+ if (_channelsTable[channel]) {
if ((b & 0xFFF0) == 0x0079B0) {
// We've just Reset All Controllers, so we need to
// re-adjust the volume. Otherwise, volume is reset to
// default whenever the music changes.
- _channel[channel]->send(0x000007B0 | (((_channelVolume[channel] * _masterVolume) / 255) << 16) | channel);
+ _channelsTable[channel]->send(0x000007B0 | (((_channelsVolume[channel] * _masterVolume) / 255) << 16) | channel);
}
}
}
-void MidiMusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stop();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiMusicPlayer::onTimer(void *refCon) {
- MidiMusicPlayer *music = (MidiMusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
-
- if (music->_isPlaying)
- music->_parser->onTimer();
-}
-
void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying)
return;
@@ -527,8 +434,8 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) {
// Load XMID resource data
- if (_xmidiParser->loadMusic(midiData, size)) {
- MidiParser *parser = _xmidiParser;
+ MidiParser *parser = MidiParser::createParser_XMIDI();
+ if (parser->loadMusic(midiData, size)) {
parser->setTrack(0);
parser->setMidiDriver(this);
parser->setTimerRate(getBaseTempo());
@@ -537,18 +444,10 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) {
_parser = parser;
- _looping = loop;
+ _isLooping = loop;
_isPlaying = true;
- }
-}
-
-void MidiMusicPlayer::stop() {
- Common::StackLock lock(_mutex);
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
+ } else {
+ delete parser;
}
}
@@ -566,7 +465,6 @@ PCMMusicPlayer::PCMMusicPlayer() {
_silenceSamples = 0;
_curChunk = 0;
- _fileName = 0;
_state = S_IDLE;
_mState = S_IDLE;
_scriptNum = -1;
@@ -589,15 +487,13 @@ PCMMusicPlayer::PCMMusicPlayer() {
PCMMusicPlayer::~PCMMusicPlayer() {
_vm->_mixer->stopHandle(_handle);
-
- delete[] _fileName;
}
void PCMMusicPlayer::startPlay(int id) {
- if (!_fileName)
+ if (_filename.empty())
return;
- debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _fileName, id);
+ debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _filename.c_str(), id);
Common::StackLock slock(_mutex);
@@ -712,8 +608,7 @@ void PCMMusicPlayer::setMusicSceneDetails(SCNHANDLE hScript,
_hScript = hScript;
_hSegment = hSegment;
- _fileName = new char[strlen(fileName) + 1];
- strcpy(_fileName, fileName);
+ _filename = fileName;
// Start scene with music not dimmed
_dimmed = false;
@@ -869,19 +764,19 @@ bool PCMMusicPlayer::getNextChunk() {
sampleLength = FROM_LE_32(musicSegments[snum].sampleLength);
sampleCLength = (((sampleLength + 63) & ~63)*33)/64;
- if (!file.open(_fileName))
- error(CANNOT_FIND_FILE, _fileName);
+ if (!file.open(_filename))
+ error(CANNOT_FIND_FILE, _filename.c_str());
file.seek(sampleOffset);
if (file.eos() || file.err() || (uint32)file.pos() != sampleOffset)
- error(FILE_IS_CORRUPT, _fileName);
+ error(FILE_IS_CORRUPT, _filename.c_str());
buffer = (byte *) malloc(sampleCLength);
assert(buffer);
// read all of the sample
if (file.read(buffer, sampleCLength) != sampleCLength)
- error(FILE_IS_CORRUPT, _fileName);
+ error(FILE_IS_CORRUPT, _filename.c_str());
debugC(DEBUG_DETAILED, kTinselDebugMusic, "Creating ADPCM music chunk with size %d, "
"offset %d (script %d.%d)", sampleCLength, sampleOffset,
diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index e2a3b4c2c1..9003e60078 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -28,12 +28,13 @@
#ifndef TINSEL_MUSIC_H
#define TINSEL_MUSIC_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "common/mutex.h"
+class MidiParser;
+
namespace Tinsel {
bool PlayMidiSequence( // Plays the specified MIDI sequence through the sound driver
@@ -60,57 +61,24 @@ SCNHANDLE GetTrackOffset(int trackNumber);
void dumpMusic();
-class MidiMusicPlayer : public MidiDriver {
+class MidiMusicPlayer : public Audio::MidiPlayer {
public:
- MidiMusicPlayer(MidiDriver *driver);
- ~MidiMusicPlayer();
-
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
+ MidiMusicPlayer();
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
+ virtual void setVolume(int volume);
void playXMIDI(byte *midiData, uint32 size, bool loop);
- void stop();
+// void stop();
void pause();
void resume();
- void setLoop(bool loop) { _looping = loop; }
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
// The original sets the "sequence timing" to 109 Hz, whatever that
// means. The default is 120.
-
uint32 getBaseTempo() { return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
-
-protected:
-
- static void onTimer(void *data);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_xmidiParser;
- byte _channelVolume[16];
-
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
};
class PCMMusicPlayer : public Audio::AudioStream {
@@ -180,7 +148,7 @@ protected:
int32 _scriptIndex;
SCNHANDLE _hScript;
SCNHANDLE _hSegment;
- char *_fileName;
+ Common::String _filename;
uint8 _volume;
diff --git a/engines/tinsel/palette.cpp b/engines/tinsel/palette.cpp
index 7cc6564832..a0ceec54eb 100644
--- a/engines/tinsel/palette.cpp
+++ b/engines/tinsel/palette.cpp
@@ -133,6 +133,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) {
void PalettesToVideoDAC() {
PALQ *pPalQ; // palette Q iterator
VIDEO_DAC_Q *pDACtail = vidDACdata; // set tail pointer
+ byte pal[768];
// while Q is not empty
while (pDAChead != pDACtail) {
@@ -164,8 +165,14 @@ void PalettesToVideoDAC() {
pColours = pDACtail->pal.pRGBarray;
}
+ for (int i = 0; i < pDACtail->numColours; ++i) {
+ pal[i * 3 + 0] = TINSEL_GetRValue(pColours[i]);
+ pal[i * 3 + 1] = TINSEL_GetGValue(pColours[i]);
+ pal[i * 3 + 2] = TINSEL_GetBValue(pColours[i]);
+ }
+
// update the system palette
- g_system->getPaletteManager()->setPalette((const byte *)pColours, pDACtail->destDACindex, pDACtail->numColours);
+ g_system->getPaletteManager()->setPalette(pal, pDACtail->destDACindex, pDACtail->numColours);
// update tail pointer
pDACtail++;
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index c965666e84..3182593a88 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -77,9 +77,6 @@ SRSTATE SRstate = SR_IDLE;
// in DOS_DW.C
extern void syncSCdata(Common::Serializer &s);
-// in DOS_MAIN.C
-//char HardDriveLetter();
-
// in PCODE.C
extern void syncGlobInfo(Common::Serializer &s);
@@ -283,32 +280,6 @@ static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd) {
}
}
-
-/**
- * Called when saving a game to a new file.
- * Generates a new, unique, filename.
- */
-static char *NewName() {
- static char result[FNAMELEN]; // FIXME: Avoid non-const global vars
- int i;
- int ano = 1; // Allocated number
-
- while (1) {
- Common::String fname = _vm->getSavegameFilename(ano);
- strcpy(result, fname.c_str());
-
- for (i = 0; i < numSfiles; i++)
- if (!strcmp(savedFiles[i].name, result))
- break;
-
- if (i == numSfiles)
- break;
- ano++;
- }
-
- return result;
-}
-
/**
* Compare two TimeDate structs to see which one was earlier.
* Returns 0 if they are equal, a negative value if a is lower / first, and
@@ -498,19 +469,37 @@ static bool DoRestore() {
*/
static void DoSave() {
Common::OutSaveFile *f;
- const char *fname;
+ char tmpName[FNAMELEN];
// Next getList() must do its stuff again
NeedLoad = true;
- if (SaveSceneName == NULL)
- SaveSceneName = NewName();
+ if (SaveSceneName == NULL) {
+ // Generate a new unique save name
+ int i;
+ int ano = 1; // Allocated number
+
+ while (1) {
+ Common::String fname = _vm->getSavegameFilename(ano);
+ strcpy(tmpName, fname.c_str());
+
+ for (i = 0; i < numSfiles; i++)
+ if (!strcmp(savedFiles[i].name, tmpName))
+ break;
+
+ if (i == numSfiles)
+ break;
+ ano++;
+ }
+
+ SaveSceneName = tmpName;
+ }
+
+
if (SaveSceneDesc[0] == 0)
SaveSceneDesc = "unnamed";
- fname = SaveSceneName;
-
- f = _vm->getSaveFileMan()->openForSaving(fname);
+ f = _vm->getSaveFileMan()->openForSaving(SaveSceneName);
Common::Serializer s(0, f);
if (f == NULL)
@@ -537,12 +526,14 @@ static void DoSave() {
f->finalize();
delete f;
+ SaveSceneName = NULL; // Invalidate save name
return;
save_failure:
if (f) {
delete f;
- _vm->getSaveFileMan()->removeSavefile(fname);
+ _vm->getSaveFileMan()->removeSavefile(SaveSceneName);
+ SaveSceneName = NULL; // Invalidate save name
}
GUI::MessageDialog dialog("Failed to save game state to file.");
dialog.runModal();
diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp
index 8f0f4771e3..67e0ea9ffd 100644
--- a/engines/tinsel/scene.cpp
+++ b/engines/tinsel/scene.cpp
@@ -112,15 +112,11 @@ struct ENTRANCE_STRUC {
static bool ShowPosition = false; // Set when showpos() has been called
#endif
-SCNHANDLE newestScene = 0;
-
int sceneCtr = 0;
static int initialMyEscape;
static SCNHANDLE SceneHandle = 0; // Current scene handle - stored in case of Save_Scene()
-static bool bWatchingOut = false;
-
SCENE_STRUC tempStruc;
struct TP_INIT {
@@ -180,9 +176,6 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) {
_ctx->myEscape);
CORO_INVOKE_1(Interpret, _ctx->pic);
- if (_ctx->pInit->event == CLOSEDOWN || _ctx->pInit->event == LEAVE_T2)
- bWatchingOut = false;
-
CORO_END_CODE;
}
@@ -193,9 +186,6 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) {
void SendSceneTinselProcess(TINSEL_EVENT event) {
SCENE_STRUC *ss;
- if (event == CLOSEDOWN || event == LEAVE_T2)
- bWatchingOut = true;
-
if (SceneHandle != (SCNHANDLE)NULL) {
ss = (SCENE_STRUC *) FindChunk(SceneHandle, CHUNK_SCENE);
@@ -206,11 +196,8 @@ void SendSceneTinselProcess(TINSEL_EVENT event) {
init.hTinselCode = ss->hSceneScript;
g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init));
- } else if (event == CLOSEDOWN)
- bWatchingOut = false;
+ }
}
- else if (event == CLOSEDOWN)
- bWatchingOut = false;
}
@@ -249,9 +236,6 @@ static void LoadScene(SCNHANDLE scene, int entry) {
assert(ss != NULL);
if (TinselV2) {
- // Handle to scene description
- newestScene = FROM_LE_32(ss->hSceneDesc);
-
// Music stuff
char *cptr = (char *)FindChunk(scene, CHUNK_MUSIC_FILENAME);
assert(cptr);
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index 5fc2820986..a76d26eade 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -530,17 +530,17 @@ void SoundManager::openSampleFiles() {
// Detect format of soundfile by looking at 1st sample-index
switch (TO_BE_32(_sampleIndex[0])) {
- case MKID_BE('MP3 '):
+ case MKTAG('M','P','3',' '):
debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected MP3 sound-data");
_soundMode = kMP3Mode;
break;
- case MKID_BE('OGG '):
+ case MKTAG('O','G','G',' '):
debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected OGG sound-data");
_soundMode = kVorbisMode;
break;
- case MKID_BE('FLAC'):
+ case MKTAG('F','L','A','C'):
debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected FLAC sound-data");
_soundMode = kFLACMode;
break;
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 23335539d1..e1396f9715 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -218,14 +218,17 @@ void KeyboardProcess(CORO_PARAM, const void *) {
continue;
#endif
+ case Common::KEYCODE_1:
case Common::KEYCODE_F1:
// Options dialog
ProcessKeyEvent(PLR_MENU);
continue;
+ case Common::KEYCODE_5:
case Common::KEYCODE_F5:
// Save game
ProcessKeyEvent(PLR_SAVE);
continue;
+ case Common::KEYCODE_7:
case Common::KEYCODE_F7:
// Load game
ProcessKeyEvent(PLR_LOAD);
@@ -856,25 +859,8 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
if (cd_num >= 0)
_system->getAudioCDManager()->openCD(cd_num);
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
- _driver = MidiDriver::createMidi(dev);
- if (native_mt32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _midiMusic = new MidiMusicPlayer(_driver);
+ _midiMusic = new MidiMusicPlayer();
_pcmMusic = new PCMMusicPlayer();
- //_midiMusic->setNativeMT32(native_mt32);
- //_midiMusic->setAdLib(adlib);
-
- if (native_mt32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- _musicVolume = ConfMan.getInt("music_volume");
_sound = new SoundManager(this);
@@ -896,7 +882,6 @@ TinselEngine::~TinselEngine() {
delete _midiMusic;
delete _pcmMusic;
delete _console;
- delete _driver;
_screenSurface.free();
FreeSaveScenes();
FreeTextBuffer();
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 009f6fe26d..5c7a1cdfb2 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -219,9 +219,6 @@ public:
RectList _clipRects;
private:
- //MidiMusicPlayer *_midiMusic;
- int _musicVolume;
-
void NextGameCycle();
void CreateConstProcesses();
void RestartGame();
diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index 2e63d89f37..6004aacead 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -99,7 +99,7 @@ bool Animation::loadAnimation(Common::String file) {
_frames[e]._data = new uint8[decompressedSize];
if (compressedSize < decompressedSize) {
decompressLZSS(imageData, _frames[e]._data, decompressedSize);
- } else {
+ } else {
memcpy(_frames[e]._data, imageData, compressedSize);
}
}
@@ -151,6 +151,8 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int32 xx, int
int32 offsX = 0;
int32 offsY = 0;
+ _vm->addDirtyRect(xx + _x1 + _frames[frame]._x1, yy + _y1 + _frames[frame]._y1, xx + rectX + _x1 + _frames[frame]._x1 , yy + rectY + _y1 + _frames[frame]._y1);
+
if (xx + _x1 + _frames[frame]._x1 < 0) {
offsX = -(xx + _x1 + _frames[frame]._x1);
}
@@ -212,14 +214,14 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
int32 finalWidth = rectX * scale / 1024;
int32 finalHeight = rectY * scale / 1024;
- // compute final x1,y1,x2,y2
+ // compute final x1, y1, x2, y2
int32 xx1 = xx + _x1 + _frames[frame]._x1 * scale / 1024;
int32 yy1 = yy + _y1 + _frames[frame]._y1 * scale / 1024;
int32 xx2 = xx1 + finalWidth;
int32 yy2 = yy1 + finalHeight;
int32 w = _frames[frame]._x2 - _frames[frame]._x1;
-// Strangerke - Commented (not used)
-// int32 h = _frames[frame]._y2 - _frames[frame]._y1;
+
+ _vm->addDirtyRect(xx1, yy1, xx2, yy2);
int32 destPitch = surface.pitch;
int32 destPitchMask = mask->getWidth();
@@ -442,7 +444,6 @@ AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type)
_layerZ = 0;
}
-
void AnimationInstance::render() {
debugC(5, kDebugAnim, "render()");
if (_visible && _animation) {
@@ -574,7 +575,7 @@ void AnimationInstance::getRect(int32 *x1, int32 *y1, int32 *x2, int32 *y2) cons
int32 finalWidth = rectX * _scale / 1024;
int32 finalHeight = rectY * _scale / 1024;
- // compute final x1,y1,x2,y2
+ // compute final x1, y1, x2, y2
*x1 = _x + _animation->_x1 + _animation->_frames[_currentFrame]._x1 * _scale / 1024;
*y1 = _y + _animation->_y1 + _animation->_frames[_currentFrame]._y1 * _scale / 1024;
*x2 = *x1 + finalWidth;
@@ -604,7 +605,7 @@ void AnimationInstance::setZ(int32 z, bool relative) {
void AnimationInstance::setLayerZ(int32 z) {
_layerZ = z;
- if (_vm->getAnimationManager()->hasInstance(this))
+ if (_vm->getAnimationManager()->hasInstance(this))
_vm->getAnimationManager()->updateInstance(this);
}
@@ -665,8 +666,6 @@ void AnimationInstance::load(Common::ReadStream *stream) {
_useMask = stream->readSint32LE();
}
-
-
void AnimationInstance::setLooping(bool enable) {
debugC(6, kDebugAnim, "setLooping(%d)", (enable) ? 1 : 0);
_looping = enable;
@@ -682,7 +681,7 @@ AnimationManager::AnimationManager(ToonEngine *vm) : _vm(vm) {
bool AnimationManager::hasInstance(AnimationInstance* instance) {
for (uint32 i = 0; i < _instances.size(); i++) {
- if(_instances[i] == instance)
+ if(_instances[i] == instance)
return true;
}
return false;
@@ -698,12 +697,12 @@ void AnimationManager::addInstance(AnimationInstance *instance) {
// if the instance already exists, we skip the add
for (uint32 i = 0; i < _instances.size(); i++) {
- if(_instances[i] == instance)
+ if(_instances[i] == instance)
return;
}
-
+
int found = -1;
-
+
// here we now do an ordered insert (closer to the original game)
for (uint32 i = 0; i < _instances.size(); i++) {
if (_instances[i]->getLayerZ() >= instance->getLayerZ()) {
@@ -717,7 +716,6 @@ void AnimationManager::addInstance(AnimationInstance *instance) {
} else {
_instances.insert_at(found, instance);
}
-
}
void AnimationManager::removeInstance(AnimationInstance *instance) {
diff --git a/engines/toon/anim.h b/engines/toon/anim.h
index d7f64ab687..dfb6842b0e 100644
--- a/engines/toon/anim.h
+++ b/engines/toon/anim.h
@@ -161,7 +161,7 @@ public:
AnimationInstance *createNewInstance(AnimationInstanceType type);
void addInstance(AnimationInstance *instance);
void removeInstance(AnimationInstance *instance);
- void updateInstance(AnimationInstance* instance);
+ void updateInstance(AnimationInstance* instance);
void removeAllInstances(AnimationInstanceType type);
void render();
void update(int32 timeIncrement);
diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp
index e5e5b85832..0003bb1972 100644
--- a/engines/toon/audio.cpp
+++ b/engines/toon/audio.cpp
@@ -29,10 +29,10 @@
namespace Toon {
-static int ADPCM_index[8] = {
+static const int ADPCM_index[8] = {
-1, -1, -1, -1, 2 , 4 , 6 , 8
};
-static int ADPCM_table[89] = {
+static const int ADPCM_table[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
@@ -48,7 +48,7 @@ AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixe
for (int32 i = 0; i < 16; i++)
_channels[i] = NULL;
- for (int32 i = 0; i < 4; i++)
+ for (int32 i = 0; i < 4; i++)
_audioPacks[i] = NULL;
for (int32 i = 0; i < 4; i++) {
@@ -63,6 +63,8 @@ AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixe
_voiceMuted = false;
_musicMuted = false;
_sfxMuted = false;
+
+ _currentMusicChannel = 0;
}
AudioManager::~AudioManager(void) {
@@ -113,24 +115,23 @@ void AudioManager::playMusic(Common::String dir, Common::String music) {
return;
// see what channel to take
- if (_channels[0] && _channels[0]->isPlaying() && _channels[1] && _channels[1]->isPlaying()) {
- // take the one that is fading
- if (_channels[0]->isFading()) {
- _channels[0]->stop(false);
- _channels[1]->stop(true);
- _currentMusicChannel = 0;
- } else {
- _channels[1]->stop(false);
- _channels[0]->stop(true);
- _currentMusicChannel = 1;
+ // if the current channel didn't really start. reuse this one
+ if (_channels[_currentMusicChannel] && _channels[_currentMusicChannel]->isPlaying()) {
+ if (_channels[_currentMusicChannel]->getPlayedSampleCount() < 500) {
+ _channels[_currentMusicChannel]->stop(false);
+ _currentMusicChannel = 1 - _currentMusicChannel;
+ }
+ else
+ {
+ _channels[_currentMusicChannel]->stop(true);
}
- } else if (_channels[0] && _channels[0]->isPlaying()) {
- _channels[0]->stop(true);
- _currentMusicChannel = 1;
- } else {
- if (_channels[1] && _channels[1]->isPlaying())
- _channels[1]->stop(true);
- _currentMusicChannel = 0;
+ }
+ // go to the next channel
+ _currentMusicChannel = 1 - _currentMusicChannel;
+
+ // if it's already playing.. stop it quickly (no fade)
+ if (_channels[_currentMusicChannel] && _channels[_currentMusicChannel]->isPlaying()) {
+ _channels[_currentMusicChannel]->stop(false);
}
// no need to delete instance here it will automatically deleted by the mixer is done with it
@@ -208,7 +209,6 @@ void AudioManager::stopCurrentVoice() {
_channels[2]->stop(false);
}
-
void AudioManager::closeAudioPack(int32 id) {
delete _audioPacks[id];
_audioPacks[id] = NULL;
@@ -261,6 +261,7 @@ AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer,
_looping = looping;
_musicAttenuation = 1000;
_deleteFileStream = deleteFileStreamAtEnd;
+ _playedSamples = 0;
// preload one packet
if (_totalSize > 0) {
@@ -286,7 +287,7 @@ AudioStreamInstance::~AudioStreamInstance() {
int AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
debugC(5, kDebugAudio, "readBuffer(buffer, %d)", numSamples);
- if(_stopped)
+ if(_stopped)
return 0;
handleFade(numSamples);
@@ -309,6 +310,8 @@ int AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
_bufferOffset += leftSamples;
}
+ _playedSamples += numSamples;
+
return numSamples;
}
@@ -423,7 +426,7 @@ void AudioStreamInstance::handleFade(int32 numSamples) {
debugC(5, kDebugAudio, "handleFade(%d)", numSamples);
// Fading enabled only for music
- if (_soundType != Audio::Mixer::kMusicSoundType)
+ if (_soundType != Audio::Mixer::kMusicSoundType)
return;
int32 finalVolume = _volume;
@@ -457,7 +460,7 @@ void AudioStreamInstance::handleFade(int32 numSamples) {
_musicAttenuation = 250;
} else {
_musicAttenuation += numSamples >> 5;
- if (_musicAttenuation > 1000)
+ if (_musicAttenuation > 1000)
_musicAttenuation = 1000;
}
@@ -468,9 +471,11 @@ void AudioStreamInstance::stop(bool fade /*= false*/) {
debugC(1, kDebugAudio, "stop(%d)", (fade) ? 1 : 0);
if (fade) {
- _fadingIn = false;
- _fadingOut = true;
- _fadeTime = 0;
+ if (!_fadingOut) {
+ _fadingIn = false;
+ _fadingOut = true;
+ _fadeTime = 0;
+ }
} else {
stopNow();
}
@@ -551,7 +556,7 @@ void AudioManager::startAmbientSFX(int32 id, int32 delay, int32 mode, int32 volu
}
}
- if (found < 0)
+ if (found < 0)
return;
_ambientSFXs[found]._lastTimer = _vm->getOldMilli() - 1;
@@ -610,13 +615,14 @@ void AudioManager::killAllAmbientSFX()
void AudioManager::updateAmbientSFX()
{
- if (_vm->getMoviePlayer()->isPlaying()) return;
+ if (_vm->getMoviePlayer()->isPlaying())
+ return;
for (int32 i = 0; i < 4; i++) {
AudioAmbientSFX* ambient = &_ambientSFXs[i];
if (ambient->_enabled && (ambient->_channel < 0 || !(_channels[ambient->_channel] && _channels[ambient->_channel]->isPlaying()))) {
if(ambient->_mode == 1) {
- if (_vm->randRange(0, 32767) < ambient->_delay) {
+ if (_vm->randRange(0, 32767) < ambient->_delay) {
ambient->_channel = playSFX(ambient->_id, ambient->_volume, false);
}
} else {
@@ -629,6 +635,5 @@ void AudioManager::updateAmbientSFX()
}
}
-
} // End of namespace Toon
diff --git a/engines/toon/audio.h b/engines/toon/audio.h
index 7c1eedfee9..5feae9c5a1 100644
--- a/engines/toon/audio.h
+++ b/engines/toon/audio.h
@@ -52,6 +52,10 @@ public:
return _fadingIn || _fadingOut;
}
+ int32 getPlayedSampleCount() {
+ return _playedSamples;
+ }
+
void setVolume(int32 volume);
protected:
int readBuffer(int16 *buffer, const int numSamples);
@@ -93,6 +97,7 @@ protected:
int32 _volume;
int32 _musicAttenuation;
bool _deleteFileStream;
+ int32 _playedSamples;
};
class AudioStreamPackage {
@@ -133,14 +138,14 @@ public:
void playVoice(int32 id, bool genericVoice);
int32 playSFX(int32 id, int volume, bool genericSFX);
void stopCurrentVoice();
- void stopAllSfxs();
+ void stopAllSfxs();
void setMusicVolume(int32 volume);
void stopMusic();
void muteVoice(bool mute);
void muteMusic(bool mute);
void muteSfx(bool mute);
bool isVoiceMuted() { return _voiceMuted; }
- bool isMusicMuted() { return _musicMuted; }
+ bool isMusicMuted() { return _musicMuted; }
bool isSfxMuted() { return _sfxMuted; }
void startAmbientSFX(int32 id, int32 delay, int32 mode, int32 volume);
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index f1f246e549..69051d45fd 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -64,6 +64,7 @@ Character::Character(ToonEngine *vm) : _vm(vm) {
_lastWalkTime = 0;
_numPixelToWalk = 0;
_nextIdleTime = _vm->getSystem()->getMillis() + (_vm->randRange(0, 600) + 300) * _vm->getTickLength();
+ _lineToSayId = 0;
}
Character::~Character(void) {
@@ -104,7 +105,7 @@ void Character::setFacing(int32 facing) {
_lastWalkTime = _vm->getSystem()->getMillis();
if ((_facing - facing + 8) % 8 > (facing - _facing + 8) % 8)
dir = 1;
- else
+ else
dir = -1;
while (_facing != facing) {
@@ -125,14 +126,13 @@ void Character::setFacing(int32 facing) {
if (_currentPathNode == 0)
playStandingAnim();
else
- playWalkAnim(0,0);
+ playWalkAnim(0, 0);
_vm->doFrame();
};
_flags &= ~2;
}
-
_facing = facing;
}
@@ -140,7 +140,7 @@ void Character::forcePosition(int32 x, int32 y) {
debugC(5, kDebugCharacter, "forcePosition(%d, %d)", x, y);
- setPosition(x,y);
+ setPosition(x, y);
_finalX = x;
_finalY = y;
}
@@ -176,7 +176,6 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
if (_x == _finalX && _y == _finalY)
return true;
-
if (_vm->getPathFinding()->findPath(_x, _y, _finalX, _finalY)) {
int32 localFinalX = _finalX;
@@ -191,7 +190,7 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
_currentPathNodeCount = _vm->getPathFinding()->getPathNodeCount();
_currentPathNode = 0;
stopSpecialAnim();
-
+
_lastWalkTime = _vm->getSystem()->getMillis();
_numPixelToWalk = 0;
@@ -327,11 +326,6 @@ void Character::updateTimers(int32 relativeAdd) {
void Character::stopSpecialAnim() {
debugC(4, kDebugCharacter, "stopSpecialAnim()");
-// Strangerke - Commented (not used)
-#if 0
- if (_animSpecialId != _animSpecialDefaultId)
- delete anim;
-#endif
if (_animScriptId != -1)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = false;
@@ -388,7 +382,6 @@ void Character::update(int32 timeIncrement) {
if ((_flags & 4) == 0)
return;
-
if (_animScriptId != -1) {
_animationInstance = _vm->getSceneAnimation(this->)
#endif
@@ -423,19 +416,9 @@ void Character::update(int32 timeIncrement) {
return;
}
-// Strangerke - Commented (not used)
-#if 0
- if (_animFlags & 8) {
- if (anim->_flags7 == 0xff && anim->_flags9 == 0xff) {
- // start voice
- }
- }
-#endif
-
if (_animScriptId != -1)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true;
-
-
+
// TODO setup backup //
_animFlags |= 0x10;
@@ -494,17 +477,6 @@ void Character::update(int32 timeIncrement) {
}
} else {
nextFrame = currentFrame + 1;
-// Strangerke - Commented (not used)
-#if 0
- if (!_vm->getAudioManager()->voiceStillPlaying()) {
- if (_animFlags & 8) {
- if ((anim->_flags9 == 0xff && nextFrame == anim->_flags6) ||
- (anim->_flags9 != 0xff && nextFrame >= anim->_flags9)) {
- // start really talking
- }
- }
- }
-#endif
if (nextFrame == anim->_flags7 + 1 && (_animFlags & 0x40) == 0) {
if (anim->_flags8 != 1 && (_vm->randRange(0, 1) || anim->_flags8 == 2)) {
_animFlags |= 0x20;
@@ -525,7 +497,6 @@ void Character::update(int32 timeIncrement) {
//label78
-
#if 0
if (_id == 0)
debug(" drew animation name %s / flag %d / frame %d", _specialAnim->_name, _animFlags, nextFrame);
@@ -611,7 +582,6 @@ int32 Character::getScale() {
}
void Character::playWalkAnim(int32 startFrame, int32 endFrame) {
-
}
void Character::setId(int32 id) {
@@ -677,7 +647,6 @@ int32 Character::getAnimScript() {
}
void Character::playTalkAnim() {
-
}
void Character::stopWalk() {
@@ -1046,7 +1015,6 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
*strchr(animName, '?') = '0' + facing;
strcat(animName, ".CAF");
-
if (_animScriptId != -1 && (flags & 8) == 0)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true;
@@ -1068,11 +1036,9 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
}
}
-
if (_sceneAnimationId > -1)
setAnimationInstance(_vm->getSceneAnimation(_sceneAnimationId)->_animInstance);
-
_animFlags |= flags;
delete _specialAnim;
diff --git a/engines/toon/character.h b/engines/toon/character.h
index d4079d82ef..e870d81813 100644
--- a/engines/toon/character.h
+++ b/engines/toon/character.h
@@ -49,7 +49,6 @@ struct SpecialCharacterAnimation {
byte _flags9; // 25
};
-
class Character {
public:
Character(ToonEngine *vm);
@@ -106,7 +105,6 @@ public:
int32 getFacingFromDirection(int32 dx, int32 dy);
static const SpecialCharacterAnimation *getSpecialAnimation(int32 characterId, int32 animationId);
-
protected:
ToonEngine *_vm;
diff --git a/engines/toon/conversation.cpp b/engines/toon/conversation.cpp
index 4678ccc1c8..fc846288ef 100644
--- a/engines/toon/conversation.cpp
+++ b/engines/toon/conversation.cpp
@@ -45,5 +45,4 @@ void Conversation::load(Common::ReadStream *stream, int16 *conversationDataBase)
}
}
-
}
diff --git a/engines/toon/conversation.h b/engines/toon/conversation.h
index 784c681055..0380210e02 100644
--- a/engines/toon/conversation.h
+++ b/engines/toon/conversation.h
@@ -33,10 +33,10 @@ namespace Toon {
class Conversation {
public:
- int32 _enable; // 00
+ int32 _enable; // 00
struct ConvState {
- int32 _data2; // 04
+ int32 _data2; // 04
int16 _data3; // 08
void *_data4; // 10
} state[10];
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index f8c4c08ce6..ef023564bc 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -91,6 +91,15 @@ static const ADGameDescription gameDescriptions[] = {
},
Common::DE_DEU, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
},
+ {
+ "toon", "",
+ {
+ {"local.pak", 0, "8ef3368078b9ea70b305c04db826feea", 2680573},
+ {"generic.svl", 0, "5c42724bb93b360dca7044d6b7ef26e5", 7739319},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
+ },
AD_TABLE_END_MARKER
};
diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp
index eefb4b8efa..4f8152833b 100644
--- a/engines/toon/drew.cpp
+++ b/engines/toon/drew.cpp
@@ -111,11 +111,10 @@ void CharacterDrew::update(int32 timeIncrement) {
_scale = _currentScale;
} else if (_currentScale < _scale) {
_scale -= timeIncrement * 2;
- if (_scale < _currentScale)
+ if (_scale < _currentScale)
_scale = _currentScale;
}
setPosition(_x, _y);
-
}
int32 CharacterDrew::getRandomIdleAnim() {
diff --git a/engines/toon/drew.h b/engines/toon/drew.h
index d8091f2225..f248e4aa51 100644
--- a/engines/toon/drew.h
+++ b/engines/toon/drew.h
@@ -28,7 +28,6 @@
#include "toon/character.h"
-
namespace Toon {
class ToonEngine;
@@ -46,7 +45,6 @@ public:
int32 getRandomIdleAnim();
protected:
int32 _currentScale;
-
};
} // End of namespace Toon
diff --git a/engines/toon/flux.cpp b/engines/toon/flux.cpp
index 2b5551732b..034332af56 100644
--- a/engines/toon/flux.cpp
+++ b/engines/toon/flux.cpp
@@ -96,7 +96,7 @@ int32 CharacterFlux::fixFacingForAnimation(int32 originalFacing, int32 animation
if (!facingMask)
break;
}
-
+
return finalFacing;
}
diff --git a/engines/toon/flux.h b/engines/toon/flux.h
index a90853cb02..136dedd415 100644
--- a/engines/toon/flux.h
+++ b/engines/toon/flux.h
@@ -26,7 +26,6 @@
#ifndef TOON_FLUX_H
#define TOON_FLUX_H
-
#include "toon/character.h"
class ToonEngine;
diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp
index 8455ca7b61..8192a6f6f1 100644
--- a/engines/toon/font.cpp
+++ b/engines/toon/font.cpp
@@ -81,6 +81,8 @@ void FontRenderer::renderText(int32 x, int32 y, Common::String origText, int32 m
x -= xx / 2;
}
+ _vm->addDirtyRect(x, y, x + xx, y + yy);
+
int32 curX = x;
int32 curY = y;
int32 height = 0;
@@ -263,8 +265,8 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
if (x - 30 - maxWidth / 2 < 0)
x = maxWidth / 2 + 30;
- if (x + 30 + (maxWidth / 2) > 640)
- x = 640 - (maxWidth / 2) - 30;
+ if (x + 30 + (maxWidth / 2) > TOON_SCREEN_WIDTH)
+ x = TOON_SCREEN_WIDTH - (maxWidth / 2) - 30;
// we have good coordinates now, we can render the multi line
int32 curX = x;
@@ -273,6 +275,8 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
for (int32 i = 0; i < numLines; i++) {
const byte *line = lines[i];
curX = x - lineSize[i] / 2;
+ _vm->addDirtyRect(curX + _vm->state()->_currentScrollValue, y, curX + lineSize[i] + _vm->state()->_currentScrollValue, curY + height);
+
while (*line) {
byte curChar = textToFont(*line);
if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp
index 687ea6ee83..0573e92fef 100644
--- a/engines/toon/hotspot.cpp
+++ b/engines/toon/hotspot.cpp
@@ -78,8 +78,6 @@ int32 Hotspots::Find(int32 x, int32 y) {
debugC(6, kDebugHotspot, "Find(%d, %d)", x, y);
int32 priority = -1;
-// Strangerke - Commented (not used)
-// bool found = false;
int32 foundId = -1;
int32 testId = -1;
@@ -91,8 +89,6 @@ int32 Hotspots::Find(int32 x, int32 y) {
testId = i;
if (_items[testId].getPriority() > priority) {
-// Strangerke - Commented (not used)
-// found = true;
foundId = testId;
priority = _items[testId].getPriority();
}
@@ -128,10 +124,10 @@ bool Hotspots::LoadRif(Common::String rifName, Common::String additionalRifName)
// RIFs are compressed in RNC1
RncDecoder decoder;
- decoder.unpackM1(rifData, _items);
+ decoder.unpackM1(rifData, size, _items);
if (rifsize2) {
RncDecoder decoder2;
- decoder2.unpackM1(rifData2 , _items + (rifsize >> 9));
+ decoder2.unpackM1(rifData2 , size2, _items + (rifsize >> 9));
for (int32 i = 0; i < (rifsize2 >> 9); i++) {
HotspotData *hot = _items + (rifsize >> 9) + i;
hot->setData(0, hot->getX1() + 1280);
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index c6b57d96e2..4305abb62b 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -38,8 +38,8 @@ void ToonstruckSmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, ui
Video::SmackerDecoder::handleAudioTrack(track, chunkSize, unpackedSize);
}
-bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forcedflags) {
- debugC(1, kDebugMovie, "loadFile(%s, %d)", filename.c_str(), forcedflags);
+bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename) {
+ debugC(1, kDebugMovie, "loadFile(%s)", filename.c_str());
_lowRes = false;
@@ -56,8 +56,6 @@ bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forc
return true;
}
-
-
return false;
}
@@ -88,7 +86,7 @@ void Movie::play(Common::String video, int32 flags) {
_playing = true;
if (flags & 1)
_vm->getAudioManager()->setMusicVolume(0);
- _decoder->loadFile(video.c_str(), flags);
+ _decoder->loadFile(video.c_str());
playVideo(isFirstIntroVideo);
_vm->flushPalette(false);
if (flags & 1)
@@ -107,9 +105,9 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
if (_decoder->isLowRes()) {
// handle manually 2x scaling here
Graphics::Surface* surf = _vm->getSystem()->lockScreen();
- for (int y = 0; y < frame->h/2; y++) {
- memcpy(surf->getBasePtr(0, y*2+0), frame->getBasePtr(0, y), frame->pitch);
- memcpy(surf->getBasePtr(0, y*2+1), frame->getBasePtr(0, y), frame->pitch);
+ for (int y = 0; y < frame->h / 2; y++) {
+ memcpy(surf->getBasePtr(0, y * 2 + 0), frame->getBasePtr(0, y), frame->pitch);
+ memcpy(surf->getBasePtr(0, y * 2 + 1), frame->getBasePtr(0, y), frame->pitch);
}
_vm->getSystem()->unlockScreen();
} else {
@@ -135,11 +133,13 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
Common::Event event;
while (_vm->getSystem()->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ _vm->dirtyAllScreen();
return false;
}
_vm->getSystem()->delayMillis(10);
}
+ _vm->dirtyAllScreen();
return !_vm->shouldQuit();
}
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index 2a9173850f..bed2ceceae 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -36,7 +36,7 @@ public:
ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
virtual ~ToonstruckSmackerDecoder() {}
void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize);
- bool loadFile(const Common::String &filename, int forcedflags);
+ bool loadFile(const Common::String &filename);
bool isLowRes() { return _lowRes; }
protected:
bool _lowRes;
diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp
index 3f948679f4..e0cdf87502 100644
--- a/engines/toon/path.cpp
+++ b/engines/toon/path.cpp
@@ -186,7 +186,7 @@ int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
- if (isWalkable(x, y) && isLikelyWalkable(x,y)) {
+ if (isWalkable(x, y) && isLikelyWalkable(x, y)) {
int32 ndist = (x - xx) * (x - xx) + (y - yy) * (y - yy);
int32 ndist2 = (x - origX) * (x - origX) + (y - origY) * (y - origY);
if (currentFound < 0 || ndist < dist || (ndist == dist && ndist2 < dist2)) {
@@ -283,8 +283,8 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
}
// first test direct line
- if (lineIsWalkable(x,y,destx,desty)) {
- walkLine(x,y,destx,desty);
+ if (lineIsWalkable(x, y, destx, desty)) {
+ walkLine(x, y, destx, desty);
return true;
}
@@ -317,7 +317,7 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
int32 curPNode = px + py * _width;
if (isWalkable(px, py)) { // walkable ?
- int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px,py) ? 5 : 0));
+ int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px, py) ? 5 : 0));
if (sq[curPNode] > sum || !sq[curPNode]) {
int newWeight = abs(destx - px) + abs(desty - py);
sq[curPNode] = sum;
@@ -438,7 +438,6 @@ void PathFinding::addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h) {
_numBlockingRects++;
}
-
int32 PathFinding::getPathNodeCount() const {
return _gridPathCount;
}
diff --git a/engines/toon/path.h b/engines/toon/path.h
index a2b1b7bf92..03d2b188e5 100644
--- a/engines/toon/path.h
+++ b/engines/toon/path.h
@@ -91,7 +91,6 @@ protected:
int32 _gridPathCount;
ToonEngine *_vm;
-
};
} // End of namespace Toon
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 18e6a8cf7f..1945f0fe45 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "toon/picture.h"
#include "toon/tools.h"
#include "common/stack.h"
@@ -32,7 +31,7 @@ namespace Toon {
bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
debugC(1, kDebugPicture, "loadPicture(%s, %d)", file.c_str(), (totalPalette) ? 1 : 0);
-
+
uint32 size = 0;
uint8 *fileData = _vm->resources()->getFileData(file, &size);
if (!fileData)
@@ -49,12 +48,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
decompressLZSS(fileData + 8, _data, dstsize);
// size can only be 640x400 or 1280x400
- if (dstsize > 640 * 400 + 768)
- _width = 1280;
+ if (dstsize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
// do we have a palette ?
_paletteEntries = (dstsize & 0x7ff) / 3;
@@ -69,7 +68,7 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
}
case kCompSPCN: {
uint32 decSize = READ_LE_UINT32(fileData + 10);
- _data = new uint8[decSize+100];
+ _data = new uint8[decSize + 100];
_paletteEntries = READ_LE_UINT16(fileData + 14) / 3;
if (_paletteEntries) {
@@ -79,12 +78,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
}
// size can only be 640x400 or 1280x400
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
// decompress the picture into our buffer
decompressSPCN(fileData + 16 + _paletteEntries * 3, _data, decSize);
@@ -98,15 +97,15 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
_data = new uint8[decSize];
- rnc.unpackM1(fileData, _data);
+ rnc.unpackM1(fileData, size, _data);
// size can only be 640x400 or 1280x400
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
return true;
}
case kCompRNC2: {
@@ -119,12 +118,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
decSize = rnc.unpackM2(fileData, _data);
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
return true;
}
}
@@ -187,6 +186,41 @@ void Picture::drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, i
}
}
+void Picture::drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray) {
+
+ int32 rx = MIN(_width, surface.w - x);
+ int32 ry = MIN(_height, surface.h - y);
+
+ if (rx < 0 || ry < 0)
+ return;
+
+ int32 destPitch = surface.pitch;
+ int32 srcPitch = _width;
+
+ for (uint32 i = 0; i < rectArray.size(); i++) {
+
+ Common::Rect rect = rectArray[i];
+
+ int32 fillRx = MIN<int32>(rx, rect.right - rect.left);
+ int32 fillRy = MIN<int32>(ry, rect.bottom - rect.top);
+
+ uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
+ uint8 *curRow = (uint8 *)surface.pixels + (y + rect.top) * destPitch + (x + rect.left);
+
+ for (int32 yy = 0; yy < fillRy; yy++) {
+ uint8 *curSrc = c;
+ uint8 *cur = curRow;
+ for (int32 xx = 0; xx < fillRx; xx++) {
+ *cur = *curSrc;
+ curSrc++;
+ cur++;
+ }
+ curRow += destPitch;
+ c += srcPitch;
+ }
+ }
+}
+
void Picture::draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy) {
debugC(6, kDebugPicture, "draw(surface, %d, %d, %d, %d)", x, y, dx, dy);
@@ -279,7 +313,6 @@ void Picture::drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable
else
t = adx;
-
int32 cdx = (dx << 16) / t;
int32 cdy = (dy << 16) / t;
@@ -289,15 +322,15 @@ void Picture::drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable
int32 rx = bx >> 16;
int32 ry = by >> 16;
- if( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
+ if( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
// were drawing outside the screen causing corruption
if (!walkable) {
_data[_width * ry + rx] &= 0xe0;
- _data[_width * ry + rx+1] &= 0xe0;
+ _data[_width * ry + rx + 1] &= 0xe0;
} else {
int32 v = _data[_width * (by >> 16) + rx - 1];
_data[_width * ry + rx] = v;
- _data[_width * ry + rx+1] = v;
+ _data[_width * ry + rx + 1] = v;
}
}
diff --git a/engines/toon/picture.h b/engines/toon/picture.h
index 1b0fd7f550..6aca408364 100644
--- a/engines/toon/picture.h
+++ b/engines/toon/picture.h
@@ -44,6 +44,7 @@ public:
bool loadPicture(Common::String file, bool totalPalette = false);
void setupPalette();
void draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
+ void drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray);
void drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
void drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable);
void floodFillNotWalkableOnMask(int32 x, int32 y);
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 61e3ffb111..b29aa3b72d 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -29,13 +29,20 @@
#include "common/substream.h"
#include "toon/toon.h"
-
namespace Toon {
-Resources::Resources(ToonEngine *vm) : _vm(vm) {
+Resources::Resources(ToonEngine *vm) : _vm(vm), _cacheSize(0) {
+ _resourceCache.clear();
}
Resources::~Resources() {
+
+ while (!_resourceCache.empty()) {
+ CacheEntry *temp = _resourceCache.back();
+ _resourceCache.pop_back();
+ delete temp;
+ }
+
while(!_pakFiles.empty()) {
PakFile *temp = _pakFiles.back();
_pakFiles.pop_back();
@@ -45,8 +52,73 @@ Resources::~Resources() {
purgeFileData();
}
-void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "openPackage(%s, %d)", fileName.c_str(), (preloadEntirePackage) ? 1 : 0);
+void Resources::removePackageFromCache(Common::String packName) {
+ // I'm not sure what's a good strategy here. It seems unnecessary to
+ // actually remove the cached resources, because the player may be
+ // wandering back and forth between rooms. So for now, do nothing.
+}
+
+bool Resources::getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData) {
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data && (*entry)->_fileName.compareToIgnoreCase(fileName) == 0) {
+ debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.c_str(), (*entry)->_size, (*entry)->_packName.c_str());
+ (*entry)->_age = 0;
+ *fileSize = (*entry)->_size;
+ *fileData = (*entry)->_data;
+ return true;
+ }
+ }
+ return false;
+}
+
+void Resources::addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData) {
+ debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.c_str(), fileName.c_str(), fileSize, _cacheSize + fileSize);
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ (*entry)->_age++;
+ }
+ }
+ _cacheSize += fileSize;
+
+ while (_cacheSize > MAX_CACHE_SIZE) {
+ CacheEntry *bestEntry = 0;
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ if (!bestEntry || ((*entry)->_age >= bestEntry->_age && (*entry)->_size >= bestEntry->_size)) {
+ bestEntry = *entry;
+ }
+ }
+ }
+ if (!bestEntry)
+ break;
+
+ free(bestEntry->_data);
+ bestEntry->_data = 0;
+ _cacheSize -= bestEntry->_size;
+ debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size);
+ }
+
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if (!(*entry)->_data) {
+ (*entry)->_packName = packName;
+ (*entry)->_fileName = fileName;
+ (*entry)->_age = 0;
+ (*entry)->_size = fileSize;
+ (*entry)->_data = fileData;
+ return;
+ }
+ }
+
+ CacheEntry *entry = new CacheEntry();
+ entry->_packName = packName;
+ entry->_fileName = fileName;
+ entry->_size = fileSize;
+ entry->_data = fileData;
+ _resourceCache.push_back(entry);
+}
+
+void Resources::openPackage(Common::String fileName) {
+ debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str());
Common::File file;
bool opened = file.open(fileName);
@@ -55,15 +127,16 @@ void Resources::openPackage(Common::String fileName, bool preloadEntirePackage)
return;
PakFile *pakFile = new PakFile();
- pakFile->open(&file, fileName, preloadEntirePackage);
+ pakFile->open(&file, fileName);
- if (preloadEntirePackage)
- file.close();
+ file.close();
_pakFiles.push_back(pakFile);
}
void Resources::closePackage(Common::String fileName) {
+
+ removePackageFromCache(fileName);
for (uint32 i = 0; i < _pakFiles.size(); i++) {
if (_pakFiles[i]->getPackName() == fileName) {
delete _pakFiles[i];
@@ -91,13 +164,21 @@ uint8 *Resources::getFileData(Common::String fileName, uint32 *fileSize) {
_allocatedFileData.push_back(memory);
return memory;
} else {
+
+ uint32 locFileSize = 0;
+ uint8 *locFileData = 0;
+
+ if (getFromCache(fileName, &locFileSize, &locFileData)) {
+ *fileSize = locFileSize;
+ return locFileData;
+ }
+
for (uint32 i = 0; i < _pakFiles.size(); i++) {
- uint32 locFileSize = 0;
- uint8 *locFileData = 0;
locFileData = _pakFiles[i]->getFileData(fileName, &locFileSize);
if (locFileData) {
*fileSize = locFileSize;
+ addToCache(_pakFiles[i]->getPackName(), fileName, locFileSize, locFileData);
return locFileData;
}
}
@@ -136,25 +217,16 @@ void Resources::purgeFileData() {
}
_allocatedFileData.clear();
}
+
Common::SeekableReadStream *PakFile::createReadStream(Common::String fileName) {
debugC(1, kDebugResource, "createReadStream(%s)", fileName.c_str());
- int32 offset = 0;
- int32 size = 0;
- for (uint32 i = 0; i < _numFiles; i++) {
- if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- size = _files[i]._size;
- offset = _files[i]._offset;
- break;
- }
- }
- if (!size)
- return 0;
-
- if (_fileHandle)
- return new Common::SeekableSubReadStream(_fileHandle, offset, offset + size);
+ uint32 fileSize = 0;
+ uint8 *buffer = getFileData(fileName, &fileSize);
+ if (buffer)
+ return new Common::MemoryReadStream(buffer, fileSize, DisposeAfterUse::YES);
else
- return new Common::MemoryReadStream(_buffer + offset, size);
+ return 0;
}
uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
@@ -162,16 +234,26 @@ uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
for (uint32 i = 0; i < _numFiles; i++) {
if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- *fileSize = _files[i]._size;
- return _buffer + _files[i]._offset;
+ Common::File file;
+ if (file.open(_packName)) {
+ *fileSize = _files[i]._size;
+ file.seek(_files[i]._offset);
+
+ // Use malloc() because that's what MemoryReadStream
+ // uses to dispose of the memory when it's done.
+ uint8 *buffer = (uint8 *)malloc(*fileSize);
+ file.read(buffer, *fileSize);
+ file.close();
+ return buffer;
+ }
}
}
return 0;
}
-void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "open(rs, %d)", (preloadEntirePackage) ? 1 : 0);
+void PakFile::open(Common::SeekableReadStream *rs, Common::String packName) {
+ debugC(1, kDebugResource, "open(rs)");
char buffer[64];
int32 currentPos = 0;
@@ -199,30 +281,12 @@ void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool
_numFiles++;
_files.push_back(newFile);
}
-
- if (preloadEntirePackage) {
- _bufferSize = rs->size();
- delete[] _buffer;
- _buffer = new uint8[_bufferSize];
- rs->seek(0);
- rs->read(_buffer, _bufferSize);
- }
}
void PakFile::close() {
- delete[] _buffer;
-
- if (_fileHandle) {
- _fileHandle->close();
- delete _fileHandle;
- }
}
PakFile::PakFile() {
- _bufferSize = 0;
- _buffer = NULL;
-
- _fileHandle = NULL;
}
PakFile::~PakFile() {
diff --git a/engines/toon/resource.h b/engines/toon/resource.h
index e117c8e259..d6ed29b81b 100644
--- a/engines/toon/resource.h
+++ b/engines/toon/resource.h
@@ -31,6 +31,8 @@
#include "common/file.h"
#include "common/stream.h"
+#define MAX_CACHE_SIZE (4 * 1024 * 1024)
+
namespace Toon {
class PakFile {
@@ -38,7 +40,7 @@ public:
PakFile();
~PakFile();
- void open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage);
+ void open(Common::SeekableReadStream *rs, Common::String packName);
uint8 *getFileData(Common::String fileName, uint32 *fileSize);
Common::String getPackName() { return _packName; }
Common::SeekableReadStream *createReadStream(Common::String fileName);
@@ -52,9 +54,6 @@ protected:
};
Common::String _packName;
- uint8 *_buffer;
- int32 _bufferSize;
-
uint32 _numFiles;
Common::Array<File> _files;
Common::File *_fileHandle;
@@ -62,11 +61,25 @@ protected:
class ToonEngine;
+class CacheEntry {
+public:
+ CacheEntry() : _age(0), _size(0), _data(0) {}
+ ~CacheEntry() {
+ free(_data);
+ }
+
+ Common::String _packName;
+ Common::String _fileName;
+ uint32 _age;
+ uint32 _size;
+ uint8 *_data;
+};
+
class Resources {
public:
Resources(ToonEngine *vm);
~Resources();
- void openPackage(Common::String file, bool preloadEntirePackage);
+ void openPackage(Common::String file);
void closePackage(Common::String fileName);
Common::SeekableReadStream *openFile(Common::String file);
uint8 *getFileData(Common::String fileName, uint32 *fileSize); // this memory must be copied to your own structures!
@@ -76,6 +89,12 @@ protected:
ToonEngine *_vm;
Common::Array<uint8 *> _allocatedFileData;
Common::Array<PakFile *> _pakFiles;
+ uint32 _cacheSize;
+ Common::Array<CacheEntry *> _resourceCache;
+
+ void removePackageFromCache(Common::String packName);
+ bool getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData);
+ void addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData);
};
} // End of namespace Toon
diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp
index 3cd56761f6..0242ace7e3 100644
--- a/engines/toon/script.cpp
+++ b/engines/toon/script.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/stream.h"
#include "common/util.h"
@@ -71,7 +70,7 @@ EMCInterpreter::~EMCInterpreter() {
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
delete[] _scriptData->text;
_scriptData->text = new byte[chunk._size];
assert(_scriptData->text);
@@ -79,7 +78,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('ORDR'):
+ case MKTAG('O','R','D','R'):
delete[] _scriptData->ordr;
_scriptData->ordr = new uint16[chunk._size >> 1];
assert(_scriptData->ordr);
@@ -90,7 +89,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
delete[] _scriptData->data;
_scriptData->data = new uint16[chunk._size >> 1];
assert(_scriptData->data);
@@ -177,7 +176,7 @@ bool EMCInterpreter::start(EMCState *script, int function) {
if (functionOffset == 0xFFFF)
return false;
- script->ip = &script->dataPtr->data[functionOffset+1];
+ script->ip = &script->dataPtr->data[functionOffset + 1];
return true;
}
diff --git a/engines/toon/script.h b/engines/toon/script.h
index 6c46238238..b6d28e1171 100644
--- a/engines/toon/script.h
+++ b/engines/toon/script.h
@@ -31,7 +31,6 @@
#include "common/func.h"
#include "common/iff_container.h"
-
// Based on Kyra script interpretor
namespace Toon {
@@ -88,9 +87,9 @@ public:
// Both lead to some problems in our IFF parser, either reading after the end
// of file or producing a "Chunk overread" error message. To work around this
// we need to adjust the size field properly.
- if (_formType == MKID_BE('EMC2'))
+ if (_formType == MKTAG('E','M','C','2'))
_formChunk.size -= 8;
- else if (_formType == MKID_BE('AVFS'))
+ else if (_formType == MKTAG('A','V','F','S'))
_formChunk.size += 4;
}
};
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index adf3a1c9cc..b181591bf0 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -265,7 +265,6 @@ int32 ScriptFunc::sys_Cmd_Draw_Actor_Standing(EMCState *state) {
arg1 = 1;
}
-
if (arg2 > -1)
_vm->getDrew()->forceFacing(arg2);
@@ -461,7 +460,7 @@ int32 ScriptFunc::sys_Cmd_Actor_Talks(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Say_Lines(EMCState *state) {
-
+
// WORKAROUND: In the scene 4 (Castle), if you click twice on the closed door, Drew disappears
// the script makes him disappear for the custom animation and not reappear.
if (_vm->state()->_currentScene == 4 && stackPos(1) == 562) {
@@ -491,11 +490,11 @@ int32 ScriptFunc::sys_Cmd_Empty_Inventory(EMCState *state) {
int32 ScriptFunc::sys_Cmd_Set_Anim_Scale_Size(EMCState *state) {
int32 animID = stackPos(0);
int32 scale = stackPos(1);
-
+
SceneAnimation *sceneAnim = _vm->getSceneAnimation(animID);
if (sceneAnim) {
sceneAnim->_animInstance->setUseMask(true);
- sceneAnim->_animInstance->setScale(scale,true);
+ sceneAnim->_animInstance->setScale(scale, true);
}
return 0;
}
@@ -939,8 +938,6 @@ int32 ScriptFunc::sys_Cmd_Init_Scene_Anim(EMCState *state) {
sceneAnim->_animInstance->setAnimationRange(stackPos(11), stackPos(11));
sceneAnim->_animInstance->setFrame(stackPos(11));
-
-
debugC(0, 0xfff, "Init Anim %s %d %d %d %d %d %d %d %d %d %d %d %d %d\n", GetText(12, state), stackPos(0), stackPos(1), stackPos(2), stackPos(3),
stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9), stackPos(10), stackPos(11), stackPos(12));
@@ -950,7 +947,7 @@ int32 ScriptFunc::sys_Cmd_Init_Scene_Anim(EMCState *state) {
int32 layerZ = stackPos(3);
if (dx == -2)
- sceneAnim->_animInstance->moveRelative(640, 0, 0);
+ sceneAnim->_animInstance->moveRelative(TOON_SCREEN_WIDTH, 0, 0);
else if (dx < 0) {
dx = sceneAnim->_animation->_x1;
}
@@ -1028,7 +1025,7 @@ int32 ScriptFunc::sys_Cmd_Draw_Scene_Anim_WSA_Frame(EMCState *state) {
else if (animId == 20 || animId == 15 || animId == 21 || animId == 16 || animId == 17 || animId == 18)
_vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 1);
else if (animId == 9) {
- _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 6);
+ _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 3);
}
}
@@ -1091,13 +1088,13 @@ int32 ScriptFunc::sys_Cmd_Proceed_To_Next_Chapter(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Play_Sfx_Plus(EMCState *state) {
- //debugC(0,0xfff, "playSfx ( %d , %d, %d, %d, %d )", stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ //debugC(0, 0xfff, "playSfx ( %d , %d, %d, %d, %d )", stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
_vm->playSFX(stackPos(0), stackPos(1));
return 0;
}
int32 ScriptFunc::sys_Cmd_Play_Sfx(EMCState *state) {
- //debugC(0,0xfff, "playSfx ( %d , %d)", stackPos(0), stackPos(1));
+ //debugC(0, 0xfff, "playSfx ( %d , %d)", stackPos(0), stackPos(1));
_vm->playSFX(stackPos(0), stackPos(1));
return 0;
}
diff --git a/engines/toon/state.cpp b/engines/toon/state.cpp
index 71674688d5..0d6977842d 100644
--- a/engines/toon/state.cpp
+++ b/engines/toon/state.cpp
@@ -54,7 +54,7 @@ void Location::load(Common::ReadStream *stream) {
}
State::State(void) {
- for (int32 i = 0; i < 64; i++) {
+ for (int32 i = 0; i < 256; i++) {
_locations[i]._visited = false;
_locations[i]._numSceneAnimations = 0;
_locations[i]._numRifBoxes = 0;
@@ -80,6 +80,7 @@ State::State(void) {
_showConversationIcons = false;
+ _inMenu = false;
_inCloseUp = false;
_inConversation = false;
@@ -118,7 +119,6 @@ State::State(void) {
}
State::~State(void) {
-
}
int32 State::getGameFlag(int32 flagId) {
diff --git a/engines/toon/state.h b/engines/toon/state.h
index 283e378443..63505fd5fb 100644
--- a/engines/toon/state.h
+++ b/engines/toon/state.h
@@ -62,6 +62,7 @@ public:
int16 _confiscatedInventory[35];
int32 _numInventoryItems;
int32 _numConfiscatedInventoryItems;
+ bool _inMenu;
bool _inCloseUp;
bool _inCutaway;
bool _inConversation;
@@ -80,7 +81,6 @@ public:
int32 _nextSpecialEnterX;
int32 _nextSpecialEnterY;
-
bool _timerEnabled[2];
int32 _timerTimeout[2];
int32 _timerDelay[2];
@@ -93,7 +93,6 @@ public:
void loadConversations(Common::ReadStream *stream);
void saveConversations(Common::WriteStream *stream);
-
};
} // End of namespace Toon
diff --git a/engines/toon/text.cpp b/engines/toon/text.cpp
index c54ea87d50..f0d17dd34e 100644
--- a/engines/toon/text.cpp
+++ b/engines/toon/text.cpp
@@ -57,7 +57,7 @@ int32 TextResource::getNext(int32 offset) {
uint16 *table = (uint16 *)_textData + 1;
int a = getId(offset);
- return table[a+1];
+ return READ_LE_UINT16(table + a + 1);
}
int32 TextResource::getId(int32 offset) {
@@ -66,7 +66,7 @@ int32 TextResource::getId(int32 offset) {
uint16 *table = (uint16 *)_textData + 1;
int32 found = -1;
for (int32 i = 0; i < _numTexts; i++) {
- if (offset == table[i]) {
+ if (offset == READ_LE_UINT16(table + i)) {
found = i;
break;
}
@@ -80,7 +80,7 @@ char *TextResource::getText(int32 offset) {
uint16 *table = (uint16 *)_textData + 1;
int32 found = -1;
for (int32 i = 0; i < _numTexts; i++) {
- if (offset == table[i]) {
+ if (offset == READ_LE_UINT16(table + i)) {
found = i;
break;
}
@@ -88,7 +88,7 @@ char *TextResource::getText(int32 offset) {
if (found < 0)
return NULL;
- int32 realOffset = ((uint16 *)_textData + 1 + _numTexts)[found];
+ int32 realOffset = READ_LE_UINT16((uint16 *)_textData + 1 + _numTexts + found);
return (char *)_textData + realOffset;
}
diff --git a/engines/toon/tools.cpp b/engines/toon/tools.cpp
index a03a2d57ce..da6e0f712e 100644
--- a/engines/toon/tools.cpp
+++ b/engines/toon/tools.cpp
@@ -125,7 +125,6 @@ uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize) {
return (dstp - dst);
}
-
//return codes
#define NOT_PACKED 0
#define PACKED_CRC -1
@@ -201,7 +200,16 @@ uint16 RncDecoder::inputBits(uint8 amount) {
newBitBuffl >>= newBitCount;
newBitBuffl |= remBits;
_srcPtr += 2;
- newBitBuffh = READ_LE_UINT16(_srcPtr);
+
+ // added some more check here to prevent reading in the buffer
+ // if there are no bytes anymore.
+ _inputByteLeft -= 2;
+ if (_inputByteLeft <= 0)
+ newBitBuffh = 0;
+ else if (_inputByteLeft == 1)
+ newBitBuffh = *_srcPtr;
+ else
+ newBitBuffh = READ_LE_UINT16(_srcPtr);
amount -= newBitCount;
newBitCount = 16 - amount;
}
@@ -284,7 +292,7 @@ int RncDecoder::getbit() {
return temp;
}
-int32 RncDecoder::unpackM1(const void *input, void *output) {
+int32 RncDecoder::unpackM1(const void *input, uint16 inputSize, void *output) {
debugC(1, kDebugTools, "unpackM1(input, output)");
uint8 *outputLow, *outputHigh;
@@ -297,6 +305,7 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
uint16 crcPacked = 0;
+ _inputByteLeft = inputSize;
_bitBuffl = 0;
_bitBuffh = 0;
_bitCount = 0;
@@ -339,9 +348,12 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
_srcPtr = (_dstPtr - packLen);
}
+ _inputByteLeft -= HEADER_LEN;
+
_dstPtr = (uint8 *)output;
_bitCount = 0;
+
_bitBuffl = READ_LE_UINT16(_srcPtr);
inputBits(2);
@@ -360,8 +372,22 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
memcpy(_dstPtr, _srcPtr, inputLength); //memcpy is allowed here
_dstPtr += inputLength;
_srcPtr += inputLength;
- uint16 a = READ_LE_UINT16(_srcPtr);
- uint16 b = READ_LE_UINT16(_srcPtr + 2);
+ _inputByteLeft -= inputLength;
+ uint16 a;
+ if (_inputByteLeft <= 0)
+ a = 0;
+ else if (_inputByteLeft == 1)
+ a = *_srcPtr;
+ else
+ a = READ_LE_UINT16(_srcPtr);
+
+ uint16 b;
+ if (_inputByteLeft <= 2)
+ b = 0;
+ else if(_inputByteLeft == 3)
+ b = *(_srcPtr + 2);
+ else
+ b = READ_LE_UINT16(_srcPtr + 2);
_bitBuffl &= ((1 << _bitCount) - 1);
_bitBuffl |= (a << _bitCount);
@@ -397,9 +423,6 @@ int32 RncDecoder::unpackM2(const void *input, void *output) {
uint16 crcUnpacked = 0;
uint16 crcPacked = 0;
-// Strangerke - Commented (not used)
-// uint16 counts = 0;
-
_bitBuffl = 0;
_bitCount = 0;
@@ -429,7 +452,6 @@ int32 RncDecoder::unpackM2(const void *input, void *output) {
_srcPtr = inputptr;
_dstPtr = (uint8 *)output;
-
uint16 ofs, len;
byte ofs_hi, ofs_lo;
diff --git a/engines/toon/tools.h b/engines/toon/tools.h
index 05fc5c9cda..1434ca26c7 100644
--- a/engines/toon/tools.h
+++ b/engines/toon/tools.h
@@ -42,8 +42,8 @@ const uint32 kCompRNC2 = 0x524E4302;
#define READ_LE_INT16(x) (int16) READ_LE_UINT16(x)
#define READ_LE_INT32(x) (int32) READ_LE_UINT32(x)
-#define WRITE_LE_INT16(x,y) WRITE_LE_UINT16(x,(int16)y)
-#define WRITE_LE_INT32(x,y) WRITE_LE_UINT32(x,(int32)y)
+#define WRITE_LE_INT16(x, y) WRITE_LE_UINT16(x, (int16)y)
+#define WRITE_LE_INT32(x, y) WRITE_LE_UINT32(x, (int32)y)
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize);
uint32 decompressLZSS(byte *src, byte *dst, int dstsize);
@@ -63,10 +63,12 @@ protected:
const uint8 *_srcPtr;
uint8 *_dstPtr;
+ int16 _inputByteLeft;
+
public:
RncDecoder();
~RncDecoder();
- int32 unpackM1(const void *input, void *output);
+ int32 unpackM1(const void *input, uint16 inputSize, void *output);
int32 unpackM2(const void *input, void *output);
protected:
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 79e153a7db..2040668245 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -49,7 +49,6 @@
namespace Toon {
-
void ToonEngine::init() {
_currentScriptRegion = 0;
_resources = new Resources(this);
@@ -58,7 +57,7 @@ void ToonEngine::init() {
_hotspots = new Hotspots(this);
_mainSurface = new Graphics::Surface();
- _mainSurface->create(1280, 400, 1);
+ _mainSurface->create(TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_HEIGHT, 1);
_finalPalette = new uint8[768];
_backupPalette = new uint8[768];
@@ -101,14 +100,13 @@ void ToonEngine::init() {
SearchMan.addSubDirectoryMatching(gameDataDir, "ACT1");
SearchMan.addSubDirectoryMatching(gameDataDir, "ACT2");
-
syncSoundSettings();
_pathFinding = new PathFinding(this);
- resources()->openPackage("LOCAL.PAK", true);
- resources()->openPackage("ONETIME.PAK", true);
- resources()->openPackage("DREW.PAK", true);
+ resources()->openPackage("LOCAL.PAK");
+ resources()->openPackage("ONETIME.PAK");
+ resources()->openPackage("DREW.PAK");
for (int32 i = 0; i < 32; i++)
_characters[i] = NULL;
@@ -185,7 +183,7 @@ void ToonEngine::parseInput() {
bool hasModifier = event.kbd.hasFlags(Common::KBD_ALT|Common::KBD_CTRL|Common::KBD_SHIFT);
switch (event.type) {
- case Common::EVENT_KEYUP:
+ case Common::EVENT_KEYDOWN:
if ((event.kbd.ascii == 27 || event.kbd.ascii == 32) && !hasModifier) {
_audioManager->stopCurrentVoice();
}
@@ -262,7 +260,6 @@ void ToonEngine::parseInput() {
selectHotspot();
clickEvent();
}
-
}
void ToonEngine::enableTimer(int32 timerId) {
@@ -325,8 +322,8 @@ void ToonEngine::updateScrolling(bool force, int32 timeIncrement) {
if ((_gameState->_locations[_gameState->_currentScene]._flags & 0x80) == 0) {
if (desiredScrollValue < 0)
desiredScrollValue = 0;
- if (desiredScrollValue >= _currentPicture->getWidth() - 640)
- desiredScrollValue = _currentPicture->getWidth() - 640;
+ if (desiredScrollValue >= _currentPicture->getWidth() - TOON_SCREEN_WIDTH)
+ desiredScrollValue = _currentPicture->getWidth() - TOON_SCREEN_WIDTH;
if (force) {
_gameState->_currentScrollValue = desiredScrollValue;
@@ -378,12 +375,23 @@ void ToonEngine::updateTimer(int32 timeIncrement) {
}
void ToonEngine::render() {
- if (_gameState->_inCutaway)
- _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
- else
- _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
- //_currentMask->drawMask(*_mainSurface,0,0,0,0);
+ if (_dirtyAll) {
+ if (_gameState->_inCutaway)
+ _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
+ else
+ _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_HEIGHT));
+ } else {
+ if (_gameState->_inCutaway)
+ _currentCutaway->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ else
+ _currentPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
+
+ //_currentMask->drawMask(*_mainSurface, 0, 0, 0, 0);
_animationManager->render();
drawInfoLine();
@@ -399,7 +407,7 @@ void ToonEngine::render() {
sprintf(test, "%d %d / mask %d layer %d z %d", _mouseX, _mouseY, getMask()->getData(_mouseX, _mouseY), getLayerAtPoint(_mouseX, _mouseY), getZAtPoint(_mouseX, _mouseY));
int32 c = *(uint8 *)_mainSurface->getBasePtr(_mouseX, _mouseY);
- sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c*3+0], _finalPalette[c*3+1], _finalPalette[c*3+2]);
+ sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c * 3 + 0], _finalPalette[c * 3 + 1], _finalPalette[c * 3 + 2]);
_fontRenderer->setFont(_fontToon);
_fontRenderer->renderText(40, 150, Common::String(test), 0);
@@ -422,8 +430,8 @@ void ToonEngine::render() {
// add a little sleep here
int32 newMillis = (int32)_system->getMillis();
int32 sleepMs = 1; // Minimum delay to allow thread scheduling
- if ((newMillis - _lastRenderTime) < _tickLength)
- sleepMs = _tickLength - (newMillis - _lastRenderTime);
+ if ((newMillis - _lastRenderTime) < _tickLength * 2)
+ sleepMs = _tickLength * 2 - (newMillis - _lastRenderTime);
assert(sleepMs >= 0);
_system->delayMillis(sleepMs);
_lastRenderTime = _system->getMillis();
@@ -454,24 +462,24 @@ void ToonEngine::doMagnifierEffect() {
11, 11, 11, 11, 12
};
- byte tempBuffer[25*25];
+ byte tempBuffer[25 * 25];
for (int32 y = -12; y <= 12; y++) {
for (int32 x = -12; x <= 12; x++) {
int32 destPitch = surface.pitch;
uint8 *curRow = (uint8 *)surface.pixels + (posY + y) * destPitch + (posX + x);
- tempBuffer[(y+12) * 25 + x + 12] = *curRow;
+ tempBuffer[(y + 12) * 25 + x + 12] = *curRow;
}
}
for (int32 y = -12; y <= 12; y++) {
for (int32 x = -12; x <= 12; x++) {
int32 dist = y * y + x * x;
- if (dist > 144)
+ if (dist > 144)
continue;
int32 destPitch = surface.pitch;
uint8 *curRow = (uint8 *)surface.pixels + (posY + y) * destPitch + (posX + x);
int32 lerp = (512 + intSqrt[dist] * 256 / 12);
- *curRow = tempBuffer[(y*lerp/1024+12) * 25 + x*lerp/1024 + 12];
+ *curRow = tempBuffer[(y * lerp / 1024 + 12) * 25 + x * lerp / 1024 + 12];
}
}
}
@@ -484,7 +492,50 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
_cursorAnimationInstance->setPosition(_mouseX - 40 + state()->_currentScrollValue - _cursorOffsetX, _mouseY - 40 - _cursorOffsetY, 0, false);
_cursorAnimationInstance->render();
}
- _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, 1280, 0, 0, 640, 400);
+
+ // Handle dirty rects here
+ static int32 lastScroll = 0;
+
+ if (_dirtyAll || _gameState->_currentScrollValue != lastScroll) {
+ // we have to refresh everything in case of scrolling.
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ } else {
+
+ int32 offX = 0;
+ for (uint i = 0; i < _oldDirtyRects.size(); i++) {
+ Common::Rect rect = _oldDirtyRects[i];
+ rect.translate(-state()->_currentScrollValue, 0);
+ offX = 0;
+ if(rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _oldDirtyRects[i].left + offX + _oldDirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+
+ for (uint i = 0; i < _dirtyRects.size(); i++) {
+ Common::Rect rect = _dirtyRects[i];
+ rect.translate(-state()->_currentScrollValue, 0);
+ offX = 0;
+ if (rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _dirtyRects[i].left + offX + _dirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+ }
+ lastScroll = _gameState->_currentScrollValue;
+
if (updateScreen) {
_system->updateScreen();
_shouldQuit = shouldQuit(); // update game quit flag - this shouldn't be called all the time, as it's a virtual function
@@ -588,6 +639,9 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
AudioStreamInstance *mainmenuMusic = NULL;
bool musicPlaying = false;
+ _gameState->_inMenu = true;
+ dirtyAllScreen();
+
while (!doExit) {
clickingOn = MAINMENUHOTSPOT_NONE;
clickRelease = false;
@@ -605,7 +659,15 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
}
while (!clickRelease) {
- mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ if(_dirtyAll) {
+ mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ addDirtyRect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ } else {
+ mainmenuPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
if (entries[entryNr].menuMask & menuMask) {
@@ -700,6 +762,8 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
}
}
+ _gameState->_inMenu = false;
+
//delete mainmenuMusic;
for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++)
delete entries[entryNr].animation;
@@ -715,7 +779,7 @@ Common::Error ToonEngine::run() {
g_eventRec.registerRandomSource(_rnd, "toon");
- initGraphics(640, 400, true);
+ initGraphics(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT, true);
init();
// do we need to load directly a game?
@@ -813,7 +877,20 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
_inventoryIcons = NULL;
_inventoryIconSlots = NULL;
_genericTexts = NULL;
- _audioManager = NULL;
+ _audioManager = NULL;
+ _gameState = NULL;
+
+ _locationDirNotVisited = NULL;
+ _locationDirVisited = NULL;
+ _specialInfoLine = NULL;
+
+ for (int i = 0; i < 64; i++) {
+ _sceneAnimations[i]._active = false;
+ }
+
+ for (int i = 0; i < 32; i++) {
+ _characters[i] = NULL;
+ }
memset(&_scriptData, 0, sizeof(EMCData));
@@ -855,7 +932,7 @@ ToonEngine::~ToonEngine() {
_mainSurface->free();
delete _mainSurface;
}
-
+
delete[] _finalPalette;
delete[] _backupPalette;
delete[] _additionalPalette1;
@@ -884,7 +961,6 @@ ToonEngine::~ToonEngine() {
delete _pathFinding;
-
for (int32 i = 0; i < 64; i++) {
if (_sceneAnimations[i]._active) {
// see if one character shares this instance
@@ -923,14 +999,7 @@ void ToonEngine::flushPalette(bool deferFlushToNextRender) {
return;
}
_needPaletteFlush = false;
- uint8 vmpalette[1024];
- for (int32 i = 0; i < 256; i++) {
- vmpalette[i*4+0] = _finalPalette[i*3+0];
- vmpalette[i*4+1] = _finalPalette[i*3+1];
- vmpalette[i*4+2] = _finalPalette[i*3+2];
- vmpalette[i*4+3] = 0;
- }
- _system->getPaletteManager()->setPalette(vmpalette, 0, 256);
+ _system->getPaletteManager()->setPalette(_finalPalette, 0, 256);
}
void ToonEngine::setPaletteEntries(uint8 *palette, int32 offset, int32 num) {
memcpy(_finalPalette + offset * 3, palette, num * 3);
@@ -953,8 +1022,6 @@ void ToonEngine::simpleUpdate(bool waitCharacterToTalk) {
_animationManager->update(elapsedTime);
_audioManager->updateAmbientSFX();
render();
-
-
}
void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
@@ -970,13 +1037,8 @@ void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
// adapted from KyraEngine
void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
-
-
static int32 numReentrant = 0;
numReentrant++;
-
-// Strangerke - Commented (not used)
-// uint32 nextTime = _system->getMillis() + _tickLength;
const int startScript = _lastProcessedSceneScript;
_updatingSceneScriptRunFlag = true;
@@ -1009,10 +1071,8 @@ void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
} while (_lastProcessedSceneScript != startScript && !_shouldQuit);
-
_updatingSceneScriptRunFlag = false;
numReentrant--;
-
}
void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
@@ -1080,10 +1140,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
_mouseButton = 0;
_lastMouseButton = 0x3;
-
// load package
strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
- resources()->openPackage(temp, true);
+ resources()->openPackage(temp);
strcpy(temp, state()->_locations[SceneId]._name);
strcat(temp, ".NPP");
@@ -1201,6 +1260,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
state()->_mouseHidden = false;
+ clearDirtyRects();
+ dirtyAllScreen();
+
if (!forGameLoad) {
_script->start(&_scriptState[0], 0);
@@ -1218,7 +1280,7 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
_gameState->_nextSpecialEnterX = -1;
_gameState->_nextSpecialEnterY = -1;
}
-
+
_script->start(&_scriptState[0], 3);
while (_script->run(&_scriptState[0]))
@@ -1258,8 +1320,8 @@ void ToonEngine::loadAdditionalPalette(Common::String fileName, int32 mode) {
fixPaletteEntries(_additionalPalette2, 23);
break;
case 2:
- memcpy(_cutawayPalette, palette, 768);
- fixPaletteEntries(_cutawayPalette, 256);
+ memcpy(_cutawayPalette, palette, size);
+ fixPaletteEntries(_cutawayPalette, size/3);
break;
case 3:
memcpy(_universalPalette, palette, 96);
@@ -1293,7 +1355,6 @@ void ToonEngine::initChapter() {
_script->unload(&data);
setupGeneralPalette();
-
}
void ToonEngine::loadCursor() {
@@ -1415,10 +1476,9 @@ void ToonEngine::clickEvent() {
return;
}
-
int32 mouseX = _mouseX;
if (_gameState->_inCutaway) {
- mouseX += 1280;
+ mouseX += TOON_BACKBUFFER_WIDTH;
}
// find hotspot
@@ -1446,7 +1506,6 @@ void ToonEngine::clickEvent() {
}
}
-
if (!currentHot) {
int32 xx, yy;
@@ -1474,9 +1533,6 @@ void ToonEngine::clickEvent() {
int16 command = currentHot->getData(commandId);
int16 argument = currentHot->getData(commandId + 1);
int16 priority = currentHot->getPriority();
-// Strangerke - Commented (not used)
-// int16 ref = currentHot->getRef();
-// int16 pad1 = currentHot->getData(6);
if (!_gameState->_inCutaway && !_gameState->_inCloseUp) {
if (leftButton && (currentHot->getData(4) != 2 || _gameState->_mouseState >= 0) && currentHot->getData(5) != -1) {
@@ -1518,8 +1574,6 @@ void ToonEngine::clickEvent() {
break;
case 7:
// switch to CloseUp
-// Strangerke - Commented (not used)
-// int closeup = 1;
break;
case 8:
// face flux
@@ -1527,11 +1581,6 @@ void ToonEngine::clickEvent() {
break;
case 9:
case 10:
-// Strangerke - Commented (not used)
-// if (rand() % 1 == 1) {
-// } else {
-// }
- // setFluxFacingPoint(x,y)
sayLines(2, argument);
break;
case 11:
@@ -1555,7 +1604,6 @@ void ToonEngine::clickEvent() {
int32 val = _scriptState[_currentScriptRegion].regs[4];
currentHot->setData(4, currentHot->getData(4) & val);
}
-
}
void ToonEngine::selectHotspot() {
@@ -1567,7 +1615,7 @@ void ToonEngine::selectHotspot() {
int32 mouseX = _mouseX;
if (_gameState->_inCutaway)
- mouseX += 1280;
+ mouseX += TOON_BACKBUFFER_WIDTH;
if (_gameState->_sackVisible) {
if (_mouseX > 0 && _mouseX < 40 && _mouseY > 356 && _mouseY < 396) {
@@ -1725,7 +1773,6 @@ void ToonEngine::exitScene() {
strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
resources()->closePackage(temp);
-
_drew->stopWalk();
_flux->stopWalk();
@@ -1737,7 +1784,7 @@ void ToonEngine::flipScreens() {
_gameState->_inCloseUp = !_gameState->_inCloseUp;
if (_gameState->_inCloseUp) {
- _gameState->_currentScrollValue = 640;
+ _gameState->_currentScrollValue = TOON_SCREEN_WIDTH;
setPaletteEntries(_cutawayPalette, 1, 128);
setPaletteEntries(_additionalPalette2, 232, 23);
} else {
@@ -1751,12 +1798,11 @@ void ToonEngine::flipScreens() {
void ToonEngine::fadeIn(int32 numFrames) {
for (int32 f = 0; f < numFrames; f++) {
- uint8 vmpalette[1024];
+ uint8 vmpalette[3 * 256];
for (int32 i = 0; i < 256; i++) {
- vmpalette[i*4+0] = f * _finalPalette[i*3+0] / (numFrames - 1);
- vmpalette[i*4+1] = f * _finalPalette[i*3+1] / (numFrames - 1);
- vmpalette[i*4+2] = f * _finalPalette[i*3+2] / (numFrames - 1);
- vmpalette[i*4+3] = 0;
+ vmpalette[i * 3 + 0] = f * _finalPalette[i * 3 + 0] / (numFrames - 1);
+ vmpalette[i * 3 + 1] = f * _finalPalette[i * 3 + 1] / (numFrames - 1);
+ vmpalette[i * 3 + 2] = f * _finalPalette[i * 3 + 2] / (numFrames - 1);
}
_system->getPaletteManager()->setPalette(vmpalette, 0, 256);
_system->updateScreen();
@@ -1766,16 +1812,15 @@ void ToonEngine::fadeIn(int32 numFrames) {
void ToonEngine::fadeOut(int32 numFrames) {
- uint8 oldpalette[1024];
+ uint8 oldpalette[3 * 256];
_system->getPaletteManager()->grabPalette(oldpalette, 0, 256);
for (int32 f = 0; f < numFrames; f++) {
- uint8 vmpalette[1024];
+ uint8 vmpalette[3 * 256];
for (int32 i = 0; i < 256; i++) {
- vmpalette[i*4+0] = (numFrames - f - 1) * oldpalette[i*4+0] / (numFrames - 1);
- vmpalette[i*4+1] = (numFrames - f - 1) * oldpalette[i*4+1] / (numFrames - 1);
- vmpalette[i*4+2] = (numFrames - f - 1) * oldpalette[i*4+2] / (numFrames - 1);
- vmpalette[i*4+3] = 255;
+ vmpalette[i * 3 + 0] = (numFrames - f - 1) * oldpalette[i * 3 + 0] / (numFrames - 1);
+ vmpalette[i * 3 + 1] = (numFrames - f - 1) * oldpalette[i * 3 + 1] / (numFrames - 1);
+ vmpalette[i * 3 + 2] = (numFrames - f - 1) * oldpalette[i * 3 + 2] / (numFrames - 1);
}
_system->getPaletteManager()->setPalette(vmpalette, 0, 256);
_system->updateScreen();
@@ -1829,11 +1874,11 @@ int32 ToonEngine::getScaleAtPoint(int32 x, int32 y) {
return 1024;
// clamp values
- x = MIN<int32>(1279, MAX<int32>(0, x));
- y = MIN<int32>(399, MAX<int32>(0, y));
+ x = MIN<int32>(TOON_BACKBUFFER_WIDTH - 1, MAX<int32>(0, x));
+ y = MIN<int32>(TOON_BACKBUFFER_HEIGHT - 1, MAX<int32>(0, y));
int32 maskData = _currentMask->getData(x, y) & 0x1f;
- return _roomScaleData[maskData+2] * 1024 / 100;
+ return _roomScaleData[maskData + 2] * 1024 / 100;
}
int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
@@ -1841,11 +1886,11 @@ int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
return 0;
// clamp values
- x = MIN<int32>(1279, MAX<int32>(0, x));
- y = MIN<int32>(399, MAX<int32>(0, y));
+ x = MIN<int32>(TOON_BACKBUFFER_WIDTH - 1, MAX<int32>(0, x));
+ y = MIN<int32>(TOON_BACKBUFFER_HEIGHT - 1, MAX<int32>(0, y));
int32 maskData = _currentMask->getData(x, y) & 0x1f;
- return _roomScaleData[maskData+130] << 5;
+ return _roomScaleData[maskData + 130] << 5;
}
int32 ToonEngine::getZAtPoint(int32 x, int32 y) {
@@ -1922,25 +1967,11 @@ void ToonEngine::sayLines(int numLines, int dialogId) {
if (oldShowMouse)
Game.MouseHiddenCount = 0;
#endif
-
}
int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
int32 myId = 0;
-// Strangerke - Commented (not used)
-#if 0
- char *myLine;
- if (dialogid < 1000) {
- myLine = _roomTexts->getText(dialogid);
- myId = dialogid;
- } else {
- myLine = _genericTexts->getText(dialogid - 1000);
- myId = dialogid - 1000;
- }
- debugC(0, 0xfff, "Talker = %d will say '%s' \n", READ_LE_UINT16(c - 2), myLine);
-#endif
-
if (_audioManager->voiceStillPlaying())
_audioManager->stopCurrentVoice();
@@ -1957,14 +1988,6 @@ int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
void ToonEngine::playTalkAnimOnCharacter(int32 animID, int32 characterId, bool talker) {
if (animID || talker) {
-// Strangerke - Commented (not used)
-#if 0
- if (_gameState->_inCutaway || _gameState->_inInventory) {
- if (talker) {
- // character talks
- }
- } else
-#endif
if (characterId == 0) {
_drew->playAnim(animID, 0, (talker ? 8 : 0) + 2);
} else if (characterId == 1) {
@@ -2014,7 +2037,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
_gameState->_mouseHidden = true;
}
-
// get what is before the string
int a = READ_LE_UINT16(myLine - 2);
char *b = myLine - 2 - 4 * a;
@@ -2025,14 +2047,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
char *e = c - 2 - 4 * numParticipants;
READ_LE_UINT16(e);
-// Strangerke - Commented (not used)
-// char *g = e - 2 * f;
-
- // flag as talking
-// Strangerke - Commented (not used)
-// char *h = c;
-
-
// if one voice is still playing, wait !
if (blocking) {
while (_audioManager->voiceStillPlaying() && !_shouldQuit)
@@ -2090,8 +2104,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
_currentTextLine = myLine;
_currentTextLineCharacterId = talkerId;
_currentTextLineId = dialogid;
-
-
} else {
Character *character = getCharacterById(talkerId);
if (character)
@@ -2100,7 +2112,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
debugC(0, 0xfff, "Talker = %d (num participants : %d) will say '%s'", (int)talkerId , (int)numParticipants, myLine);
-
getTextPosition(talkerId, &_currentTextLineX, &_currentTextLineY);
if (dialogid < 1000) {
@@ -2120,8 +2131,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
if (character)
character->setTalking(false);
}
-
-
return 1;
}
@@ -2136,7 +2145,7 @@ void ToonEngine::haveAConversation(int32 convId) {
_gameState->_currentConversationId = convId;
// change the music to the "conversation" music if needed.
- playRoomMusic();
+ playRoomMusic();
if (conv->_enable) {
// fix dialog script based on new flags
@@ -2154,7 +2163,6 @@ void ToonEngine::haveAConversation(int32 convId) {
doFrame();
}
-
_mouseButton = 0;
_gameState->_firstConverstationLine = true;
@@ -2183,11 +2191,13 @@ void ToonEngine::haveAConversation(int32 convId) {
a++;
}
}
- if (_shouldQuit) return;
+
+ if (_shouldQuit)
+ return;
+
_gameState->_showConversationIcons = false;
_gameState->_mouseHidden = 1;
-
if (selected < 0 || selected == 1 || selected == 3) {
if (_gameState->_firstConverstationLine)
processConversationClick(conv, 3);
@@ -2199,9 +2209,6 @@ void ToonEngine::haveAConversation(int32 convId) {
}
}
-// Strangerke - Commented (not used)
-// int cur = 0;
-
for (int i = 0; i < 10; i++) {
if (conv->state[i]._data2 == 2) {
if (i != 3)
@@ -2216,8 +2223,7 @@ void ToonEngine::haveAConversation(int32 convId) {
_gameState->_sackVisible = true;
// switch back to original music
- playRoomMusic();
-
+ playRoomMusic();
}
void ToonEngine::drawConversationIcons() {
@@ -2339,7 +2345,6 @@ retry:
break;
}
}
-
}
// hardcoded conversation flag to know if one dialogue icon must be displayed or not
@@ -2500,7 +2505,7 @@ int32 ToonEngine::runConversationCommand(int16 **command) {
int16 *v5 = *command;
int v2 = READ_LE_INT16(v5);
- int v4 = READ_LE_INT16(v5+1);
+ int v4 = READ_LE_INT16(v5 + 1);
int result = v2 - 100;
switch (v2) {
case 100:
@@ -2533,9 +2538,6 @@ int32 ToonEngine::runConversationCommand(int16 **command) {
}
int32 ToonEngine::waitTicks(int32 numTicks, bool breakOnMouseClick) {
-// Strangerke - Commented (not used)
-// Common::EventManager *_event = _system->getEventManager();
-
uint32 nextTime = _system->getMillis() + numTicks * _tickLength;
while (_system->getMillis() < nextTime || numTicks == -1) {
//if (!_animationSceneScriptRunFlag)
@@ -2554,7 +2556,13 @@ void ToonEngine::renderInventory() {
if (!_gameState->_inInventory)
return;
- _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ _inventoryPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT));
+ }
+ clearDirtyRects();
// draw items on screen
for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
@@ -2582,13 +2590,13 @@ void ToonEngine::renderInventory() {
int32 ToonEngine::showInventory() {
int32 oldScrollValue = _gameState->_currentScrollValue;
-// Strangerke - Commented (not used)
-// Common::EventManager *_event = _system->getEventManager();
+
delete _inventoryPicture;
_inventoryPicture = new Picture(this);
fadeOut(5);
_inventoryPicture->loadPicture("SACK128.CPS", true);
_inventoryPicture->setupPalette();
+ dirtyAllScreen();
if (_gameState->_mouseState >= 0) {
setCursor(_gameState->_mouseState, true, -18, -14);
@@ -2637,7 +2645,6 @@ int32 ToonEngine::showInventory() {
int32 modItem = getSpecialInventoryItem(item);
if (modItem) {
-
if (modItem == -1) {
_gameState->_mouseState = item;
_gameState->_inventory[foundObj] = 0;
@@ -2686,7 +2693,7 @@ int32 ToonEngine::showInventory() {
}
_gameState->_currentScrollValue = oldScrollValue;
- _gameState->_inInventory = false;
+ _gameState->_inInventory = false;
_mouseButton = 0;
_lastMouseButton = 0x3;
@@ -2702,6 +2709,7 @@ int32 ToonEngine::showInventory() {
setupGeneralPalette();
}
flushPalette();
+ dirtyAllScreen();
_firstFrame = true;
return 0;
@@ -2776,6 +2784,7 @@ void ToonEngine::showCutaway(Common::String cutawayPicture) {
_currentCutaway->setupPalette();
_oldScrollValue = _gameState->_currentScrollValue;
_gameState->_currentScrollValue = 0;
+ dirtyAllScreen();
flushPalette();
}
@@ -2786,6 +2795,7 @@ void ToonEngine::hideCutaway() {
_gameState->_currentScrollValue = _oldScrollValue;
_currentCutaway = 0;
_currentPicture->setupPalette();
+ dirtyAllScreen();
flushPalette();
}
@@ -2810,7 +2820,7 @@ void ToonEngine::rearrangeInventory() {
if (_gameState->_inventory[i] == 0) {
// move all the following items from one
for (int32 j = i + 1; j < _gameState->_numInventoryItems; j++) {
- _gameState->_inventory[j-1] = _gameState->_inventory[j];
+ _gameState->_inventory[j - 1] = _gameState->_inventory[j];
}
_gameState->_numInventoryItems--;
}
@@ -2824,14 +2834,14 @@ void ToonEngine::newGame() {
addItemToInventory(67);
addItemToInventory(11);
addItemToInventory(19);
- loadScene(_gameState->_currentScene);
+ loadScene(22);
+ //loadScene(_gameState->_currentScene);
} else {
//loadScene(4);
loadScene(_gameState->_currentScene);
}
}
-
void ToonEngine::playSFX(int32 id, int32 volume) {
if (id < 0)
_audioManager->playSFX(-id + 1, volume, true);
@@ -2857,7 +2867,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
// drew
int32 x = _drew->getX();
int32 y = _drew->getY();
- if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
if (!_gameState->_inCutaway && !_gameState->_inInventory) {
*retX = x;
*retY = y - ((_drew->getScale() * 256 / 1024) >> 1) - 45;
@@ -2867,7 +2877,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
// flux
int32 x = _flux->getX();
int32 y = _flux->getY();
- if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
if (!_gameState->_inCutaway) {
*retX = x;
*retY = y - ((_drew->getScale() * 100 / 1024) >> 1) - 30;
@@ -2897,7 +2907,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
Character *character = getCharacterById(characterId);
if (character && !_gameState->_inCutaway) {
if (character->getAnimationInstance()) {
- if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + 640) {
+ if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
int32 x1, y1, x2, y2;
character->getAnimationInstance()->getRect(&x1, &y1, &x2, &y2);
*retX = (x1 + x2) / 2;
@@ -2926,7 +2936,7 @@ void ToonEngine::drawConversationLine() {
}
void ToonEngine::pauseEngineIntern(bool pause) {
-
+
Engine::pauseEngineIntern(pause);
static int32 pauseStart = 0;
@@ -2956,11 +2966,11 @@ void ToonEngine::pauseEngineIntern(bool pause) {
}
bool ToonEngine::canSaveGameStateCurrently() {
- return !_gameState->_inInventory && !_gameState->_inConversation && !_gameState->_inCutaway && !_gameState->_mouseHidden && !_moviePlayer->isPlaying();
+ return !_gameState->_inMenu && !_gameState->_inInventory && !_gameState->_inConversation && !_gameState->_inCutaway && !_gameState->_mouseHidden && !_moviePlayer->isPlaying();
}
bool ToonEngine::canLoadGameStateCurrently() {
- return !_gameState->_inInventory && !_gameState->_inConversation && !_gameState->_inCutaway && !_gameState->_mouseHidden && !_moviePlayer->isPlaying();
+ return !_gameState->_inMenu && !_gameState->_inInventory && !_gameState->_inConversation && !_gameState->_inCutaway && !_gameState->_mouseHidden && !_moviePlayer->isPlaying();
}
Common::String ToonEngine::getSavegameName(int nr) {
@@ -3018,7 +3028,6 @@ bool ToonEngine::saveGame(int32 slot, Common::String saveGameDesc) {
saveFile->writeUint32BE(saveDate);
saveFile->writeUint16BE(saveTime);
-
// save global state
_gameState->save(saveFile);
_gameState->saveConversations(saveFile);
@@ -3045,7 +3054,6 @@ bool ToonEngine::saveGame(int32 slot, Common::String saveGameDesc) {
_sceneAnimations[i].save(this, saveFile);
}
-
for (int32 i = 0; i < 8; i++) {
if (_characters[i]) {
saveFile->writeSByte(i);
@@ -3125,7 +3133,7 @@ bool ToonEngine::loadGame(int32 slot) {
_sceneAnimationScripts[i]._frozen = loadFile->readByte();
_sceneAnimationScripts[i]._frozenForConversation = false;
int32 oldTimer = loadFile->readSint32BE();
- _sceneAnimationScripts[i]._lastTimer = MAX<int32>(0,oldTimer + timerDiff);
+ _sceneAnimationScripts[i]._lastTimer = MAX<int32>(0, oldTimer + timerDiff);
_script->loadState(&_sceneAnimationScripts[i]._state, loadFile);
}
@@ -3164,7 +3172,7 @@ bool ToonEngine::loadGame(int32 slot) {
// load "command buffer"
int32 size = loadFile->readSint16BE();
if (size) {
- uint8 *buf = new uint8[size+2];
+ uint8 *buf = new uint8[size + 2];
loadFile->read(buf, size + 2);
Common::MemoryReadStream rStr(buf, size + 2);
@@ -3283,10 +3291,6 @@ void ToonEngine::initCharacter(int32 characterId, int32 animScriptId, int32 scen
return;
}
-// Strangerke - Commented (not used)
-// if (_characters[characterIndex])
-// delete current char
-
_characters[characterIndex] = new Character(this);
_characters[characterIndex]->setId(characterId);
_characters[characterIndex]->setAnimScript(animScriptId);
@@ -3410,6 +3414,7 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
Picture *pic = new Picture(this);
pic->loadPicture(str, false);
pic->setupPalette();
+ dirtyAllScreen();
flushPalette();
if (lineId) {
@@ -3433,7 +3438,13 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
break;
}
- pic->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ pic->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ pic->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT));
+ }
+ clearDirtyRects();
drawConversationLine();
if (!_audioManager->voiceStillPlaying()) {
@@ -3452,11 +3463,11 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
}
fadeOut(5);
+ dirtyAllScreen();
restorePalette();
_firstFrame = true;
_gameState->_currentScrollValue = oldScrollValue;
delete pic;
-
}
int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
@@ -3498,7 +3509,7 @@ int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
case 11:
if (itemSrc == 0xb) {
_gameState->_mouseState = -1;
- replaceItemFromInventory(11,12);
+ replaceItemFromInventory(11, 12);
setCursor(0, false, 0, 0);
rearrangeInventory();
return 1;
@@ -4511,9 +4522,9 @@ void ToonEngine::createShadowLUT() {
for (int32 i = 0; i < 255; i++) {
// goal color
- uint32 destR = _finalPalette[i*3+0] * scaleNum / scaleDenom;
- uint32 destG = _finalPalette[i*3+1] * scaleNum / scaleDenom;
- uint32 destB = _finalPalette[i*3+2] * scaleNum / scaleDenom;
+ uint32 destR = _finalPalette[i * 3 + 0] * scaleNum / scaleDenom;
+ uint32 destG = _finalPalette[i * 3 + 1] * scaleNum / scaleDenom;
+ uint32 destB = _finalPalette[i * 3 + 2] * scaleNum / scaleDenom;
// search only in the "picture palette" which is in colors 1-128 and 200-255
int32 colorDist = 0xffffff;
@@ -4521,9 +4532,9 @@ void ToonEngine::createShadowLUT() {
for (int32 c = 1; c < 129; c++) {
- int32 diffR = _finalPalette[c*3+0] - destR;
- int32 diffG = _finalPalette[c*3+1] - destG;
- int32 diffB = _finalPalette[c*3+2] - destB;
+ int32 diffR = _finalPalette[c * 3 + 0] - destR;
+ int32 diffG = _finalPalette[c * 3 + 1] - destG;
+ int32 diffB = _finalPalette[c * 3 + 2] - destB;
if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
@@ -4533,9 +4544,9 @@ void ToonEngine::createShadowLUT() {
for (int32 c = 200; c < 256; c++) {
- int32 diffR = _finalPalette[c*3+0] - destR;
- int32 diffG = _finalPalette[c*3+1] - destG;
- int32 diffB = _finalPalette[c*3+2] - destB;
+ int32 diffR = _finalPalette[c * 3 + 0] - destR;
+ int32 diffG = _finalPalette[c * 3 + 1] - destG;
+ int32 diffB = _finalPalette[c * 3 + 2] - destB;
if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
@@ -4665,6 +4676,47 @@ void ToonEngine::playRoomMusic() {
_audioManager->playMusic(_gameState->_locations[_gameState->_currentScene]._name, _gameState->_locations[_gameState->_currentScene]._music);
}
+void ToonEngine::dirtyAllScreen()
+{
+ _dirtyRects.clear();
+ _dirtyAll = true;
+}
+
+void ToonEngine::addDirtyRect( int32 left, int32 top, int32 right, int32 bottom ) {
+ left = MIN<int32>(MAX<int32>(left, 0), TOON_BACKBUFFER_WIDTH);
+ right = MIN<int32>(MAX<int32>(right, 0), TOON_BACKBUFFER_WIDTH);
+ top = MIN<int32>(MAX<int32>(top, 0), TOON_BACKBUFFER_HEIGHT);
+ bottom = MIN<int32>(MAX<int32>(bottom, 0), TOON_BACKBUFFER_HEIGHT);
+
+ Common::Rect rect(left, top, right, bottom);
+
+ if (bottom - top <= 0 || right - left <= 0)
+ return;
+
+ for (uint32 i = 0; i < _dirtyRects.size(); i++) {
+ if (_dirtyRects[i].contains(rect))
+ return;
+ if (rect.contains(_dirtyRects[i])) {
+ _dirtyRects.remove_at(i);
+ i--;
+ }
+ }
+
+ // check also in the old rect (of the old frame)
+ for (int32 i = _oldDirtyRects.size() - 1 ; i >= 0; i--) {
+ if (rect.contains(_oldDirtyRects[i])) {
+ _oldDirtyRects.remove_at(i);
+ }
+ }
+
+ _dirtyRects.push_back(rect);
+}
+
+void ToonEngine::clearDirtyRects() {
+ _oldDirtyRects = _dirtyRects;
+ _dirtyRects.clear();
+ _dirtyAll = false;
+}
void SceneAnimation::save(ToonEngine *vm, Common::WriteStream *stream) {
stream->writeByte(_active);
stream->writeSint32BE(_id);
@@ -4691,7 +4743,6 @@ void SceneAnimation::load(ToonEngine *vm, Common::ReadStream *stream) {
_active = stream->readByte();
_id = stream->readSint32BE();
-
if (!_active)
return;
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index f3370aed5e..3554900684 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -52,6 +52,11 @@ class MemoryWriteStreamDynamic;
#define TOON_SAVEGAME_VERSION 4
#define DATAALIGNMENT 4
+#define TOON_SCREEN_WIDTH 640
+#define TOON_SCREEN_HEIGHT 400
+#define TOON_BACKBUFFER_WIDTH 1280
+#define TOON_BACKBUFFER_HEIGHT 400
+
/**
* This is the namespace of the Toon engine.
*
@@ -206,8 +211,6 @@ public:
void waitForScriptStep();
void doMagnifierEffect();
-
-
bool canSaveGameStateCurrently();
bool canLoadGameStateCurrently();
void pauseEngineIntern(bool pause);
@@ -334,6 +337,10 @@ public:
(f == kSupportsSavingDuringRuntime);
}
+ void dirtyAllScreen();
+ void addDirtyRect(int32 left, int32 top, int32 right, int32 bottom);
+ void clearDirtyRects();
+
protected:
OSystem *_system;
int32 _tickLength;
@@ -371,6 +378,11 @@ protected:
bool _updatingSceneScriptRunFlag;
Graphics::Surface *_mainSurface;
+ Common::Array<Common::Rect> _dirtyRects;
+ Common::Array<Common::Rect> _oldDirtyRects;
+
+ bool _dirtyAll;
+
AnimationInstance *_cursorAnimationInstance;
Animation *_cursorAnimation;
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index 0b15643767..c89375d876 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -32,143 +32,83 @@
namespace Touche {
-MidiPlayer::MidiPlayer()
- : _driver(0), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) {
- memset(_channelsTable, 0, sizeof(_channelsTable));
+static const uint8 _gmToRol[256] = {
+ 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26,
+ 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F,
+ 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71,
+ 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A,
+ 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E,
+ 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22,
+ 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10,
+ 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01
+};
+
+
+MidiPlayer::MidiPlayer() {
+
+ // FIXME: Necessary?
memset(_channelsVolume, 0, sizeof(_channelsVolume));
- open();
-}
-MidiPlayer::~MidiPlayer() {
- close();
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+ _driver = MidiDriver::createMidi(dev);
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+ }
}
void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) {
+ Common::StackLock lock(_mutex);
+
stop();
- _midiData = (uint8 *)malloc(size);
+ _midiData = (byte *)malloc(size);
if (_midiData) {
stream.read(_midiData, size);
- _mutex.lock();
+
+ _parser = MidiParser::createParser_SMF();
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
_isLooping = loop;
_isPlaying = true;
- _mutex.unlock();
}
}
-void MidiPlayer::stop() {
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
- }
- _mutex.unlock();
-}
-
-void MidiPlayer::updateTimer() {
- _mutex.lock();
- if (_isPlaying) {
- _parser->onTimer();
- }
- _mutex.unlock();
-}
-
void MidiPlayer::adjustVolume(int diff) {
setVolume(_masterVolume + diff);
}
void MidiPlayer::setVolume(int volume) {
+ // FIXME: This is almost identical to Audio::MidiPlayer::setVolume,
+ // the only difference is that this implementation will always
+ // transmit the volume change, even if the current _masterVolume
+ // equals the new master volume. This *could* make a difference in
+ // some situations.
+ // So, we should determine whether Touche requires this behavioral
+ // difference; and maybe also if other engines could benefit from it
+ // (as hypothetically, it might fix some subtle bugs?)
_masterVolume = CLIP(volume, 0, 255);
- _mutex.lock();
- for (int i = 0; i < NUM_CHANNELS; ++i) {
+ Common::StackLock lock(_mutex);
+ for (int i = 0; i < kNumChannels; ++i) {
if (_channelsTable[i]) {
_channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
}
}
- _mutex.unlock();
-}
-
-int MidiPlayer::open() {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- _driver = MidiDriver::createMidi(dev);
- int ret = _driver->open();
- if (ret == 0) {
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
- }
- return ret;
-}
-
-void MidiPlayer::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _driver;
- _driver = 0;
- _parser->setMidiDriver(NULL);
- delete _parser;
- _mutex.unlock();
}
void MidiPlayer::send(uint32 b) {
- byte volume, ch = (byte)(b & 0xF);
- switch (b & 0xFFF0) {
- case 0x07B0: // volume change
- volume = (byte)((b >> 16) & 0x7F);
- _channelsVolume[ch] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- break;
- case 0x7BB0: // all notes off
- if (!_channelsTable[ch]) {
- // channel not yet allocated, no need to send the event
- return;
- }
- break;
- default:
- if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change
- b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8);
- }
- break;
- }
- if (!_channelsTable[ch]) {
- _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change
+ b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8);
}
- if (_channelsTable[ch]) {
- _channelsTable[ch]->send(b);
- }
-}
-
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
-// warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiPlayer::timerCallback(void *p) {
- MidiPlayer *player = (MidiPlayer *)p;
- player->updateTimer();
+ Audio::MidiPlayer::send(b);
}
} // Touche namespace
diff --git a/engines/touche/midi.h b/engines/touche/midi.h
index 8e43c12037..f0f55e64e6 100644
--- a/engines/touche/midi.h
+++ b/engines/touche/midi.h
@@ -29,7 +29,7 @@
#include "common/util.h"
#include "common/mutex.h"
-#include "audio/mididrv.h"
+#include "audio/midiplayer.h"
class MidiParser;
@@ -39,50 +39,16 @@ namespace Common {
namespace Touche {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
-
- enum {
- NUM_CHANNELS = 16
- };
-
MidiPlayer();
- ~MidiPlayer();
void play(Common::ReadStream &stream, int size, bool loop = false);
- void stop();
- void updateTimer();
void adjustVolume(int diff);
void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
- void setLooping(bool loop) { _isLooping = loop; }
-
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
-private:
-
- static void timerCallback(void *p);
-
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
- int _masterVolume;
- bool _nativeMT32;
- MidiChannel *_channelsTable[NUM_CHANNELS];
- uint8 _channelsVolume[NUM_CHANNELS];
- Common::Mutex _mutex;
- static const uint8 _gmToRol[];
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
};
} // namespace Touche
diff --git a/engines/touche/opcodes.cpp b/engines/touche/opcodes.cpp
index b2b16eb29d..5df0ca3548 100644
--- a/engines/touche/opcodes.cpp
+++ b/engines/touche/opcodes.cpp
@@ -41,7 +41,7 @@ void ToucheEngine::setupOpcodes() {
&ToucheEngine::op_true,
&ToucheEngine::op_false,
&ToucheEngine::op_push,
- &ToucheEngine::op_testFalse,
+ &ToucheEngine::op_not,
/* 0x08 */
&ToucheEngine::op_add,
&ToucheEngine::op_sub,
@@ -51,7 +51,7 @@ void ToucheEngine::setupOpcodes() {
&ToucheEngine::op_mod,
&ToucheEngine::op_and,
&ToucheEngine::op_or,
- &ToucheEngine::op_not,
+ &ToucheEngine::op_neg,
/* 0x10 */
&ToucheEngine::op_testGreater,
&ToucheEngine::op_testEquals,
@@ -250,8 +250,8 @@ void ToucheEngine::op_push() {
*_script.stackDataPtr = 0;
}
-void ToucheEngine::op_testFalse() {
- debugC(9, kDebugOpcodes, "ToucheEngine::op_testFalse()");
+void ToucheEngine::op_not() {
+ debugC(9, kDebugOpcodes, "ToucheEngine::op_not()");
if (*_script.stackDataPtr == 0) {
*_script.stackDataPtr = -1;
} else {
@@ -309,8 +309,8 @@ void ToucheEngine::op_or() {
*_script.stackDataPtr |= val;
}
-void ToucheEngine::op_not() {
- debugC(9, kDebugOpcodes, "ToucheEngine::op_not()");
+void ToucheEngine::op_neg() {
+ debugC(9, kDebugOpcodes, "ToucheEngine::op_neg()");
uint16 val = *_script.stackDataPtr;
*_script.stackDataPtr = ~val;
}
diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp
index df7992f26c..3c108e2931 100644
--- a/engines/touche/resource.cpp
+++ b/engines/touche/resource.cpp
@@ -423,10 +423,7 @@ void ToucheEngine::res_loadRoom(int num) {
_fData.skip(2);
const int roomImageNum = _fData.readUint16LE();
_fData.skip(2);
- for (int i = 0; i < 256; ++i) {
- _fData.read(&_paletteBuffer[i * 4], 3);
- _paletteBuffer[i * 4 + 3] = 0;
- }
+ _fData.read(_paletteBuffer, 3 * 256);
const uint32 offsImage = res_getDataOffset(kResourceTypeRoomImage, roomImageNum);
_fData.seek(offsImage);
diff --git a/engines/touche/staticres.cpp b/engines/touche/staticres.cpp
index a377a6e45f..74aa7954de 100644
--- a/engines/touche/staticres.cpp
+++ b/engines/touche/staticres.cpp
@@ -1822,15 +1822,4 @@ int Graphics::_fontSize = Graphics::_engFontSize;
const uint8 *Graphics::_fontData = Graphics::_engFontData;
-const uint8 MidiPlayer::_gmToRol[] = {
- 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26,
- 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F,
- 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71,
- 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A,
- 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E,
- 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22,
- 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10,
- 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01
-};
-
} // namespace Touche
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index ff8b0d944e..6b47a7fc4d 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -44,7 +44,6 @@ namespace Touche {
ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
: Engine(system), _midiPlayer(0), _language(language) {
-
_saveLoadCurrentPage = 0;
_saveLoadCurrentSlot = 0;
_hideInventoryTexts = false;
@@ -103,9 +102,8 @@ Common::Error ToucheEngine::run() {
_midiPlayer = new MidiPlayer;
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ // Setup mixer
+ syncSoundSettings();
res_openDataFile();
res_allocateTables();
@@ -245,10 +243,9 @@ Common::Point ToucheEngine::getMousePos() const {
}
void ToucheEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
readConfigurationSettings();
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
}
void ToucheEngine::mainLoop() {
@@ -3243,23 +3240,21 @@ void ToucheEngine::clearDirtyRects() {
}
void ToucheEngine::setPalette(int firstColor, int colorCount, int rScale, int gScale, int bScale) {
- uint8 pal[256 * 4];
+ uint8 pal[256 * 3];
for (int i = firstColor; i < firstColor + colorCount; ++i) {
- int r = _paletteBuffer[i * 4 + 0];
+ int r = _paletteBuffer[i * 3 + 0];
r = (r * rScale) >> 8;
- pal[i * 4 + 0] = (uint8)r;
+ pal[i * 3 + 0] = (uint8)r;
- int g = _paletteBuffer[i * 4 + 1];
+ int g = _paletteBuffer[i * 3 + 1];
g = (g * gScale) >> 8;
- pal[i * 4 + 1] = (uint8)g;
+ pal[i * 3 + 1] = (uint8)g;
- int b = _paletteBuffer[i * 4 + 2];
+ int b = _paletteBuffer[i * 3 + 2];
b = (b * bScale) >> 8;
- pal[i * 4 + 2] = (uint8)b;
-
- pal[i * 4 + 3] = 0;
+ pal[i * 3 + 2] = (uint8)b;
}
- _system->getPaletteManager()->setPalette(&pal[firstColor * 4], firstColor, colorCount);
+ _system->getPaletteManager()->setPalette(&pal[firstColor * 3], firstColor, colorCount);
}
void ToucheEngine::updateScreenArea(int x, int y, int w, int h) {
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index 50a5c6e439..1580d072e6 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -531,7 +531,7 @@ protected:
void op_true();
void op_false();
void op_push();
- void op_testFalse();
+ void op_not();
void op_add();
void op_sub();
void op_mul();
@@ -539,7 +539,7 @@ protected:
void op_mod();
void op_and();
void op_or();
- void op_not();
+ void op_neg();
void op_testGreater();
void op_testEquals();
void op_testLower();
@@ -781,7 +781,7 @@ protected:
int _fullRedrawCounter;
int _menuRedrawCounter;
uint8 *_offscreenBuffer;
- uint8 _paletteBuffer[256 * 4];
+ uint8 _paletteBuffer[256 * 3];
Common::Rect _dirtyRectsTable[NUM_DIRTY_RECTS];
int _dirtyRectsTableCount;
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index f0437d2f87..7404abc2e7 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -122,8 +122,8 @@ static const ADParams detectionParams = {
0,
// Flags
0,
- // Additional GUI options (for every game}
- Common::GUIO_NOLAUNCHLOAD,
+ // Additional GUI options (for every game)
+ Common::GUIO_NONE,
// Maximum directory depth
1,
// List of directory globs
@@ -156,6 +156,7 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const {
switch (f) {
case kSupportsListSaves:
+ case kSupportsLoadingDuringStartup:
case kSupportsDeleteSave:
return true;
default:
diff --git a/engines/tucker/graphics.cpp b/engines/tucker/graphics.cpp
index 52018d25e6..163719197d 100644
--- a/engines/tucker/graphics.cpp
+++ b/engines/tucker/graphics.cpp
@@ -112,7 +112,7 @@ void Graphics::decodeRLE_224(uint8 *dst, const uint8 *src, int w, int h) {
}
}
-void Graphics::decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1, int y2, bool xflip) {
+void Graphics::decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1, int y2, bool xflip, bool color248Only) {
int code = 0;
int color = 0;
for (int y = 0; y < h; ++y) {
@@ -125,7 +125,7 @@ void Graphics::decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1,
}
}
if (color != 0) {
- if ((dst[offset] < 0xE0 || y + y1 < y2) && dst[offset] < 0xF8) {
+ if ((color248Only || dst[offset] < 0xE0 || y + y1 < y2) && dst[offset] < 0xF8) {
dst[offset] = color;
}
} else {
diff --git a/engines/tucker/graphics.h b/engines/tucker/graphics.h
index 60c66f519e..c5b723e632 100644
--- a/engines/tucker/graphics.h
+++ b/engines/tucker/graphics.h
@@ -52,7 +52,7 @@ public:
static void decodeRLE(uint8 *dst, const uint8 *src, int w, int h);
static void decodeRLE_224(uint8 *dst, const uint8 *src, int w, int h);
- static void decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1, int y2, bool xflip);
+ static void decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1, int y2, bool xflip, bool color248Only = false);
static void decodeRLE_320(uint8 *dst, const uint8 *src, int w, int h);
static void copyRect(uint8 *dst, int dstPitch, uint8 *src, int srcPitch, int w, int h);
diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp
index 009695e8aa..108c6bcad5 100644
--- a/engines/tucker/locations.cpp
+++ b/engines/tucker/locations.cpp
@@ -660,7 +660,7 @@ void TuckerEngine::execData3PostUpdate_locationNum8() {
_locationBackgroundGfxBuf[offset + 640 * j + i] = colorsTable[(j - 1) * 3 + i + 1];
}
}
- addDirtyRect(_updateLocationXPosTable2[0] - 1, _updateLocationYPosTable2[0] + 1, 3, 4);
+ addDirtyRect(_updateLocationXPosTable2[0] - 1, _updateLocationYPosTable2[0], 3, 4);
_updateLocationYPosTable2[0] += 2;
if (_updateLocationYPosTable2[0] > 120) {
_updateLocationYPosTable2[0] = 0;
@@ -676,7 +676,7 @@ void TuckerEngine::execData3PostUpdate_locationNum8() {
void TuckerEngine::updateSprite_locationNum9_0(int i) {
if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) {
- _spritesTable[0].needUpdate = 1;
+ _spritesTable[i].needUpdate = 1;
_spritesTable[i].state = 3;
} else if (_updateLocationCounter2 > 0 || getRandomNumber() > 30000) {
_spritesTable[i].state = 1;
@@ -974,7 +974,7 @@ void TuckerEngine::updateSprite_locationNum14(int i) {
}
void TuckerEngine::execData3PreUpdate_locationNum14() {
- if (_yPosCurrent >= 126)
+ if (_yPosCurrent >= 127)
return;
if (!isSoundPlaying(0)) {
@@ -1021,7 +1021,7 @@ void TuckerEngine::execData3PreUpdate_locationNum14() {
}
void TuckerEngine::execData3PreUpdate_locationNum14Helper1(int i) {
- const int y = 1872; // FIXME: bug, 187/182 ?
+ const int y = 117 * 16;
if (_updateLocation14ObjNum[i] == 0) {
if (getRandomNumber() <= 30000) {
return;
@@ -1031,9 +1031,8 @@ void TuckerEngine::execData3PreUpdate_locationNum14Helper1(int i) {
_updateLocation14Step[i] = -55 - getRandomNumber() / 512;
_updateLocation14ObjNum[i] = 231;
_updateLocation14Delay[i] = 16 + getRandomNumber() / 2048;
- // FIXME: bug, missing return ?
}
- _updateLocation14Step[i] = 4;
+ _updateLocation14Step[i] += 4;
_updateLocationYPosTable2[i] += _updateLocation14Step[i];
if (_updateLocationYPosTable2[i] > y) {
_updateLocationYPosTable2[i] = y;
@@ -1792,11 +1791,11 @@ void TuckerEngine::execData3PreUpdate_locationNum29() {
_updateLocationFadePaletteCounter = 0;
}
const int d = _updateLocationFadePaletteCounter / 2;
- uint8 scrollPal[5 * 4];
+ uint8 scrollPal[5 * 3];
for (int i = 0; i < 5; ++i) {
- scrollPal[i * 4] = r[i + d];
- scrollPal[i * 4 + 1] = g[i + d];
- scrollPal[i * 4 + 2] = b[i + d];
+ scrollPal[i * 3] = r[i + d];
+ scrollPal[i * 3 + 1] = g[i + d];
+ scrollPal[i * 3 + 2] = b[i + d];
}
_system->getPaletteManager()->setPalette(scrollPal, 118, 5);
if (_flagsTable[143] == 1) {
@@ -2484,7 +2483,8 @@ void TuckerEngine::updateSprite_locationNum58(int i) {
}
void TuckerEngine::execData3PreUpdate_locationNum58() {
- if (_flagsTable[190] < 3 && _xPosCurrent > 310) {
+ // workaround original game glitch #2872348: do not change position on location change
+ if (_nextLocationNum == 0 && _flagsTable[190] < 3 && _xPosCurrent > 310) {
_xPosCurrent = 310;
_panelLockedFlag = 0;
}
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index 6b6ab1e600..c0f1baae99 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -383,26 +383,28 @@ void TuckerEngine::loadPanel() {
}
void TuckerEngine::loadBudSpr(int startOffset) {
- int endOffset = loadCTable01(0, startOffset);
+ int framesCount[20];
+ memset(framesCount, 0, sizeof(framesCount));
+ int endOffset = loadCTable01(0, startOffset, framesCount);
loadCTable02(0);
int frame = 0;
int spriteOffset = 0;
for (int i = startOffset; i < endOffset; ++i) {
- if (_ctable01Table_sprite[frame] == i) {
+ if (framesCount[frame] == i) {
char filename[40];
switch (_flagsTable[137]) {
case 0:
if ((_gameFlags & kGameFlagDemo) != 0) {
- sprintf(filename, "budl00_%d.pcx", frame + 1);
+ snprintf(filename, sizeof(filename), "budl00_%d.pcx", frame + 1);
} else {
- sprintf(filename, "bud_%d.pcx", frame + 1);
+ snprintf(filename, sizeof(filename), "bud_%d.pcx", frame + 1);
}
break;
case 1:
- sprintf(filename, "peg_%d.pcx", frame + 1);
+ snprintf(filename, sizeof(filename), "peg_%d.pcx", frame + 1);
break;
default:
- sprintf(filename, "mac_%d.pcx", frame + 1);
+ snprintf(filename, sizeof(filename), "mac_%d.pcx", frame + 1);
break;
}
loadImage(filename, _loadTempBuf, 0);
@@ -414,7 +416,7 @@ void TuckerEngine::loadBudSpr(int startOffset) {
}
}
-int TuckerEngine::loadCTable01(int index, int firstSpriteNum) {
+int TuckerEngine::loadCTable01(int index, int firstSpriteNum, int *framesCount) {
loadFile("ctable01.c", _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
int lastSpriteNum = firstSpriteNum;
@@ -425,7 +427,7 @@ int TuckerEngine::loadCTable01(int index, int firstSpriteNum) {
if (x < 0) {
break;
} else if (x == 999) {
- _ctable01Table_sprite[count] = lastSpriteNum;
+ framesCount[count] = lastSpriteNum;
++count;
continue;
}
@@ -444,7 +446,7 @@ int TuckerEngine::loadCTable01(int index, int firstSpriteNum) {
}
}
}
- _ctable01Table_sprite[count] = -1;
+ framesCount[count] = -1;
return lastSpriteNum;
}
@@ -483,25 +485,25 @@ void TuckerEngine::loadLoc() {
int i = _locationWidthTable[_locationNum];
_locationHeight = (_locationNum < 73) ? 140 : 200;
- sprintf(filename, (i == 1) ? "loc%02d.pcx" : "loc%02da.pcx", _locationNum);
+ snprintf(filename, sizeof(filename), (i == 1) ? "loc%02d.pcx" : "loc%02da.pcx", _locationNum);
copyLocBitmap(filename, 0, false);
Graphics::copyRect(_quadBackgroundGfxBuf, 320, _locationBackgroundGfxBuf, 640, 320, _locationHeight);
if (_locationHeight == 200) {
return;
}
- sprintf(filename, (i != 2) ? "path%02d.pcx" : "path%02da.pcx", _locationNum);
+ snprintf(filename, sizeof(filename), (i != 2) ? "path%02d.pcx" : "path%02da.pcx", _locationNum);
copyLocBitmap(filename, 0, true);
if (i > 1) {
- sprintf(filename, "loc%02db.pcx", _locationNum);
+ snprintf(filename, sizeof(filename), "loc%02db.pcx", _locationNum);
copyLocBitmap(filename, 320, false);
Graphics::copyRect(_quadBackgroundGfxBuf + 44800, 320, _locationBackgroundGfxBuf + 320, 640, 320, _locationHeight);
if (i == 2) {
- sprintf(filename, "path%02db.pcx", _locationNum);
+ snprintf(filename, sizeof(filename), "path%02db.pcx", _locationNum);
copyLocBitmap(filename, 320, true);
}
}
if (i > 2) {
- sprintf(filename, "loc%02dc.pcx", _locationNum);
+ snprintf(filename, sizeof(filename), "loc%02dc.pcx", _locationNum);
copyLocBitmap(filename, 0, false);
Graphics::copyRect(_quadBackgroundGfxBuf + 89600, 320, _locationBackgroundGfxBuf, 640, 320, 140);
}
@@ -510,7 +512,7 @@ void TuckerEngine::loadLoc() {
loadImage("rochpath.pcx", _loadLocBufPtr, 0);
}
if (i > 3) {
- sprintf(filename, "loc%02dd.pcx", _locationNum);
+ snprintf(filename, sizeof(filename), "loc%02dd.pcx", _locationNum);
copyLocBitmap(filename, 0, false);
Graphics::copyRect(_quadBackgroundGfxBuf + 134400, 320, _locationBackgroundGfxBuf + 320, 640, 320, 140);
}
@@ -541,10 +543,10 @@ void TuckerEngine::loadObj() {
_currentPartNum = _partNum;
char filename[40];
- sprintf(filename, "objtxt%d.c", _partNum);
+ snprintf(filename, sizeof(filename), "objtxt%d.c", _partNum);
free(_objTxtBuf);
_objTxtBuf = loadFile(filename, 0);
- sprintf(filename, "pt%dtext.c", _partNum);
+ snprintf(filename, sizeof(filename), "pt%dtext.c", _partNum);
free(_ptTextBuf);
_ptTextBuf = loadFile(filename, 0);
_characterSpeechDataPtr = _ptTextBuf;
@@ -585,7 +587,7 @@ void TuckerEngine::loadData() {
int offset = 0;
for (int i = 0; i < count; ++i) {
char filename[40];
- sprintf(filename, "scrobj%d%d.pcx", _partNum, i);
+ snprintf(filename, sizeof(filename), "scrobj%d%d.pcx", _partNum, i);
loadImage(filename, _loadTempBuf, 0);
offset = loadDataHelper(offset, i);
}
@@ -604,7 +606,7 @@ int TuckerEngine::loadDataHelper(int offset, int index) {
void TuckerEngine::loadPanObj() {
char filename[40];
- sprintf(filename, "panobjs%d.pcx", _partNum);
+ snprintf(filename, sizeof(filename), "panobjs%d.pcx", _partNum);
loadImage(filename, _loadTempBuf, 0);
int offset = 0;
for (int y = 0; y < 5; ++y) {
@@ -813,7 +815,7 @@ void TuckerEngine::loadSprA02_01() {
const int count = _sprA02LookupTable[_locationNum];
for (int i = 1; i < count + 1; ++i) {
char filename[40];
- sprintf(filename, "sprites/a%02d_%02d.spr", _locationNum, i);
+ snprintf(filename, sizeof(filename), "sprites/a%02d_%02d.spr", _locationNum, i);
_sprA02Table[i] = loadFile(filename, 0);
}
_sprA02Table[0] = _sprA02Table[1];
@@ -832,7 +834,7 @@ void TuckerEngine::loadSprC02_01() {
const int count = _sprC02LookupTable[_locationNum];
for (int i = 1; i < count + 1; ++i) {
char filename[40];
- sprintf(filename, "sprites/c%02d_%02d.spr", _locationNum, i);
+ snprintf(filename, sizeof(filename), "sprites/c%02d_%02d.spr", _locationNum, i);
_sprC02Table[i] = loadFile(filename, 0);
}
_sprC02Table[0] = _sprC02Table[1];
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index 73018b8c00..5e99e3ccef 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -110,7 +110,6 @@ void TuckerEngine::handleCreditsSequence() {
}
redrawScreen(0);
waitForTimer(3);
- _timerCounter1 = 0;
counter4 = _timerCounter2 / 3;
if (counter4 == _creditsSequenceTimecounts[num]) {
_fadePaletteCounter = 0;
@@ -119,7 +118,7 @@ void TuckerEngine::handleCreditsSequence() {
char filename[40];
if (num == 6) {
for (int i = 0; i < 16; ++i) {
- sprintf(filename, "cogs%04d.pcx", i + 1);
+ snprintf(filename, sizeof(filename), "cogs%04d.pcx", i + 1);
loadImage(filename, imgBuf + i * 64000, 2);
}
} else {
@@ -678,14 +677,14 @@ void AnimationSequencePlayer::updateSounds() {
}
void AnimationSequencePlayer::fadeInPalette() {
- uint8 paletteBuffer[256 * 4];
+ uint8 paletteBuffer[256 * 3];
memset(paletteBuffer, 0, sizeof(paletteBuffer));
bool fadeColors = true;
for (int step = 0; step < 64; ++step) {
if (fadeColors) {
fadeColors = false;
- for (int i = 0; i < 1024; ++i) {
- if ((i & 3) != 3 && paletteBuffer[i] < _animationPalette[i]) {
+ for (int i = 0; i < 3*256; ++i) {
+ if (paletteBuffer[i] < _animationPalette[i]) {
const int color = paletteBuffer[i] + 4;
paletteBuffer[i] = MIN<int>(color, _animationPalette[i]);
fadeColors = true;
@@ -699,14 +698,14 @@ void AnimationSequencePlayer::fadeInPalette() {
}
void AnimationSequencePlayer::fadeOutPalette() {
- uint8 paletteBuffer[256 * 4];
- memcpy(paletteBuffer, _animationPalette, 1024);
+ uint8 paletteBuffer[256 * 3];
+ memcpy(paletteBuffer, _animationPalette, 3*256);
bool fadeColors = true;
for (int step = 0; step < 64; ++step) {
if (fadeColors) {
fadeColors = false;
- for (int i = 0; i < 1024; ++i) {
- if ((i & 3) != 3 && paletteBuffer[i] > 0) {
+ for (int i = 0; i < 3*256; ++i) {
+ if (paletteBuffer[i] > 0) {
const int color = paletteBuffer[i] - 4;
paletteBuffer[i] = MAX<int>(0, color);
fadeColors = true;
@@ -742,13 +741,7 @@ uint8 *AnimationSequencePlayer::loadPicture(const char *fileName) {
}
void AnimationSequencePlayer::getRGBPalette(int index) {
- const byte *rgbPalette = _flicPlayer[index].getPalette();
- for (int i = 0; i < 256; i++) {
- _animationPalette[i * 4 + 0] = rgbPalette[i * 3 + 0];
- _animationPalette[i * 4 + 1] = rgbPalette[i * 3 + 1];
- _animationPalette[i * 4 + 2] = rgbPalette[i * 3 + 2];
- _animationPalette[i * 4 + 3] = 0;
- }
+ memcpy(_animationPalette, _flicPlayer[index].getPalette(), 3 * 256);
}
void AnimationSequencePlayer::openAnimation(int index, const char *fileName) {
@@ -828,9 +821,7 @@ void AnimationSequencePlayer::displayLoadingScreen() {
if (f.open("graphics/loading.pic")) {
fadeOutPalette();
f.seek(32);
- for (int i = 0; i < 1024; i += 4) {
- f.read(_animationPalette + i, 3);
- }
+ f.read(_animationPalette, 3 * 256);
f.read(_offscreenBuffer, 64000);
_system->copyRectToScreen(_offscreenBuffer, 320, 0, 0, kScreenWidth, kScreenHeight);
fadeInPalette();
@@ -847,12 +838,7 @@ void AnimationSequencePlayer::initPicPart4() {
void AnimationSequencePlayer::drawPicPart4() {
static const uint8 offsets[] = { 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 };
if (_updateScreenIndex == -1) {
- for (int i = 0; i < 256; ++i) {
- if (memcmp(_animationPalette + i * 4, _picBufPtr + 32 + i * 3, 3) != 0) {
- memcpy(_animationPalette + i * 4, _picBufPtr + 32 + i * 3, 3);
- _animationPalette[i * 4 + 3] = 0;
- }
- }
+ memcpy(_animationPalette, _picBufPtr + 32, 3 * 256);
}
if (_updateScreenCounter == 0) {
static const uint8 counter[] = { 1, 2, 3, 4, 5, 35, 5, 4, 3, 2, 1 };
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index c61a4228c6..e41cbfbeef 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -68,12 +68,6 @@ Common::Error TuckerEngine::run() {
return Common::kNoError;
}
-void TuckerEngine::syncSoundSettings() {
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
-}
-
int TuckerEngine::getRandomNumber() {
return _rnd.getRandomNumber(0x7FFF);
}
@@ -127,13 +121,10 @@ void TuckerEngine::restart() {
_syncCounter = 0;
_lastFrameTime = _system->getMillis();
_mainLoopCounter1 = _mainLoopCounter2 = 0;
- _timerCounter1 = _timerCounter2 = 0;
+ _timerCounter2 = 0;
_partNum = _currentPartNum = 0;
_locationNum = 0;
- _nextLocationNum = ConfMan.getInt("boot_param");
- if (_nextLocationNum == 0) {
- _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo;
- }
+ _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo;
_gamePaused = false;
_gameDebug = false;
_displayGameHints = false;
@@ -273,7 +264,6 @@ void TuckerEngine::restart() {
_xPosCurrent = 160;
_characterSpeechDataPtr = 0;
_ptTextOffset = 0;
- memset(_ctable01Table_sprite, 0, sizeof(_ctable01Table_sprite));
memset(_characterAnimationsTable, 0, sizeof(_characterAnimationsTable));
memset(_characterStateTable, 0, sizeof(_characterStateTable));
_backgroundSprOffset = 0;
@@ -360,6 +350,15 @@ void TuckerEngine::mainLoop() {
_spriteAnimationFrameIndex = _spriteAnimationsTable[14].firstFrameIndex;
+ if (ConfMan.hasKey("save_slot")) {
+ const int slot = ConfMan.getInt("save_slot");
+ if (slot >= 0 && slot <= kLastSaveSlot) {
+ loadGameState(slot);
+ }
+ } else if (ConfMan.hasKey("boot_param")) {
+ _nextLocationNum = ConfMan.getInt("boot_param");
+ }
+
do {
++_syncCounter;
if (_flagsTable[137] != _flagsTable[138]) {
@@ -556,13 +555,7 @@ void TuckerEngine::mainLoop() {
if (_inputKeys[kInputKeyToggleTextSpeech]) {
_inputKeys[kInputKeyToggleTextSpeech] = false;
if ((_gameFlags & kGameFlagNoSubtitles) == 0) {
- if (_displaySpeechText) {
- _displaySpeechText = false;
-// kDefaultCharSpeechSoundCounter = 1;
- } else {
- _displaySpeechText = true;
-// kDefaultCharSpeechSoundCounter = 70;
- }
+ _displaySpeechText = !_displaySpeechText;
ConfMan.setBool("subtitles", _displaySpeechText);
}
}
@@ -595,13 +588,11 @@ void TuckerEngine::mainLoop() {
void TuckerEngine::waitForTimer(int ticksCount) {
uint32 end = _lastFrameTime + ticksCount * 1000 / 46;
do {
- ++_timerCounter1;
parseEvents();
_system->delayMillis(10);
_lastFrameTime = _system->getMillis();
} while (!_fastMode && _lastFrameTime < end);
_timerCounter2 += ticksCount;
- _timerCounter1 = 0;
}
void TuckerEngine::parseEvents() {
@@ -674,8 +665,8 @@ void TuckerEngine::updateCursorPos(int x, int y) {
void TuckerEngine::setCursorNum(int num) {
_cursorNum = num;
- const int cursorW = 16;
- const int cursorH = 16;
+ static const int cursorW = 16;
+ static const int cursorH = 16;
CursorMan.replaceCursor(_cursorGfxBuf + _cursorNum * 256, cursorW, cursorH, 1, 1, 0);
}
@@ -942,31 +933,29 @@ void TuckerEngine::updateFlagsForCharPosition() {
}
void TuckerEngine::fadeOutPalette(int colorsCount) {
- uint8 pal[256 * 4];
+ uint8 pal[256 * 3];
_system->getPaletteManager()->grabPalette(pal, 0, colorsCount);
for (int color = 0; color < colorsCount; ++color) {
for (int i = 0; i < 3; ++i) {
- const int c = int(pal[color * 4 + i]) + kFadePaletteStep * 4;
- pal[color * 4 + i] = MIN<int>(c, _currentPalette[color * 3 + i]);
+ const int c = int(pal[color * 3 + i]) + kFadePaletteStep * 3;
+ pal[color * 3 + i] = MIN<int>(c, _currentPalette[color * 3 + i]);
}
}
_system->getPaletteManager()->setPalette(pal, 0, colorsCount);
_system->updateScreen();
- waitForTimer(1);
}
void TuckerEngine::fadeInPalette(int colorsCount) {
- uint8 pal[256 * 4];
+ uint8 pal[256 * 3];
_system->getPaletteManager()->grabPalette(pal, 0, colorsCount);
for (int color = 0; color < colorsCount; ++color) {
for (int i = 0; i < 3; ++i) {
- const int c = int(pal[color * 4 + i]) - kFadePaletteStep * 4;
- pal[color * 4 + i] = MAX<int>(c, 0);
+ const int c = int(pal[color * 3 + i]) - kFadePaletteStep * 3;
+ pal[color * 3 + i] = MAX<int>(c, 0);
}
}
_system->getPaletteManager()->setPalette(pal, 0, colorsCount);
_system->updateScreen();
- waitForTimer(1);
}
void TuckerEngine::fadePaletteColor(int color, int step) {
@@ -980,7 +969,7 @@ void TuckerEngine::fadePaletteColor(int color, int step) {
}
void TuckerEngine::setBlackPalette() {
- uint8 pal[256 * 4];
+ uint8 pal[256 * 3];
memset(pal, 0, sizeof(pal));
_system->getPaletteManager()->setPalette(pal, 0, 256);
}
@@ -1098,17 +1087,15 @@ void TuckerEngine::stopSounds() {
}
void TuckerEngine::playSounds() {
- for (int i = 0; i < 29; ++i) {
- if (i < _locationSoundsCount) {
- if (_locationSoundsTable[i].type == 1 || _locationSoundsTable[i].type == 2 || _locationSoundsTable[i].type == 5 ||
- (_locationSoundsTable[i].type == 7 && _flagsTable[_locationSoundsTable[i].flagNum] == _locationSoundsTable[i].flagValueStartFx)) {
- startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
- }
+ for (int i = 0; i < _locationSoundsCount; ++i) {
+ if (_locationSoundsTable[i].type == 1 || _locationSoundsTable[i].type == 2 || _locationSoundsTable[i].type == 5 ||
+ (_locationSoundsTable[i].type == 7 && _flagsTable[_locationSoundsTable[i].flagNum] == _locationSoundsTable[i].flagValueStartFx)) {
+ startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
}
- if (i < _locationMusicsCount) {
- if (_locationMusicsTable[i].flag > 0) {
- startMusic(_locationMusicsTable[i].offset, i, _locationMusicsTable[i].volume);
- }
+ }
+ for (int i = 0; i < _locationMusicsCount; ++i) {
+ if (_locationMusicsTable[i].flag > 0) {
+ startMusic(_locationMusicsTable[i].offset, i, _locationMusicsTable[i].volume);
}
}
}
@@ -1430,7 +1417,6 @@ void TuckerEngine::redrawPanelOverBackground() {
}
void TuckerEngine::drawConversationTexts() {
- int x = 0;
int y = 141;
int flag = 0;
for (int i = 0; i < _conversationOptionsCount; ++i) {
@@ -1438,7 +1424,7 @@ void TuckerEngine::drawConversationTexts() {
if ((_mousePosY > y && _mousePosY < y + 11) || _nextTableToLoadIndex == i) {
color = 106;
}
- drawSpeechText(x, y, _characterSpeechDataPtr, _instructionsActionsTable[i], color);
+ drawSpeechText(0, y, _characterSpeechDataPtr, _instructionsActionsTable[i], color);
if (_mousePosY > y && _mousePosY < _conversationOptionLinesCount * 10 + y + 1) {
_nextTableToLoadIndex = i;
flag = 1;
@@ -1757,6 +1743,8 @@ void TuckerEngine::drawCurrentSprite() {
if ((_locationNum == 17 || _locationNum == 18) && _currentSpriteAnimationFrame == 16) {
return;
}
+ // Workaround original game glitch: location 14 contains some colors from [0xE0-0xF8] in a walkable area (tracker item #3106542)
+ const bool color248Only = (_locationNum == 14);
SpriteFrame *chr = &_spriteFramesTable[_currentSpriteAnimationFrame];
int yPos = _yPosCurrent + _mainSpritesBaseOffset - 54 + chr->yOffset;
int xPos = _xPosCurrent;
@@ -1766,7 +1754,7 @@ void TuckerEngine::drawCurrentSprite() {
xPos -= chr->xSize + chr->xOffset - 14;
}
Graphics::decodeRLE_248(_locationBackgroundGfxBuf + yPos * 640 + xPos, _spritesGfxBuf + chr->sourceOffset, chr->xSize, chr->ySize,
- chr->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0);
+ chr->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0, color248Only);
addDirtyRect(xPos, yPos, chr->xSize, chr->ySize);
if (_currentSpriteAnimationLength > 1) {
SpriteFrame *chr2 = &_spriteFramesTable[_currentSpriteAnimationFrame2];
@@ -1778,7 +1766,7 @@ void TuckerEngine::drawCurrentSprite() {
xPos -= chr2->xSize + chr2->xOffset - 14;
}
Graphics::decodeRLE_248(_locationBackgroundGfxBuf + yPos * 640 + xPos, _spritesGfxBuf + chr2->sourceOffset, chr2->xSize, chr2->ySize,
- chr2->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0);
+ chr2->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0, color248Only);
addDirtyRect(xPos, yPos, chr2->xSize, chr2->ySize);
}
}
@@ -1929,7 +1917,9 @@ void TuckerEngine::drawSprite(int num) {
Graphics::decodeRLE_248(dstPtr, srcPtr, srcW, srcH, 0, s->yMaxBackground, s->flipX != 0);
break;
}
- addDirtyRect(xPos, srcY, srcW, srcH);
+ const int xR = srcX + (s->gfxBackgroundOffset % 640);
+ const int yR = srcY + (s->gfxBackgroundOffset / 640);
+ addDirtyRect(xR, yR, srcW, srcH);
}
}
@@ -1980,12 +1970,10 @@ void TuckerEngine::drawInfoString() {
if (_actionRequiresTwoObjects) {
verbPreposition = (_actionVerb == 5) ? 12 : 11;
verbPrepositionWidth = getStringWidth(verbPreposition, infoStrBuf) + 4;
- if (_gameLang == Common::FR_FRA || _gameLang == Common::DE_DEU) {
- if ((_actionObj2Num > 0 || _actionObj2Type > 0) && verbPreposition > 0) {
- infoStringWidth = 0;
- verbWidth = 0;
- object1NameWidth = 0;
- }
+ if (_gameLang != Common::EN_ANY && (_actionObj2Num > 0 || _actionObj2Type > 0) && verbPreposition > 0) {
+ infoStringWidth = 0;
+ verbWidth = 0;
+ object1NameWidth = 0;
}
infoStringWidth += verbPrepositionWidth;
if (_actionObj2Num > 0 || _actionObj2Type > 0) {
@@ -1993,7 +1981,7 @@ void TuckerEngine::drawInfoString() {
}
}
const int xPos = 159 - infoStringWidth / 2;
- if (verbPreposition == 0 || (_actionObj2Num == 0 && _actionObj2Type == 0)) {
+ if (_gameLang == Common::EN_ANY || (_actionObj2Num == 0 && _actionObj2Type == 0) || verbPreposition == 0) {
drawItemString(xPos, _actionVerb + 1, infoStrBuf);
if (_actionObj1Num > 0 || _actionObj1Type > 0) {
drawItemString(xPos + 4 + verbWidth, _actionObj1Num + 1, obj1StrBuf);
@@ -2891,7 +2879,11 @@ void TuckerEngine::updateCharSpeechSound(bool displayText) {
if (_charSpeechSoundCounter == 0) {
return;
}
- --_charSpeechSoundCounter;
+ if (_displaySpeechText) {
+ _charSpeechSoundCounter = 0;
+ } else {
+ --_charSpeechSoundCounter;
+ }
if (_charSpeechSoundCounter == 0) {
_charSpeechSoundCounter = isSpeechSoundPlaying() ? 1 : 0;
if (_charSpeechSoundCounter == 0) {
@@ -3091,6 +3083,11 @@ int TuckerEngine::readTableInstructionCode(int *index) {
}
int TuckerEngine::readTableInstructionParam(int len) {
+ // skip duplicated minus signs (bua,--1, c0a,--1, ...)
+ if (len >= 3 && memcmp(_tableInstructionsPtr, "--", 2) == 0) {
+ ++_tableInstructionsPtr;
+ --len;
+ }
char *end = 0;
const int param = strtol((const char *)_tableInstructionsPtr, &end, 10);
if (end != (const char *)_tableInstructionsPtr + len) {
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index 4d7b530bbc..532892fd48 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -280,7 +280,6 @@ public:
virtual Common::Error run();
virtual bool hasFeature(EngineFeature f) const;
- virtual void syncSoundSettings();
GUI::Debugger *getDebugger() { return _console; }
protected:
@@ -593,7 +592,7 @@ protected:
void loadCharSizeDta();
void loadPanel();
void loadBudSpr(int startOffset);
- int loadCTable01(int index, int firstSpriteNum);
+ int loadCTable01(int index, int firstSpriteNum, int *framesCount);
void loadCTable02(int fl);
void loadLoc();
void loadObj();
@@ -624,7 +623,6 @@ protected:
uint32 _lastFrameTime;
int _mainLoopCounter1;
int _mainLoopCounter2;
- int _timerCounter1;
int _timerCounter2;
int _flagsTable[kFlagsTableSize];
int _partNum;
@@ -803,7 +801,6 @@ protected:
int _yPosCurrent;
const uint8 *_characterSpeechDataPtr;
int _ptTextOffset;
- int _ctable01Table_sprite[20];
int _characterAnimationsTable[200];
int _characterStateTable[200];
int _backgroundSprOffset;
@@ -977,7 +974,7 @@ private:
const SequenceUpdateFunc *_updateFunc;
int _updateFuncIndex;
Video::FlicDecoder _flicPlayer[2];
- uint8 _animationPalette[256 * 4];
+ uint8 _animationPalette[256 * 3];
int _soundSeqDataCount;
int _soundSeqDataIndex;
const SoundSequenceData *_soundSeqData;
diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp
index fe90545280..8f31421a8b 100644
--- a/graphics/cursorman.cpp
+++ b/graphics/cursorman.cpp
@@ -206,7 +206,7 @@ void CursorManager::replaceCursorPalette(const byte *colors, uint start, uint nu
}
Palette *pal = _cursorPaletteStack.top();
- uint size = 4 * num;
+ uint size = 3 * num;
if (pal->_size < size) {
// Could not re-use the old buffer. Create a new one.
@@ -219,7 +219,7 @@ void CursorManager::replaceCursorPalette(const byte *colors, uint start, uint nu
pal->_num = num;
if (num) {
- memcpy(pal->_data, colors, 4 * num);
+ memcpy(pal->_data, colors, size);
g_system->setCursorPalette(pal->_data, pal->_start, pal->_num);
} else {
g_system->disableCursorPalette(true);
@@ -256,7 +256,7 @@ CursorManager::Cursor::~Cursor() {
CursorManager::Palette::Palette(const byte *colors, uint start, uint num) {
_start = start;
_num = num;
- _size = 4 * num;
+ _size = 3 * num;
if (num) {
_data = new byte[_size];
diff --git a/graphics/cursorman.h b/graphics/cursorman.h
index c041beb957..2f3891aee7 100644
--- a/graphics/cursorman.h
+++ b/graphics/cursorman.h
@@ -130,7 +130,7 @@ public:
* The palette entries from 'start' till (start+num-1) will be replaced
* so a full palette updated is accomplished via start=0, num=256.
*
- * The palette data is specified in the same interleaved RGBA format as
+ * The palette data is specified in the same interleaved RGB format as
* used by all backends.
*
* @param colors the new palette data, in interleaved RGB format
diff --git a/graphics/dither.cpp b/graphics/dither.cpp
index 6a37679b0a..5f423d1c7a 100644
--- a/graphics/dither.cpp
+++ b/graphics/dither.cpp
@@ -174,7 +174,7 @@ bool PaletteLUT::save(Common::WriteStream &stream) {
while (_got < _dim1)
buildNext();
- stream.writeUint32BE(MKID_BE('PLUT')); // Magic
+ stream.writeUint32BE(MKTAG('P','L','U','T')); // Magic
stream.writeUint32BE(kVersion);
stream.writeByte(_depth1);
if (stream.write(_realPal, 768) != 768)
@@ -200,7 +200,7 @@ bool PaletteLUT::load(Common::SeekableReadStream &stream) {
return false;
// Magic
- if (stream.readUint32BE() != MKID_BE('PLUT'))
+ if (stream.readUint32BE() != MKTAG('P','L','U','T'))
return false;
if (stream.readUint32BE() != kVersion)
diff --git a/graphics/fonts/winfont.cpp b/graphics/fonts/winfont.cpp
index fb37c8ddef..12509fd9e1 100644
--- a/graphics/fonts/winfont.cpp
+++ b/graphics/fonts/winfont.cpp
@@ -23,8 +23,9 @@
*/
#include "common/file.h"
-#include "common/ne_exe.h"
#include "common/str.h"
+#include "common/winexe_ne.h"
+#include "common/winexe_pe.h"
#include "graphics/fonts/winfont.h"
namespace Graphics {
@@ -75,8 +76,15 @@ static WinFontDirEntry readDirEntry(Common::SeekableReadStream &stream) {
}
bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry &dirEntry) {
- // TODO: PE libraries (If it's used anywhere by a ScummVM game)
+ // First try loading via the NE code
+ if (loadFromNE(fileName, dirEntry))
+ return true;
+ // Then try loading via the PE code
+ return loadFromPE(fileName, dirEntry);
+}
+
+bool WinFont::loadFromNE(const Common::String &fileName, const WinFontDirEntry &dirEntry) {
Common::NEResources exe;
if (!exe.loadFromEXE(fileName))
@@ -89,44 +97,53 @@ bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry
return false;
}
- uint16 numFonts = fontDirectory->readUint16LE();
+ uint32 fontId = getFontIndex(*fontDirectory, dirEntry);
+
+ delete fontDirectory;
- // Probably not possible, so this is really a sanity check
- if (numFonts == 0) {
- warning("No fonts in '%s'", fileName.c_str());
+ // Couldn't match the face name
+ if (fontId == 0xffffffff) {
+ warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(), fileName.c_str());
return false;
}
- // Scour the directory for our matching name
- int fontId = -1;
- for (uint16 i = 0; i < numFonts; i++) {
- uint16 id = fontDirectory->readUint16LE();
+ // Actually go get our font now...
+ Common::SeekableReadStream *fontStream = exe.getResource(Common::kNEFont, fontId);
+ if (!fontStream) {
+ warning("Could not find font %d in %s", fontId, fileName.c_str());
+ return false;
+ }
- if (dirEntry.faceName.empty()) {
- // Use the first name when empty
- fontId = id;
- break;
- }
+ bool ok = loadFromFNT(*fontStream);
+ delete fontStream;
+ return ok;
+}
- WinFontDirEntry entry = readDirEntry(*fontDirectory);
+bool WinFont::loadFromPE(const Common::String &fileName, const WinFontDirEntry &dirEntry) {
+ Common::PEResources exe;
- if (dirEntry.faceName.equalsIgnoreCase(entry.faceName) && dirEntry.points == entry.points) {
- // Match!
- fontId = id;
- break;
- }
+ if (!exe.loadFromEXE(fileName))
+ return false;
+
+ // Let's pull out the font directory
+ Common::SeekableReadStream *fontDirectory = exe.getResource(Common::kPEFontDir, Common::String("FONTDIR"));
+ if (!fontDirectory) {
+ warning("No font directory in '%s'", fileName.c_str());
+ return false;
}
+ uint32 fontId = getFontIndex(*fontDirectory, dirEntry);
+
delete fontDirectory;
// Couldn't match the face name
- if (fontId < 0) {
+ if (fontId == 0xffffffff) {
warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(), fileName.c_str());
return false;
}
// Actually go get our font now...
- Common::SeekableReadStream *fontStream = exe.getResource(Common::kNEFont, fontId);
+ Common::SeekableReadStream *fontStream = exe.getResource(Common::kPEFont, fontId);
if (!fontStream) {
warning("Could not find font %d in %s", fontId, fileName.c_str());
return false;
@@ -137,6 +154,32 @@ bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry
return ok;
}
+uint32 WinFont::getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry) {
+ uint16 numFonts = stream.readUint16LE();
+
+ // Probably not possible, so this is really a sanity check
+ if (numFonts == 0) {
+ warning("No fonts in exe");
+ return 0xffffffff;
+ }
+
+ // Scour the directory for our matching name
+ for (uint16 i = 0; i < numFonts; i++) {
+ uint16 id = stream.readUint16LE();
+
+ // Use the first name when empty
+ if (dirEntry.faceName.empty())
+ return id;
+
+ WinFontDirEntry entry = readDirEntry(stream);
+
+ if (dirEntry.faceName.equalsIgnoreCase(entry.faceName) && dirEntry.points == entry.points) // Match!
+ return id;
+ }
+
+ return 0xffffffff;
+}
+
bool WinFont::loadFromFNT(const Common::String &fileName) {
Common::File file;
diff --git a/graphics/fonts/winfont.h b/graphics/fonts/winfont.h
index b23455e2d5..fbe4a778e2 100644
--- a/graphics/fonts/winfont.h
+++ b/graphics/fonts/winfont.h
@@ -69,6 +69,10 @@ public:
void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const;
private:
+ bool loadFromPE(const Common::String &fileName, const WinFontDirEntry &dirEntry);
+ bool loadFromNE(const Common::String &fileName, const WinFontDirEntry &dirEntry);
+
+ uint32 getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry);
bool loadFromFNT(Common::SeekableReadStream &stream);
char indexToCharacter(uint16 index) const;
uint16 characterToIndex(byte character) const;
diff --git a/graphics/jpeg.cpp b/graphics/jpeg.cpp
index aa4b876680..169c3b5f1b 100644
--- a/graphics/jpeg.cpp
+++ b/graphics/jpeg.cpp
@@ -46,7 +46,7 @@ static const uint8 _zigZagOrder[64] = {
};
// IDCT table built with :
-// _idct8x8[x][y] = cos(((2 * x + 1) * y) * (PI / 16.0)) * 0.5;
+// _idct8x8[x][y] = cos(((2 * x + 1) * y) * (M_PI / 16.0)) * 0.5;
// _idct8x8[x][y] /= sqrt(2.0) if y == 0
static const double _idct8x8[8][8] = {
{ 0.353553390593274, 0.490392640201615, 0.461939766255643, 0.415734806151273, 0.353553390593274, 0.277785116509801, 0.191341716182545, 0.097545161008064 },
@@ -226,7 +226,7 @@ bool JPEG::read(Common::SeekableReadStream *stream) {
bool JPEG::readJFIF() {
uint16 length = _stream->readUint16BE();
uint32 tag = _stream->readUint32BE();
- if (tag != MKID_BE('JFIF')) {
+ if (tag != MKTAG('J','F','I','F')) {
warning("JPEG::readJFIF() tag mismatch");
return false;
}
diff --git a/graphics/module.mk b/graphics/module.mk
index c962f0617d..cb3a07e691 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -23,7 +23,8 @@ MODULE_OBJS := \
surface.o \
thumbnail.o \
VectorRenderer.o \
- VectorRendererSpec.o
+ VectorRendererSpec.o \
+ wincursor.o
ifdef USE_SCALERS
MODULE_OBJS += \
diff --git a/graphics/palette.h b/graphics/palette.h
index 72db16a3d3..8d7fdbd99a 100644
--- a/graphics/palette.h
+++ b/graphics/palette.h
@@ -46,14 +46,14 @@ public:
* The palette entries from 'start' till (start+num-1) will be replaced - so
* a full palette update is accomplished via start=0, num=256.
*
- * The palette data is specified in interleaved RGBA format. That is, the
+ * The palette data is specified in interleaved RGB format. That is, the
* first byte of the memory block 'colors' points at is the red component
* of the first new color; the second byte the green component of the first
* new color; the third byte the blue component, the last byte to the alpha
* (transparency) value. Then the second color starts, and so on. So memory
- * looks like this: R1-G1-B1-A1-R2-G2-B2-A2-R3-...
+ * looks like this: R1-G1-B1-R2-G2-B2-R3-...
*
- * @param colors the new palette data, in interleaved RGBA format
+ * @param colors the new palette data, in interleaved RGB format
* @param start the first palette entry to be updated
* @param num the number of palette entries to be updated
*
@@ -62,8 +62,6 @@ public:
* @note It is an error if this function gets called when the pixel format
* in use (the return value of getScreenFormat) has more than one
* byte per pixel.
- * @note The alpha value is not actually used, and future revisions of this
- * API are probably going to remove it.
*
* @see getScreenFormat
*/
@@ -79,19 +77,18 @@ public:
* For example, for every valid value of start and num of the following
* code:
*
- * byte origPal[num*4];
+ * byte origPal[num*3];
* // Setup origPal's data however you like
* g_system->setPalette(origPal, start, num);
- * byte obtainedPal[num*4];
+ * byte obtainedPal[num*3];
* g_system->grabPalette(obtainedPal, start, num);
*
* the following should be true:
*
- * For each i < num : memcmp(&origPal[i*4], &obtainedPal[i*4], 3) == 0
- * (i is an uint here)
+ * memcmp(origPal, obtainedPal, num*3) == 0
*
* @see setPalette
- * @param colors the palette data, in interleaved RGBA format
+ * @param colors the palette data, in interleaved RGB format
* @param start the first platte entry to be read
* @param num the number of palette entries to be read
*
diff --git a/graphics/pict.cpp b/graphics/pict.cpp
index 95f659c19b..ca4aac751d 100644
--- a/graphics/pict.cpp
+++ b/graphics/pict.cpp
@@ -95,10 +95,10 @@ Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *pale
} else if (opcode == 0x001E) { // DefHilite
// Ignore, Contains no Data
} else if (opcode == 0x0098) { // PackBitsRect
- decodeDirectBitsRect(stream, _imageRect.width(), _imageRect.height(), true);
+ decodeDirectBitsRect(stream, true);
_isPaletted = true;
} else if (opcode == 0x009A) { // DirectBitsRect
- decodeDirectBitsRect(stream, _imageRect.width(), _imageRect.height(), false);
+ decodeDirectBitsRect(stream, false);
} else if (opcode == 0x00A1) { // LongComment
stream->readUint16BE();
uint16 dataSize = stream->readUint16BE();
@@ -127,7 +127,7 @@ Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *pale
// If we got a palette throughout this nonsense, go and grab it
if (palette && _isPaletted)
- memcpy(palette, _palette, 256 * 4);
+ memcpy(palette, _palette, 256 * 3);
return _outputSurface;
}
@@ -162,7 +162,7 @@ struct DirectBitsRectData {
uint16 mode;
};
-void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, uint16 width, uint16 height, bool hasPalette) {
+void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, bool hasPalette) {
static const PixelFormat directBitsFormat16 = PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
// Clear the palette
@@ -180,9 +180,9 @@ void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, uint1
for (uint32 i = 0; i < colorCount; i++) {
stream->readUint16BE();
- _palette[i * 4] = stream->readUint16BE() >> 8;
- _palette[i * 4 + 1] = stream->readUint16BE() >> 8;
- _palette[i * 4 + 2] = stream->readUint16BE() >> 8;
+ _palette[i * 3] = stream->readUint16BE() >> 8;
+ _palette[i * 3 + 1] = stream->readUint16BE() >> 8;
+ _palette[i * 3 + 2] = stream->readUint16BE() >> 8;
}
}
@@ -196,6 +196,9 @@ void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, uint1
directBitsData.dstRect.right = stream->readUint16BE();
directBitsData.mode = stream->readUint16BE();
+ uint16 width = directBitsData.srcRect.width();
+ uint16 height = directBitsData.srcRect.height();
+
byte bytesPerPixel = 0;
if (directBitsData.pixMap.pixelSize <= 8)
diff --git a/graphics/pict.h b/graphics/pict.h
index a9ea170292..a683a23bf6 100644
--- a/graphics/pict.h
+++ b/graphics/pict.h
@@ -70,11 +70,11 @@ private:
Common::Rect _imageRect;
PixelFormat _pixelFormat;
JPEG *_jpeg;
- byte _palette[256 * 4];
+ byte _palette[256 * 3];
bool _isPaletted;
Graphics::Surface *_outputSurface;
- void decodeDirectBitsRect(Common::SeekableReadStream *stream, uint16 width, uint16 height, bool hasPalette);
+ void decodeDirectBitsRect(Common::SeekableReadStream *stream, bool hasPalette);
void decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel);
void decodeCompressedQuickTime(Common::SeekableReadStream *stream);
void outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel);
diff --git a/graphics/png.cpp b/graphics/png.cpp
index 5292ea0100..eb066efa57 100644
--- a/graphics/png.cpp
+++ b/graphics/png.cpp
@@ -67,12 +67,12 @@ namespace Graphics {
enum PNGChunks {
// == Critical chunks =====================================================
- kChunkIHDR = MKID_BE('IHDR'), // Image header
- kChunkIDAT = MKID_BE('IDAT'), // Image data
- kChunkPLTE = MKID_BE('PLTE'), // Palette
- kChunkIEND = MKID_BE('IEND'), // Image trailer
+ kChunkIHDR = MKTAG('I','H','D','R'), // Image header
+ kChunkIDAT = MKTAG('I','D','A','T'), // Image data
+ kChunkPLTE = MKTAG('P','L','T','E'), // Palette
+ kChunkIEND = MKTAG('I','E','N','D'), // Image trailer
// == Ancillary chunks ====================================================
- kChunktRNS = MKID_BE('tRNS') // Transparency
+ kChunktRNS = MKTAG('t','R','N','S') // Transparency
// All of the other ancillary chunks are ignored. They're added here for
// reference only.
// cHRM - Primary chromacities and white point
diff --git a/graphics/png.h b/graphics/png.h
index b2ba7ac0f2..70f2e4ba27 100644
--- a/graphics/png.h
+++ b/graphics/png.h
@@ -117,9 +117,11 @@ public:
}
/**
- * Returns the palette of the specified PNG8 image
+ * Returns the palette of the specified PNG8 image.
+ *
+ * Note that the palette's format is RGBA.
*/
- void getPalette(byte *palette, byte &entries) {
+ void getPalette(byte *palette, uint16 &entries) {
if (_header.colorType != kIndexed)
error("Palette requested for a non-indexed PNG");
palette = _palette;
diff --git a/graphics/scaler/2xsai.cpp b/graphics/scaler/2xsai.cpp
index 936ed19124..43a5b2fd1d 100644
--- a/graphics/scaler/2xsai.cpp
+++ b/graphics/scaler/2xsai.cpp
@@ -287,7 +287,7 @@ void _2xSaITemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32
register unsigned colorA, colorB;
unsigned colorC, colorD,
- colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO, colorP;
+ colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO;
unsigned product, product1, product2;
//---------------------------------------
@@ -313,7 +313,6 @@ void _2xSaITemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32
colorM = *(bP + 2 * nextlineSrc - 1);
colorN = *(bP + 2 * nextlineSrc);
colorO = *(bP + 2 * nextlineSrc + 1);
- colorP = *(bP + 2 * nextlineSrc + 2);
if ((colorA == colorD) && (colorB != colorC)) {
if (((colorA == colorE) && (colorB == colorL)) ||
diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp
index bd325aca63..5cee1c7a72 100644
--- a/graphics/scaler/thumbnail_intern.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -108,7 +108,7 @@ static bool grabScreen565(Graphics::Surface *surf) {
byte *palette = 0;
if (screenFormat.bytesPerPixel == 1) {
- palette = new byte[256 * 4];
+ palette = new byte[256 * 3];
assert(palette);
g_system->getPaletteManager()->grabPalette(palette, 0, 256);
}
@@ -118,9 +118,9 @@ static bool grabScreen565(Graphics::Surface *surf) {
byte r = 0, g = 0, b = 0;
if (screenFormat.bytesPerPixel == 1) {
- r = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4];
- g = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 1];
- b = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 2];
+ r = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 3];
+ g = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 3 + 1];
+ b = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 3 + 2];
} else if (screenFormat.bytesPerPixel == 2) {
uint16 col = READ_UINT16(screen->getBasePtr(x, y));
screenFormat.colorToRGB(col, r, g, b);
diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp
index bb9f33aa26..c581f9b265 100644
--- a/graphics/sjis.cpp
+++ b/graphics/sjis.cpp
@@ -362,7 +362,7 @@ bool FontSjisSVM::loadData() {
uint32 magic1 = data->readUint32BE();
uint32 magic2 = data->readUint32BE();
- if (magic1 != MKID_BE('SCVM') || magic2 != MKID_BE('SJIS')) {
+ if (magic1 != MKTAG('S','C','V','M') || magic2 != MKTAG('S','J','I','S')) {
delete data;
return false;
}
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index b245cfc5fa..8688096c3d 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -49,7 +49,7 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
// We also accept the bad 'BMHT' header here, for the sake of compatibility
// with some older savegames which were written incorrectly due to a bug in
// ScummVM which wrote the thumb header type incorrectly on LE systems.
- if (header.type != MKID_BE('THMB') && header.type != MKID_BE('BMHT')) {
+ if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) {
if (outputWarnings)
warning("couldn't find thumbnail header type");
return false;
@@ -145,7 +145,7 @@ bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) {
}
ThumbnailHeader header;
- header.type = MKID_BE('THMB');
+ header.type = MKTAG('T','H','M','B');
header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel;
header.version = THMB_VERSION;
header.width = thumb.w;
diff --git a/graphics/wincursor.cpp b/graphics/wincursor.cpp
new file mode 100644
index 0000000000..10939a677a
--- /dev/null
+++ b/graphics/wincursor.cpp
@@ -0,0 +1,317 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/ptr.h"
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/winexe_ne.h"
+#include "common/winexe_pe.h"
+
+#include "graphics/wincursor.h"
+
+namespace Graphics {
+
+WinCursor::WinCursor() {
+ _width = 0;
+ _height = 0;
+ _hotspotX = 0;
+ _hotspotY = 0;
+ _surface = 0;
+ _keyColor = 0;
+ memset(_palette, 0, 256 * 3);
+}
+
+WinCursor::~WinCursor() {
+ clear();
+}
+
+uint16 WinCursor::getWidth() const {
+ return _width;
+}
+
+uint16 WinCursor::getHeight() const {
+ return _height;
+}
+
+uint16 WinCursor::getHotspotX() const {
+ return _hotspotX;
+}
+
+uint16 WinCursor::getHotspotY() const {
+ return _hotspotY;
+}
+
+byte WinCursor::getKeyColor() const {
+ return _keyColor;
+}
+
+bool WinCursor::readFromStream(Common::SeekableReadStream &stream) {
+ clear();
+
+ _hotspotX = stream.readUint16LE();
+ _hotspotY = stream.readUint16LE();
+
+ // Check header size
+ if (stream.readUint32LE() != 40)
+ return false;
+
+ // Check dimensions
+ _width = stream.readUint32LE();
+ _height = stream.readUint32LE() / 2;
+
+ if (_width & 3) {
+ // Cursors should always be a power of 2
+ // Of course, it wouldn't be hard to handle but if we have no examples...
+ warning("Non-divisible-by-4 width cursor found");
+ return false;
+ }
+
+ // Color planes
+ if (stream.readUint16LE() != 1)
+ return false;
+
+ // Only 1bpp and 8bpp supported
+ uint16 bitsPerPixel = stream.readUint16LE();
+ if (bitsPerPixel != 1 && bitsPerPixel != 8)
+ return false;
+
+ // Compression
+ if (stream.readUint32LE() != 0)
+ return false;
+
+ // Image size + X resolution + Y resolution
+ stream.skip(12);
+
+ uint32 numColors = stream.readUint32LE();
+
+ // If the color count is 0, then it uses up the maximum amount
+ if (numColors == 0)
+ numColors = 1 << bitsPerPixel;
+
+ // Reading the palette
+ stream.seek(40 + 4);
+ for (uint32 i = 0 ; i < numColors; i++) {
+ _palette[i * 3 + 2] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 ] = stream.readByte();
+ stream.readByte();
+ }
+
+ // Reading the bitmap data
+ uint32 dataSize = stream.size() - stream.pos();
+ byte *initialSource = new byte[dataSize];
+ stream.read(initialSource, dataSize);
+
+ // Parse the XOR map
+ const byte *src = initialSource;
+ _surface = new byte[_width * _height];
+ byte *dest = _surface + _width * (_height - 1);
+ uint32 imagePitch = _width * bitsPerPixel / 8;
+
+ for (uint32 i = 0; i < _height; i++) {
+ byte *rowDest = dest;
+
+ if (bitsPerPixel == 1) {
+ // 1bpp
+ for (uint16 j = 0; j < (_width / 8); j++) {
+ byte p = src[j];
+
+ for (int k = 0; k < 8; k++, rowDest++, p <<= 1) {
+ if ((p & 0x80) == 0x80)
+ *rowDest = 1;
+ else
+ *rowDest = 0;
+ }
+ }
+ } else {
+ // 8bpp
+ memcpy(rowDest, src, _width);
+ }
+
+ dest -= _width;
+ src += imagePitch;
+ }
+
+ // Calculate our key color
+ if (numColors < 256) {
+ // If we're not using the maximum colors in a byte, we can fit it in
+ _keyColor = numColors;
+ } else {
+ // HACK: Try to find a color that's not being used so it can become
+ // our keycolor. It's quite impossible to fit 257 entries into 256...
+ for (uint32 i = 0; i < 256; i++) {
+ for (int j = 0; j < _width * _height; j++) {
+ // TODO: Also check to see if the space is transparent
+
+ if (_surface[j] == i)
+ break;
+
+ if (j == _width * _height - 1) {
+ _keyColor = i;
+ i = 256;
+ break;
+ }
+ }
+ }
+ }
+
+ // Now go through and apply the AND map to get the transparency
+ uint32 andWidth = (_width + 7) / 8;
+ src += andWidth * (_height - 1);
+
+ for (uint32 y = 0; y < _height; y++) {
+ for (uint32 x = 0; x < _width; x++)
+ if (src[x / 8] & (1 << (7 - x % 8)))
+ _surface[y * _width + x] = _keyColor;
+
+ src -= andWidth;
+ }
+
+ delete[] initialSource;
+ return true;
+}
+
+void WinCursor::clear() {
+ delete[] _surface; _surface = 0;
+}
+
+WinCursorGroup::WinCursorGroup() {
+}
+
+WinCursorGroup::~WinCursorGroup() {
+ for (uint32 i = 0; i < cursors.size(); i++)
+ delete cursors[i].cursor;
+}
+
+WinCursorGroup *WinCursorGroup::createCursorGroup(Common::NEResources &exe, const Common::WinResourceID &id) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(exe.getResource(Common::kNEGroupCursor, id));
+
+ if (!stream || stream->size() <= 6)
+ return 0;
+
+ stream->skip(4);
+ uint32 cursorCount = stream->readUint16LE();
+ if ((uint32)stream->size() < (6 + cursorCount * 16))
+ return 0;
+
+ WinCursorGroup *group = new WinCursorGroup();
+ group->cursors.reserve(cursorCount);
+
+ for (uint32 i = 0; i < cursorCount; i++) {
+ stream->readUint16LE(); // width
+ stream->readUint16LE(); // height
+
+ // Plane count
+ if (stream->readUint16LE() != 1) {
+ delete group;
+ return 0;
+ }
+
+ // Bits per pixel
+ // NE cursors can only be 1bpp
+ if (stream->readUint16LE() != 1) {
+ delete group;
+ return 0;
+ }
+
+ stream->readUint32LE(); // data size
+ uint32 cursorId = stream->readUint32LE();
+
+ Common::ScopedPtr<Common::SeekableReadStream> cursorStream(exe.getResource(Common::kNECursor, cursorId));
+ if (!cursorStream) {
+ delete group;
+ return 0;
+ }
+
+ WinCursor *cursor = new WinCursor();
+ if (!cursor->readFromStream(*cursorStream)) {
+ delete cursor;
+ delete group;
+ return 0;
+ }
+
+ CursorItem item;
+ item.id = cursorId;
+ item.cursor = cursor;
+ group->cursors.push_back(item);
+ }
+
+ return group;
+}
+
+WinCursorGroup *WinCursorGroup::createCursorGroup(Common::PEResources &exe, const Common::WinResourceID &id) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(exe.getResource(Common::kPEGroupCursor, id));
+
+ if (!stream || stream->size() <= 6)
+ return 0;
+
+ stream->skip(4);
+ uint32 cursorCount = stream->readUint16LE();
+ if ((uint32)stream->size() < (6 + cursorCount * 14))
+ return 0;
+
+ WinCursorGroup *group = new WinCursorGroup();
+ group->cursors.reserve(cursorCount);
+
+ for (uint32 i = 0; i < cursorCount; i++) {
+ stream->readUint16LE(); // width
+ stream->readUint16LE(); // height
+
+ // Plane count
+ if (stream->readUint16LE() != 1) {
+ delete group;
+ return 0;
+ }
+
+ stream->readUint16LE(); // bits per pixel
+ stream->readUint32LE(); // data size
+ uint32 cursorId = stream->readUint16LE();
+
+ Common::ScopedPtr<Common::SeekableReadStream> cursorStream(exe.getResource(Common::kPECursor, cursorId));
+ if (!cursorStream) {
+ delete group;
+ return 0;
+ }
+
+ WinCursor *cursor = new WinCursor();
+ if (!cursor->readFromStream(*cursorStream)) {
+ delete cursor;
+ delete group;
+ return 0;
+ }
+
+ CursorItem item;
+ item.id = cursorId;
+ item.cursor = cursor;
+ group->cursors.push_back(item);
+ }
+
+ return group;
+}
+
+} // End of namespace Graphics
diff --git a/graphics/wincursor.h b/graphics/wincursor.h
new file mode 100644
index 0000000000..ca0abf6fe1
--- /dev/null
+++ b/graphics/wincursor.h
@@ -0,0 +1,105 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_WINCURSOR_H
+#define GRAPHICS_WINCURSOR_H
+
+#include "common/array.h"
+#include "common/winexe.h"
+
+namespace Common {
+ class NEResources;
+ class PEResources;
+ class SeekableReadStream;
+}
+
+namespace Graphics {
+
+/** A Windows cursor. */
+class WinCursor {
+public:
+ WinCursor();
+ ~WinCursor();
+
+ /** Return the cursor's width. */
+ uint16 getWidth() const;
+ /** Return the cursor's height. */
+ uint16 getHeight() const;
+ /** Return the cursor's hotspot's x coordinate. */
+ uint16 getHotspotX() const;
+ /** Return the cursor's hotspot's y coordinate. */
+ uint16 getHotspotY() const;
+ /** Return the cursor's transparent key. */
+ byte getKeyColor() const;
+
+ const byte *getSurface() const { return _surface; }
+ const byte *getPalette() const { return _palette; }
+
+ /** Read the cursor's data out of a stream. */
+ bool readFromStream(Common::SeekableReadStream &stream);
+
+private:
+ byte *_surface;
+ byte _palette[256 * 3];
+
+ uint16 _width; ///< The cursor's width.
+ uint16 _height; ///< The cursor's height.
+ uint16 _hotspotX; ///< The cursor's hotspot's x coordinate.
+ uint16 _hotspotY; ///< The cursor's hotspot's y coordinate.
+ byte _keyColor; ///< The cursor's transparent key
+
+ /** Clear the cursor. */
+ void clear();
+};
+
+/**
+ * A structure holding an array of cursors from a single Windows Executable cursor group.
+ *
+ * Windows lumps different versions of the same cursors/icons together and decides which one
+ * to use based on the screen's color depth and resolution. For instance, one cursor group
+ * could hold a 1bpp 16x16 cursorand a 8bpp 16x16 cursor. This will hold all cursors in the
+ * group. This class should be used to actually parse the cursors, whereas WinCursor is just
+ * the representation used by this struct to store the cursors.
+ */
+struct WinCursorGroup {
+ WinCursorGroup();
+ ~WinCursorGroup();
+
+ struct CursorItem {
+ Common::WinResourceID id;
+ WinCursor *cursor;
+ };
+
+ Common::Array<CursorItem> cursors;
+
+ /** Create a cursor group from an NE EXE, returns 0 on failure */
+ static WinCursorGroup *createCursorGroup(Common::NEResources &exe, const Common::WinResourceID &id);
+ /** Create a cursor group from an PE EXE, returns 0 on failure */
+ static WinCursorGroup *createCursorGroup(Common::PEResources &exe, const Common::WinResourceID &id);
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index beb17b0c88..82104eb7ae 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -69,18 +69,18 @@ struct WidgetDrawData {
/** Extra space that the widget occupies when it's drawn.
E.g. when taking into account rounded corners, drop shadows, etc
- Used when restoring the widget background */
+ Used when restoring the widget background */
uint16 _backgroundOffset;
bool _buffer;
/**
- * Calculates the background threshold offset of a given DrawData item.
- * After fully loading all DrawSteps of a DrawData item, this function must be
- * called in order to calculate if such draw steps would be drawn outside of
- * the actual widget drawing zone (e.g. shadows). If this is the case, a constant
- * value will be added when restoring the background of the widget.
+ * Calculates the background threshold offset of a given DrawData item.
+ * After fully loading all DrawSteps of a DrawData item, this function must be
+ * called in order to calculate if such draw steps would be drawn outside of
+ * the actual widget drawing zone (e.g. shadows). If this is the case, a constant
+ * value will be added when restoring the background of the widget.
*/
void calcBackgroundOffset();
};
@@ -114,8 +114,8 @@ protected:
class ThemeItemTextData : public ThemeItem {
public:
ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::String &text,
- Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV,
- bool ellipsis, bool restoreBg, int deltaX) :
+ Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV,
+ bool ellipsis, bool restoreBg, int deltaX) :
ThemeItem(engine, area), _data(data), _color(color), _text(text), _alignH(alignH), _alignV(alignV),
_ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX) {}
@@ -147,71 +147,71 @@ protected:
/**********************************************************
- * Data definitions for theme engine elements
+ * Data definitions for theme engine elements
*********************************************************/
struct DrawDataInfo {
- DrawData id; ///< The actual ID of the DrawData item.
- const char *name; ///< The name of the DrawData item as it appears in the Theme Description files
- bool buffer; ///< Sets whether this item is buffered on the backbuffer or drawn directly to the screen.
- DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover
+ DrawData id; ///< The actual ID of the DrawData item.
+ const char *name; ///< The name of the DrawData item as it appears in the Theme Description files
+ bool buffer; ///< Sets whether this item is buffered on the backbuffer or drawn directly to the screen.
+ DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover
};
/**
* Default values for each DrawData item.
*/
static const DrawDataInfo kDrawDataDefaults[] = {
- {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone},
- {kDDSpecialColorBackground, "special_bg", true, kDDNone},
- {kDDPlainColorBackground, "plain_bg", true, kDDNone},
- {kDDTooltipBackground, "tooltip_bg", true, kDDNone},
- {kDDDefaultBackground, "default_bg", true, kDDNone},
- {kDDTextSelectionBackground, "text_selection", false, kDDNone},
- {kDDTextSelectionFocusBackground, "text_selection_focus", false, kDDNone},
+ {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone},
+ {kDDSpecialColorBackground, "special_bg", true, kDDNone},
+ {kDDPlainColorBackground, "plain_bg", true, kDDNone},
+ {kDDTooltipBackground, "tooltip_bg", true, kDDNone},
+ {kDDDefaultBackground, "default_bg", true, kDDNone},
+ {kDDTextSelectionBackground, "text_selection", false, kDDNone},
+ {kDDTextSelectionFocusBackground, "text_selection_focus", false, kDDNone},
- {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone},
- {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone},
- {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone},
- {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone},
+ {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone},
+ {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone},
+ {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone},
+ {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone},
- {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider},
- {kDDButtonHover, "button_hover", false, kDDButtonIdle},
- {kDDButtonDisabled, "button_disabled", true, kDDNone},
+ {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider},
+ {kDDButtonHover, "button_hover", false, kDDButtonIdle},
+ {kDDButtonDisabled, "button_disabled", true, kDDNone},
- {kDDSliderFull, "slider_full", false, kDDNone},
- {kDDSliderHover, "slider_hover", false, kDDNone},
- {kDDSliderDisabled, "slider_disabled", false, kDDNone},
+ {kDDSliderFull, "slider_full", false, kDDNone},
+ {kDDSliderHover, "slider_hover", false, kDDNone},
+ {kDDSliderDisabled, "slider_disabled", false, kDDNone},
- {kDDCheckboxDefault, "checkbox_default", true, kDDNone},
- {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone},
- {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault},
+ {kDDCheckboxDefault, "checkbox_default", true, kDDNone},
+ {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone},
+ {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault},
- {kDDRadiobuttonDefault, "radiobutton_default", true, kDDNone},
- {kDDRadiobuttonDisabled, "radiobutton_disabled", true, kDDNone},
- {kDDRadiobuttonSelected, "radiobutton_selected", false, kDDRadiobuttonDefault},
+ {kDDRadiobuttonDefault, "radiobutton_default", true, kDDNone},
+ {kDDRadiobuttonDisabled, "radiobutton_disabled", true, kDDNone},
+ {kDDRadiobuttonSelected, "radiobutton_selected", false, kDDRadiobuttonDefault},
- {kDDTabActive, "tab_active", false, kDDTabInactive},
- {kDDTabInactive, "tab_inactive", true, kDDNone},
- {kDDTabBackground, "tab_background", true, kDDNone},
+ {kDDTabActive, "tab_active", false, kDDTabInactive},
+ {kDDTabInactive, "tab_inactive", true, kDDNone},
+ {kDDTabBackground, "tab_background", true, kDDNone},
- {kDDScrollbarBase, "scrollbar_base", true, kDDNone},
+ {kDDScrollbarBase, "scrollbar_base", true, kDDNone},
- {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone},
- {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle},
+ {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone},
+ {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle},
- {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone},
- {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase},
+ {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone},
+ {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase},
- {kDDPopUpIdle, "popup_idle", true, kDDNone},
- {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle},
- {kDDPopUpDisabled, "popup_disabled", true, kDDNone},
+ {kDDPopUpIdle, "popup_idle", true, kDDNone},
+ {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle},
+ {kDDPopUpDisabled, "popup_disabled", true, kDDNone},
- {kDDCaret, "caret", false, kDDNone},
- {kDDSeparator, "separator", true, kDDNone},
+ {kDDCaret, "caret", false, kDDNone},
+ {kDDSeparator, "separator", true, kDDNone},
};
/**********************************************************
- * ThemeItem functions for drawing queues.
+ * ThemeItem functions for drawing queues.
*********************************************************/
void ThemeItemDrawData::drawSelf(bool draw, bool restore) {
@@ -259,7 +259,7 @@ void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
/**********************************************************
- * ThemeEngine class
+ * ThemeEngine class
*********************************************************/
ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) :
_system(0), _vectorRenderer(0),
@@ -326,7 +326,7 @@ ThemeEngine::~ThemeEngine() {
/**********************************************************
- * Rendering mode management
+ * Rendering mode management
*********************************************************/
const ThemeEngine::Renderer ThemeEngine::_rendererModes[] = {
{ _s("Disabled GFX"), _sc("Disabled GFX", "lowres"), "none", kGfxDisabled },
@@ -368,7 +368,7 @@ const char *ThemeEngine::findModeConfigName(GraphicsMode mode) {
/**********************************************************
- * Theme setup/initialization
+ * Theme setup/initialization
*********************************************************/
bool ThemeEngine::init() {
// reset everything and reload the graphics
@@ -512,7 +512,7 @@ void ThemeEngine::setGraphicsMode(GraphicsMode mode) {
void WidgetDrawData::calcBackgroundOffset() {
uint maxShadow = 0;
for (Common::List<Graphics::DrawStep>::const_iterator step = _steps.begin();
- step != _steps.end(); ++step) {
+ step != _steps.end(); ++step) {
if ((step->autoWidth || step->autoHeight) && step->shadow > maxShadow)
maxShadow = step->shadow;
@@ -531,7 +531,7 @@ void ThemeEngine::restoreBackground(Common::Rect r) {
/**********************************************************
- * Theme elements management
+ * Theme elements management
*********************************************************/
void ThemeEngine::addDrawStep(const Common::String &drawDataId, const Graphics::DrawStep &step) {
DrawData id = parseDrawDataId(drawDataId);
@@ -659,7 +659,7 @@ bool ThemeEngine::addDrawData(const Common::String &data, bool cached) {
/**********************************************************
- * Theme XML loading
+ * Theme XML loading
*********************************************************/
void ThemeEngine::loadTheme(const Common::String &themeId) {
unloadTheme();
@@ -717,9 +717,9 @@ bool ThemeEngine::loadDefaultXML() {
#ifndef DISABLE_GUI_BUILTIN_THEME
const char *defaultXML =
#include "themes/default.inc"
- ;
+ ;
- if (!_parser->loadBuffer((const byte*)defaultXML, strlen(defaultXML)))
+ if (!_parser->loadBuffer((const byte *)defaultXML, strlen(defaultXML)))
return false;
_themeName = "ScummVM Classic Theme (Builtin Version)";
@@ -793,7 +793,7 @@ bool ThemeEngine::loadThemeXML(const Common::String &themeId) {
/**********************************************************
- * Drawing Queue management
+ * Drawing Queue management
*********************************************************/
void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic, bool restore) {
if (_widgets[type] == 0)
@@ -820,7 +820,7 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic,
}
void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
- bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax) {
+ bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax) {
if (_texts[type] == 0)
return;
@@ -856,7 +856,7 @@ void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rec
/**********************************************************
- * Widget drawing functions
+ * Widget drawing functions
*********************************************************/
void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) {
if (!ready())
@@ -1088,7 +1088,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
}
if (active >= 0 &&
- (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
+ (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
const uint16 tabLeft = active * tabWidth;
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
@@ -1191,25 +1191,25 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) {
}
/**********************************************************
- * Screen/overlay management
+ * Screen/overlay management
*********************************************************/
-void ThemeEngine::updateScreen() {
+void ThemeEngine::updateScreen(bool render) {
if (!_bufferQueue.empty()) {
_vectorRenderer->setSurface(&_backBuffer);
- for (Common::List<ThemeItem*>::iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) {
+ for (Common::List<ThemeItem *>::iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) {
(*q)->drawSelf(true, false);
delete *q;
}
_vectorRenderer->setSurface(&_screen);
- memcpy(_screen.getBasePtr(0,0), _backBuffer.getBasePtr(0,0), _screen.pitch * _screen.h);
+ memcpy(_screen.getBasePtr(0, 0), _backBuffer.getBasePtr(0, 0), _screen.pitch * _screen.h);
_bufferQueue.clear();
}
if (!_screenQueue.empty()) {
_vectorRenderer->disableShadows();
- for (Common::List<ThemeItem*>::iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) {
+ for (Common::List<ThemeItem *>::iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) {
(*q)->drawSelf(true, false);
delete *q;
}
@@ -1218,7 +1218,8 @@ void ThemeEngine::updateScreen() {
_screenQueue.clear();
}
- renderDirtyScreen();
+ if (render)
+ renderDirtyScreen();
}
void ThemeEngine::addDirtyRect(Common::Rect r) {
@@ -1231,7 +1232,7 @@ void ThemeEngine::addDirtyRect(Common::Rect r) {
// Check if the new rectangle is contained within another in the list
Common::List<Common::Rect>::iterator it;
- for (it = _dirtyScreen.begin(); it != _dirtyScreen.end(); ) {
+ for (it = _dirtyScreen.begin(); it != _dirtyScreen.end();) {
// If we find a rectangle which fully contains the new one,
// we can abort the search.
if (it->contains(r))
@@ -1270,7 +1271,7 @@ void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) {
addDirtyRect(Common::Rect(0, 0, _screen.w, _screen.h));
}
- memcpy(_backBuffer.getBasePtr(0,0), _screen.getBasePtr(0,0), _screen.pitch * _screen.h);
+ memcpy(_backBuffer.getBasePtr(0, 0), _screen.getBasePtr(0, 0), _screen.pitch * _screen.h);
_vectorRenderer->setSurface(&_screen);
}
@@ -1309,8 +1310,8 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int
// Now, scan the bitmap. We have to convert it from 16 bit color mode
// to 8 bit mode, and have to create a suitable palette on the fly.
uint colorsFound = 0;
- Common::HashMap<int, int> colorToIndex;
- const OverlayColor *src = (const OverlayColor*)cursor->pixels;
+ Common::HashMap<int, int> colorToIndex;
+ const OverlayColor *src = (const OverlayColor *)cursor->pixels;
for (uint y = 0; y < _cursorHeight; ++y) {
for (uint x = 0; x < _cursorWidth; ++x) {
byte r, g, b;
@@ -1327,10 +1328,9 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int
const int index = colorsFound++;
colorToIndex[col] = index;
- _cursorPal[index * 4 + 0] = r;
- _cursorPal[index * 4 + 1] = g;
- _cursorPal[index * 4 + 2] = b;
- _cursorPal[index * 4 + 3] = 0xFF;
+ _cursorPal[index * 3 + 0] = r;
+ _cursorPal[index * 3 + 1] = g;
+ _cursorPal[index * 3 + 2] = b;
if (colorsFound > MAX_CURS_COLORS) {
warning("Cursor contains too many colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS);
@@ -1353,7 +1353,7 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int
/**********************************************************
- * Legacy GUI::Theme support functions
+ * Legacy GUI::Theme support functions
*********************************************************/
const Graphics::Font *ThemeEngine::getFont(FontStyle font) const {
@@ -1389,7 +1389,7 @@ DrawData ThemeEngine::parseDrawDataId(const Common::String &name) const {
}
/**********************************************************
- * External data loading
+ * External data loading
*********************************************************/
const Graphics::Font *ThemeEngine::loadFontFromArchive(const Common::String &filename) {
@@ -1498,7 +1498,7 @@ Common::String ThemeEngine::genLocalizedFontFilename(const Common::String &filen
/**********************************************************
- * Static Theme XML functions
+ * Static Theme XML functions
*********************************************************/
bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String &themeName) {
@@ -1584,7 +1584,9 @@ struct TDComparator {
const Common::String _id;
TDComparator(const Common::String &id) : _id(id) {}
- bool operator()(const ThemeEngine::ThemeDescriptor &r) { return _id == r.id; }
+ bool operator()(const ThemeEngine::ThemeDescriptor &r) {
+ return _id == r.id;
+ }
};
} // end of anonymous namespace
@@ -1626,7 +1628,7 @@ void ThemeEngine::listUsableThemes(Common::Archive &archive, Common::List<ThemeD
Common::ArchiveMemberList fileList;
archive.listMatchingMembers(fileList, "*.zip");
for (Common::ArchiveMemberList::iterator i = fileList.begin();
- i != fileList.end(); ++i) {
+ i != fileList.end(); ++i) {
td.name.clear();
if (themeConfigUsable(**i, td.name)) {
td.filename = (*i)->getName();
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 966c792042..46065278d3 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -32,11 +32,11 @@
#include "graphics/surface.h"
#include "graphics/font.h"
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.2"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.3"
namespace Graphics {
- struct DrawStep;
- class VectorRenderer;
+struct DrawStep;
+class VectorRenderer;
}
namespace GUI {
@@ -53,9 +53,9 @@ class ThemeItem;
class ThemeParser;
/**
- * DrawData sets enumeration.
- * Each DD set corresponds to the actual looks
- * of a widget in a given state.
+ * DrawData sets enumeration.
+ * Each DD set corresponds to the actual looks
+ * of a widget in a given state.
*/
enum DrawData {
kDDMainDialogBackground,
@@ -134,7 +134,7 @@ enum TextColor {
class ThemeEngine {
protected:
- typedef Common::HashMap<Common::String, Graphics::Surface*> ImagesMap;
+ typedef Common::HashMap<Common::String, Graphics::Surface *> ImagesMap;
friend class GUI::Dialog;
friend class GUI::GuiObject;
@@ -150,12 +150,12 @@ public:
/// Widget background type
enum WidgetBackground {
- kWidgetBackgroundNo, ///< No background at all
- kWidgetBackgroundPlain, ///< Simple background, this may not include borders
- kWidgetBackgroundBorder, ///< Same as kWidgetBackgroundPlain just with a border
- kWidgetBackgroundBorderSmall, ///< Same as kWidgetBackgroundPlain just with a small border
- kWidgetBackgroundEditText, ///< Background used for edit text fields
- kWidgetBackgroundSlider ///< Background used for sliders
+ kWidgetBackgroundNo, ///< No background at all
+ kWidgetBackgroundPlain, ///< Simple background, this may not include borders
+ kWidgetBackgroundBorder, ///< Same as kWidgetBackgroundPlain just with a border
+ kWidgetBackgroundBorderSmall, ///< Same as kWidgetBackgroundPlain just with a small border
+ kWidgetBackgroundEditText, ///< Background used for edit text fields
+ kWidgetBackgroundSlider ///< Background used for sliders
};
/// Dialog background type
@@ -169,18 +169,18 @@ public:
/// State of the widget to be drawn
enum State {
- kStateDisabled, ///< Indicates that the widget is disabled, that does NOT include that it is invisible
- kStateEnabled, ///< Indicates that the widget is enabled
- kStateHighlight ///< Indicates that the widget is highlighted by the user
+ kStateDisabled, ///< Indicates that the widget is disabled, that does NOT include that it is invisible
+ kStateEnabled, ///< Indicates that the widget is enabled
+ kStateHighlight ///< Indicates that the widget is highlighted by the user
};
typedef State WidgetStateInfo;
/// Text inversion state of the text to be draw
enum TextInversionState {
- kTextInversionNone, ///< Indicates that the text should not be drawn inverted
- kTextInversion, ///< Indicates that the text should be drawn inverted, but not focused
- kTextInversionFocus ///< Indicates that the text should be drawn inverted, and focused
+ kTextInversionNone, ///< Indicates that the text should not be drawn inverted
+ kTextInversion, ///< Indicates that the text should be drawn inverted, but not focused
+ kTextInversionFocus ///< Indicates that the text should be drawn inverted, and focused
};
enum ScrollbarState {
@@ -193,34 +193,34 @@ public:
/// Font style selector
enum FontStyle {
- kFontStyleBold = 0, ///< A bold font. This is also the default font.
- kFontStyleNormal = 1, ///< A normal font.
- kFontStyleItalic = 2, ///< Italic styled font.
- kFontStyleFixedNormal = 3, ///< Fixed size font.
- kFontStyleFixedBold = 4, ///< Fixed size bold font.
- kFontStyleFixedItalic = 5, ///< Fixed size italic font.
- kFontStyleTooltip = 6, ///< Tiny console font
+ kFontStyleBold = 0, ///< A bold font. This is also the default font.
+ kFontStyleNormal = 1, ///< A normal font.
+ kFontStyleItalic = 2, ///< Italic styled font.
+ kFontStyleFixedNormal = 3, ///< Fixed size font.
+ kFontStyleFixedBold = 4, ///< Fixed size bold font.
+ kFontStyleFixedItalic = 5, ///< Fixed size italic font.
+ kFontStyleTooltip = 6, ///< Tiny console font
kFontStyleMax
};
/// Font color selector
enum FontColor {
- kFontColorNormal = 0, ///< The default color of the theme
- kFontColorAlternate = 1, ///< Alternative font color
+ kFontColorNormal = 0, ///< The default color of the theme
+ kFontColorAlternate = 1, ///< Alternative font color
kFontColorMax
};
/// Function used to process areas other than the current dialog
enum ShadingStyle {
- kShadingNone, ///< No special post processing
- kShadingDim, ///< Dimming unused areas
- kShadingLuminance ///< Converting colors to luminance for unused areas
+ kShadingNone, ///< No special post processing
+ kShadingDim, ///< Dimming unused areas
+ kShadingLuminance ///< Converting colors to luminance for unused areas
};
// Special image ids for images used in the GUI
- static const char * const kImageLogo; ///< ScummVM logo used in the launcher
- static const char * const kImageLogoSmall; ///< ScummVM logo used in the GMM
- static const char * const kImageSearch; ///< Search tool image used in the launcher
+ static const char *const kImageLogo; ///< ScummVM logo used in the launcher
+ static const char *const kImageLogoSmall; ///< ScummVM logo used in the GMM
+ static const char *const kImageSearch; ///< Search tool image used in the launcher
/**
* Graphics mode enumeration.
@@ -228,9 +228,9 @@ public:
* surface.
*/
enum GraphicsMode {
- kGfxDisabled = 0, ///< No GFX
- kGfxStandard16bit, ///< 2BPP with the standard (aliased) renderer.
- kGfxAntialias16bit ///< 2BPP with the optimized AA renderer.
+ kGfxDisabled = 0, ///< No GFX
+ kGfxStandard16bit, ///< 2BPP with the standard (aliased) renderer.
+ kGfxAntialias16bit ///< 2BPP with the optimized AA renderer.
};
/** Constant value to expand dirty rectangles, to make sure they are fully copied */
@@ -265,22 +265,22 @@ public:
void disable();
/**
- * Implementation of the GUI::Theme API. Called when a
- * new dialog is opened. Note that the boolean parameter
- * meaning has been changed.
+ * Implementation of the GUI::Theme API. Called when a
+ * new dialog is opened. Note that the boolean parameter
+ * meaning has been changed.
*
* @param enableBuffering If set to true, buffering is enabled for
- * drawing this dialog, and will continue enabled
- * until disabled.
+ * drawing this dialog, and will continue enabled
+ * until disabled.
*/
void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone);
/**
- * The updateScreen() method is called every frame.
- * It processes all the drawing queues and then copies dirty rects
- * in the current Screen surface to the overlay.
+ * The updateScreen() method is called every frame.
+ * It processes all the drawing queues and then copies dirty rects
+ * in the current Screen surface to the overlay.
*/
- void updateScreen();
+ void updateScreen(bool render = true);
/** @name FONT MANAGEMENT METHODS */
@@ -309,35 +309,35 @@ public:
//@{
void drawWidgetBackground(const Common::Rect &r, uint16 hints,
- WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
+ WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
void drawButton(const Common::Rect &r, const Common::String &str,
- WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
+ WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
void drawSurface(const Common::Rect &r, const Graphics::Surface &surface,
- WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false);
+ WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false);
void drawSlider(const Common::Rect &r, int width,
- WidgetStateInfo state = kStateEnabled);
+ WidgetStateInfo state = kStateEnabled);
void drawCheckbox(const Common::Rect &r, const Common::String &str,
- bool checked, WidgetStateInfo state = kStateEnabled);
+ bool checked, WidgetStateInfo state = kStateEnabled);
void drawRadiobutton(const Common::Rect &r, const Common::String &str,
- bool checked, WidgetStateInfo state = kStateEnabled);
+ bool checked, WidgetStateInfo state = kStateEnabled);
void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
- const Common::Array<Common::String> &tabs, int active, uint16 hints,
- int titleVPad, WidgetStateInfo state = kStateEnabled);
+ const Common::Array<Common::String> &tabs, int active, uint16 hints,
+ int titleVPad, WidgetStateInfo state = kStateEnabled);
void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
- ScrollbarState, WidgetStateInfo state = kStateEnabled);
+ ScrollbarState, WidgetStateInfo state = kStateEnabled);
void drawPopUpWidget(const Common::Rect &r, const Common::String &sel,
- int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
+ int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
void drawCaret(const Common::Rect &r, bool erase,
- WidgetStateInfo state = kStateEnabled);
+ WidgetStateInfo state = kStateEnabled);
void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled);
@@ -362,13 +362,13 @@ public:
/**
- * Returns the DrawData enumeration value that represents the given string
- * in the DrawDataDefaults enumeration.
- * It's slow, but called sparsely.
+ * Returns the DrawData enumeration value that represents the given string
+ * in the DrawDataDefaults enumeration.
+ * It's slow, but called sparsely.
*
- * @returns The drawdata enum value, or -1 if not found.
- * @param name The representing name, as found on Theme Description XML files.
- * @see kDrawDataDefaults[]
+ * @returns The drawdata enum value, or -1 if not found.
+ * @param name The representing name, as found on Theme Description XML files.
+ * @see kDrawDataDefaults[]
*/
DrawData parseDrawDataId(const Common::String &name) const;
@@ -377,34 +377,34 @@ public:
/**
- * Interface for ThemeParser class: Parsed DrawSteps are added via this function.
- * There is no return type because DrawSteps can always be added, unless something
- * goes horribly wrong.
- * The specified step will be added to the Steps list of the given DrawData id.
+ * Interface for ThemeParser class: Parsed DrawSteps are added via this function.
+ * There is no return type because DrawSteps can always be added, unless something
+ * goes horribly wrong.
+ * The specified step will be added to the Steps list of the given DrawData id.
*
- * @param drawDataId The representing DrawData name, as found on Theme Description XML files.
- * @param step The actual DrawStep struct to be added.
+ * @param drawDataId The representing DrawData name, as found on Theme Description XML files.
+ * @param step The actual DrawStep struct to be added.
*/
void addDrawStep(const Common::String &drawDataId, const Graphics::DrawStep &step);
/**
- * Interface for the ThemeParser class: Parsed DrawData sets are added via this function.
- * The goal of the function is to initialize each DrawData set before their DrawSteps can
- * be added, hence this must be called for each DD set before addDrawStep() can be called
- * for that given set.
+ * Interface for the ThemeParser class: Parsed DrawData sets are added via this function.
+ * The goal of the function is to initialize each DrawData set before their DrawSteps can
+ * be added, hence this must be called for each DD set before addDrawStep() can be called
+ * for that given set.
*
- * @param data The representing DrawData name, as found on Theme Description XML files.
- * @param cached Whether this DD set will be cached beforehand.
+ * @param data The representing DrawData name, as found on Theme Description XML files.
+ * @param cached Whether this DD set will be cached beforehand.
*/
bool addDrawData(const Common::String &data, bool cached);
/**
- * Interface for the ThemeParser class: Loads a font to use on the GUI from the given
- * filename.
+ * Interface for the ThemeParser class: Loads a font to use on the GUI from the given
+ * filename.
*
- * @param fontName Identifier name for the font.
- * @param file Name of the font file.
+ * @param fontName Identifier name for the font.
+ * @param file Name of the font file.
*/
bool addFont(TextData textId, const Common::String &file);
@@ -418,25 +418,25 @@ public:
/**
- * Interface for the ThemeParser class: Loads a bitmap file to use on the GUI.
- * The filename is also used as its identifier.
+ * Interface for the ThemeParser class: Loads a bitmap file to use on the GUI.
+ * The filename is also used as its identifier.
*
- * @param filename Name of the bitmap file.
+ * @param filename Name of the bitmap file.
*/
bool addBitmap(const Common::String &filename);
/**
- * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the
- * new Font API is in place. FIXME: Is that so ???
+ * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the
+ * new Font API is in place. FIXME: Is that so ???
*/
bool addTextData(const Common::String &drawDataId, TextData textId, TextColor id, Graphics::TextAlign alignH, TextAlignVertical alignV);
protected:
/**
- * Returns if the Theme is ready to draw stuff on screen.
- * Must be called instead of just checking _initOk, because
- * this checks if the renderer is initialized AND if the theme
- * is loaded.
+ * Returns if the Theme is ready to draw stuff on screen.
+ * Must be called instead of just checking _initOk, because
+ * this checks if the renderer is initialized AND if the theme
+ * is loaded.
*/
bool ready() const {
return _initOk && _themeOk;
@@ -446,15 +446,15 @@ protected:
void loadTheme(const Common::String &themeid);
/**
- * Changes the active graphics mode of the GUI; may be used to either
- * initialize the GUI or to change the mode while the GUI is already running.
+ * Changes the active graphics mode of the GUI; may be used to either
+ * initialize the GUI or to change the mode while the GUI is already running.
*/
void setGraphicsMode(GraphicsMode mode);
public:
/**
- * Finishes buffering: widgets from then on will be drawn straight on the screen
- * without drawing queues.
+ * Finishes buffering: widgets from then on will be drawn straight on the screen
+ * without drawing queues.
*/
inline void finishBuffering() { _buffering = false; }
inline void startBuffering() { _buffering = true; }
@@ -474,21 +474,21 @@ public:
}
/**
- * Interface for the Theme Parser: Creates a new cursor by loading the given
- * bitmap and sets it as the active cursor.
+ * Interface for the Theme Parser: Creates a new cursor by loading the given
+ * bitmap and sets it as the active cursor.
*
- * @param filename File name of the bitmap to load.
- * @param hotspotX X Coordinate of the bitmap which does the cursor click.
- * @param hotspotY Y Coordinate of the bitmap which does the cursor click.
- * @param scale Scale at which the bitmap is supposed to be used.
+ * @param filename File name of the bitmap to load.
+ * @param hotspotX X Coordinate of the bitmap which does the cursor click.
+ * @param hotspotY Y Coordinate of the bitmap which does the cursor click.
+ * @param scale Scale at which the bitmap is supposed to be used.
*/
bool createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale);
/**
- * Wrapper for restoring data from the Back Buffer to the screen.
- * The actual processing is done in the VectorRenderer.
+ * Wrapper for restoring data from the Back Buffer to the screen.
+ * The actual processing is done in the VectorRenderer.
*
- * @param r Area to restore.
+ * @param r Area to restore.
*/
void restoreBackground(Common::Rect r);
@@ -498,33 +498,33 @@ public:
protected:
/**
- * Initializes the drawing screen surfaces, _screen and _backBuffer.
- * If the surfaces already exist, they are cleared and re-initialized.
+ * Initializes the drawing screen surfaces, _screen and _backBuffer.
+ * If the surfaces already exist, they are cleared and re-initialized.
*
- * @param backBuffer Sets whether the _backBuffer surface should be initialized.
- * @template PixelType C type which specifies the size of each pixel.
- * Defaults to uint16 (2 BPP for the surfaces)
+ * @param backBuffer Sets whether the _backBuffer surface should be initialized.
+ * @template PixelType C type which specifies the size of each pixel.
+ * Defaults to uint16 (2 BPP for the surfaces)
*/
template<typename PixelType> void screenInit(bool backBuffer = true);
/**
- * Loads the given theme into the ThemeEngine.
+ * Loads the given theme into the ThemeEngine.
*
- * @param themeId Theme identifier.
- * @returns true if the theme was successfully loaded.
+ * @param themeId Theme identifier.
+ * @returns true if the theme was successfully loaded.
*/
bool loadThemeXML(const Common::String &themeId);
/**
- * Loads the default theme file (the embedded XML file found
- * in ThemeDefaultXML.cpp).
- * Called only when no other themes are available.
+ * Loads the default theme file (the embedded XML file found
+ * in ThemeDefaultXML.cpp).
+ * Called only when no other themes are available.
*/
bool loadDefaultXML();
/**
- * Unloads the currently loaded theme so another one can
- * be loaded.
+ * Unloads the currently loaded theme so another one can
+ * be loaded.
*/
void unloadTheme();
@@ -535,31 +535,31 @@ protected:
Common::String genLocalizedFontFilename(const Common::String &filename) const;
/**
- * Actual Dirty Screen handling function.
- * Handles all the dirty squares in the list, merges and optimizes
- * them when possible and draws them to the screen.
- * Called from updateScreen()
+ * Actual Dirty Screen handling function.
+ * Handles all the dirty squares in the list, merges and optimizes
+ * them when possible and draws them to the screen.
+ * Called from updateScreen()
*/
void renderDirtyScreen();
/**
- * Generates a DrawQueue item and enqueues it so it's drawn to the screen
- * when the drawing queue is processed.
+ * Generates a DrawQueue item and enqueues it so it's drawn to the screen
+ * when the drawing queue is processed.
*
- * If Buffering is enabled, the DrawQueue item will be automatically placed
- * on its corresponding queue.
- * If Buffering is disabled, the DrawQueue item will be processed immediately
- * and drawn to the screen.
+ * If Buffering is enabled, the DrawQueue item will be automatically placed
+ * on its corresponding queue.
+ * If Buffering is disabled, the DrawQueue item will be processed immediately
+ * and drawn to the screen.
*
- * This function is called from all the Widget Drawing methods.
+ * This function is called from all the Widget Drawing methods.
*/
void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false);
void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
- bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0);
+ bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0);
void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
/**
- * DEBUG: Draws a white square and writes some text next to it.
+ * DEBUG: Draws a white square and writes some text next to it.
*/
void debugWidgetPosition(const char *name, const Common::Rect &r);
@@ -603,7 +603,7 @@ protected:
Graphics::Surface _backBuffer;
/** Sets whether the current drawing is being buffered (stored for later
- processing) or drawn directly to the screen. */
+ processing) or drawn directly to the screen. */
bool _buffering;
/** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */
@@ -643,7 +643,7 @@ protected:
/** Queue with all the drawing that must be done to the screen */
Common::List<ThemeItem *> _screenQueue;
- bool _initOk; ///< Class and renderer properly initialized
+ bool _initOk; ///< Class and renderer properly initialized
bool _themeOk; ///< Theme data successfully loaded.
bool _enabled; ///< Whether the Theme is currently shown on the overlay
@@ -661,7 +661,7 @@ protected:
byte *_cursor;
bool _needPaletteUpdates;
uint _cursorWidth, _cursorHeight;
- byte _cursorPal[4*MAX_CURS_COLORS];
+ byte _cursorPal[3 * MAX_CURS_COLORS];
byte _cursorPalSize;
};
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index 70d81a962e..e3523d11e8 100644
--- a/gui/ThemeParser.cpp
+++ b/gui/ThemeParser.cpp
@@ -861,30 +861,50 @@ bool ThemeParser::resolutionCheck(const Common::String &resolution) {
return true;
Common::StringTokenizer globTokenizer(resolution, ", ");
- Common::String cur, w, h;
- bool definedRes = false;
+ Common::String cur;
while (!globTokenizer.empty()) {
- bool ignore = false;
cur = globTokenizer.nextToken();
- if (cur[0] == '-') {
- ignore = true;
- cur.deleteChar(0);
+ bool lt;
+ int val;
+
+ if (cur.size() < 5) {
+ warning("Invalid theme 'resolution' token '%s'", resolution.c_str());
+ return false;
+ }
+
+ if (cur[0] == 'x') {
+ val = g_system->getOverlayWidth();
+ } else if (cur[0] == 'y') {
+ val = g_system->getOverlayHeight();
+ } else {
+ warning("Error parsing theme 'resolution' token '%s'", resolution.c_str());
+ return false;
+ }
+
+ if (cur[1] == '<') {
+ lt = true;
+ } else if (cur[1] == '>') {
+ lt = false;
} else {
- definedRes = true;
+ warning("Error parsing theme 'resolution' token '%s'", resolution.c_str());
+ return false;
}
- Common::StringTokenizer resTokenizer(cur, "x");
- w = resTokenizer.nextToken();
- h = resTokenizer.nextToken();
+ int token = atoi(cur.c_str() + 2);
- if ((w == "X" || atoi(w.c_str()) == g_system->getOverlayWidth()) &&
- (h == "Y" || atoi(h.c_str()) == g_system->getOverlayHeight()))
- return !ignore;
+ // check inverse for unfulfilled requirements
+ if (lt) {
+ if (val >= token)
+ return false;
+ } else {
+ if (val <= token)
+ return false;
+ }
}
- return !definedRes;
+ return true;
}
} // End of namespace GUI
diff --git a/gui/credits.h b/gui/credits.h
index 926adf4c9c..a6a8a4f483 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -158,8 +158,10 @@ static const char *credits[] = {
"C0""Filippos Karapetis",
"",
"C1""Mohawk",
+"C0""Bastien Bouclet",
"C0""Matthew Hoops",
"C0""Filippos Karapetis",
+"C0""Alyssa Milburn",
"C0""Eugene Sandulenko",
"C0""David Turner",
"",
@@ -210,6 +212,7 @@ static const char *credits[] = {
"",
"C1""Backend Teams",
"C1""Android",
+"C0""Andre Heider",
"C0""Angus Lees",
"",
"C1""Dreamcast",
@@ -259,6 +262,9 @@ static const char *credits[] = {
"C0""Jurgen Braam",
"C0""Lars Persson",
"",
+"C1""WebOS",
+"C0""Klaus Reimer",
+"",
"C1""Wii",
"C0""Andre Heider",
"",
@@ -279,7 +285,7 @@ static const char *credits[] = {
"C0""David Corrales-Lopez",
"C2""Filesystem access improvements (GSoC 2007 task) (retired)",
"C0""Jerome Fisher",
-"C2""MT-32 emulator (retired)",
+"C2""MT-32 emulator",
"C0""Benjamin Haisch",
"C2""Heavily improved de-/encoder for DXA videos",
"C0""Jochen Hoenicke",
@@ -294,6 +300,23 @@ static const char *credits[] = {
"C0""Fredrik Wendel",
"C2""(retired)",
"",
+"C1""Website (maintenance)",
+"C0""James Brown",
+"C2""IRC Logs maintainer",
+"C0""Thierry Crozat",
+"C2""Wiki maintainer",
+"C0""Andre Heider",
+"C2""Buildbot maintainer",
+"C0""Max Horn",
+"C2""Forum, IRC channel and Mailing list maintainer",
+"C0""Joost Peters",
+"C2""Doxygen Project Documentation maintainer",
+"C0""Jordi Vilalta Prat",
+"C2""Wiki maintainer",
+"C0""Eugene Sandulenko",
+"C2""Forum, IRC channel, Screen Shots and Mailing list maintainer",
+"C0""John Willis",
+"",
"C1""Website (content)",
"C0""All active team members",
"C0""",
@@ -430,6 +453,9 @@ static const char *credits[] = {
"C1""Spanish",
"C0""Tom\341s Maidagan",
"",
+"C1""Swedish",
+"C0""Hampus Flink",
+"",
"C1""Ukrainian",
"C0""Lubomyr Lisen",
"",
@@ -445,6 +471,8 @@ static const char *credits[] = {
"C2""ScummVM logo",
"C0""Raina",
"C2""ScummVM forum buttons",
+"C0""William Claydon",
+"C2""Skins for doxygen and wiki",
"",
"C1""Code contributions",
"C0""Ori Avtalion",
@@ -456,7 +484,7 @@ static const char *credits[] = {
"C0""Martin Doucha",
"C2""CinE engine objectification",
"C0""Thomas Fach-Pedersen",
-"C2""ProTracker module player",
+"C2""ProTracker module player, Smacker video decoder",
"C0""Tobias Gunkel",
"C2""Sound support for C64 version of MM/Zak, Loom PCE support",
"C0""Janne Huttunen",
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index af567c65d8..0cb06458ef 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -201,14 +201,15 @@ void GuiManager::redraw() {
_theme->clearAll();
_theme->openDialog(true, ThemeEngine::kShadingNone);
- for (i = 0; i < _dialogStack.size() - 1; i++) {
+ for (i = 0; i < _dialogStack.size() - 1; i++)
_dialogStack[i]->drawDialog();
- }
_theme->finishBuffering();
+ // fall through
+
case kRedrawOpenDialog:
- _theme->updateScreen();
+ _theme->updateScreen(false);
_theme->openDialog(true, shading);
_dialogStack.top()->drawDialog();
_theme->finishBuffering();
@@ -293,7 +294,6 @@ void GuiManager::runLoop() {
Common::Event event;
while (eventMan->pollEvent(event)) {
-
// The top dialog can change during the event loop. In that case, flush all the
// dialog-related events since they were probably generated while the old dialog
// was still visible, and therefore not intended for the new one.
@@ -305,12 +305,6 @@ void GuiManager::runLoop() {
Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
- if (lastRedraw + waitTime < _system->getMillis()) {
- _theme->updateScreen();
- _system->updateScreen();
- lastRedraw = _system->getMillis();
- }
-
switch (event.type) {
case Common::EVENT_KEYDOWN:
activeDialog->handleKeyDown(event.kbd);
@@ -365,6 +359,12 @@ void GuiManager::runLoop() {
default:
break;
}
+
+ if (lastRedraw + waitTime < _system->getMillis()) {
+ _theme->updateScreen();
+ _system->updateScreen();
+ lastRedraw = _system->getMillis();
+ }
}
if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) {
@@ -441,10 +441,10 @@ void GuiManager::closeTopDialog() {
void GuiManager::setupCursor() {
const byte palette[] = {
- 255, 255, 255, 0,
- 255, 255, 255, 0,
- 171, 171, 171, 0,
- 87, 87, 87, 0
+ 255, 255, 255,
+ 255, 255, 255,
+ 171, 171, 171,
+ 87, 87, 87
};
CursorMan.pushCursorPalette(palette, 0, 4);
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 3236071055..2716e6ca72 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1,5 +1,5 @@
"<?xml version = '1.0'?>"
-"<layout_info resolution='-320xY,-256x240,-Xx272,-544x332,-Xx350'> "
+"<layout_info resolution='y>399'> "
"<globals> "
"<def var='Line.Height' value='16' /> "
"<def var='Font.Height' value='16' /> "
@@ -789,7 +789,7 @@
"</layout> "
"</dialog> "
"</layout_info> "
-"<layout_info resolution='320xY,256x240,Xx272,544x332,Xx350'> "
+"<layout_info resolution='y<400'> "
"<globals> "
"<def var='Line.Height' value='12' /> "
"<def var='Font.Height' value='10' /> "
@@ -1602,21 +1602,21 @@
"<font id='text_default' "
"file='helvb12.bdf' "
"/> "
-"<font resolution='320xY,256x240' "
+"<font resolution='y<400' "
"id='text_default' "
"file='clR6x12.bdf' "
"/> "
"<font id='text_button' "
"file='helvb12.bdf' "
"/> "
-"<font resolution='320xY,256x240' "
+"<font resolution='y<400' "
"id='text_button' "
"file='clR6x12.bdf' "
"/> "
"<font id='text_normal' "
"file='helvb12.bdf' "
"/> "
-"<font resolution='320xY,256x240' "
+"<font resolution='y<400' "
"id='text_normal' "
"file='clR6x12.bdf' "
"/> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 9fd2c187fd..4dbedd4f14 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index f0276969fe..17e934d5ef 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.2:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.8.3:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx
index d672db2540..3fd00abbb9 100644
--- a/gui/themes/scummclassic/classic_gfx.stx
+++ b/gui/themes/scummclassic/classic_gfx.stx
@@ -46,21 +46,21 @@
<font id = 'text_default'
file = 'helvb12.bdf'
/>
- <font resolution = '320xY, 256x240'
+ <font resolution = 'y<400'
id = 'text_default'
file = 'clR6x12.bdf'
/>
<font id = 'text_button'
file = 'helvb12.bdf'
/>
- <font resolution = '320xY, 256x240'
+ <font resolution = 'y<400'
id = 'text_button'
file = 'clR6x12.bdf'
/>
<font id = 'text_normal'
file = 'helvb12.bdf'
/>
- <font resolution = '320xY, 256x240'
+ <font resolution = 'y<400'
id = 'text_normal'
file = 'clR6x12.bdf'
/>
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 416ffb30eb..f09c29e360 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = '-320xY, -256x240, -Xx272, -544x332, -Xx350'>
+<layout_info resolution = 'y>399'>
<globals>
<def var = 'Line.Height' value = '16' />
<def var = 'Font.Height' value = '16' />
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index fe0eb66b8d..a440be7694 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = "320xY, 256x240, Xx272, 544x332, Xx350">
+<layout_info resolution = 'y<400'>
<globals>
<def var = 'Line.Height' value = '12' />
<def var = 'Font.Height' value = '10' />
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index f4e18ef00c..77951475e6 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index b8f41fc207..f947a5685a 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.2:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.3:ScummVM Modern Theme:No Author]
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index cfe00a7016..a325d4982b 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -108,21 +108,21 @@
<font id = 'text_default'
file = 'helvb12.bdf'
/>
- <font resolution = '320xY, 256x240'
+ <font resolution = 'y<400'
id = 'text_default'
file = 'clR6x12.bdf'
/>
<font id = 'text_button'
file = 'helvb12.bdf'
/>
- <font resolution = '320xY, 256x240'
+ <font resolution = 'y<400'
id = 'text_button'
file = 'clR6x12.bdf'
/>
<font id = 'text_normal'
file = 'helvb12.bdf'
/>
- <font resolution = '320xY, 256x240'
+ <font resolution = 'y<400'
id = 'text_normal'
file = 'clR6x12.bdf'
/>
@@ -178,7 +178,7 @@
<!-- <defaults fill = 'gradient' fg_color = 'white'/> -->
<cursor file = 'cursor.bmp' hotspot = '0, 0' scale = '3'/>
- <cursor resolution = '320xY, 256x240' file = 'cursor_small.bmp' hotspot = '0, 0' scale = '3'/>
+ <cursor resolution = 'y<400' file = 'cursor_small.bmp' hotspot = '0, 0' scale = '3'/>
<!-- Selection (text or list items) -->
<drawdata id = 'text_selection' cache = 'false'>
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 879be2aafe..32d6d19d1a 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = '-320xY, -256x240, -Xx272, -544x332, -Xx350'>
+<layout_info resolution = 'y>399'>
<globals>
<def var = 'Line.Height' value = '16' />
<def var = 'Font.Height' value = '16' />
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 3a7a4b63b9..06916a80f1 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -23,7 +23,7 @@
- $Id$
-
-->
-<layout_info resolution = "320xY, 256x240, Xx272, 544x332, Xx350">
+<layout_info resolution = 'y<400'>
<globals>
<def var = 'Line.Height' value = '12' />
<def var = 'Font.Height' value = '10' />
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index 69e4c80804..e488b45347 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/icons/scummvm.icns b/icons/scummvm.icns
index 0e2b9b800b..f5618a59d2 100644
--- a/icons/scummvm.icns
+++ b/icons/scummvm.icns
Binary files differ
diff --git a/po/ca_ES.po b/po/ca_ES.po
index 993aee9874..6aea7b3314 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-09-21 23:12+0100\n"
"Last-Translator: Jordi Vilalta Prat <jvprat@jvprat.com>\n"
"Language-Team: Catalan <scummvm-devel@lists.sf.net>\n"
@@ -64,11 +64,11 @@ msgstr "Tanca"
msgid "Mouse click"
msgstr "Clic del ratolэ"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Mostra el teclat"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Remapeja les tecles"
@@ -421,15 +421,15 @@ msgstr "Cerca:"
msgid "Clear value"
msgstr "Neteja el valor"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Carrega partida:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Carrega"
@@ -443,16 +443,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Sэ"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "No"
@@ -974,35 +974,35 @@ msgstr "Pintat amb antialias (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Amb antialias (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "El motor no suporta el nivell de depuraciѓ '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menњ"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Salta"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pausa"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Salta la lэnia"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Error al executar el joc:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "No s'ha pogut trobar cap motor capaч d'executar el joc seleccionat"
@@ -1110,17 +1110,17 @@ msgid "~R~eturn to Launcher"
msgstr "~R~etorna al Llanчador"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Desa la partida:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Desa"
@@ -1183,8 +1183,12 @@ msgstr "Veus"
msgid "Pause game"
msgstr "Desa la partida:"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
@@ -1192,8 +1196,10 @@ msgstr ""
msgid "Load game state 1-10"
msgstr "Carrega partida:"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1208,12 +1214,8 @@ msgstr "Desa la partida:"
msgid "Quit"
msgstr "Surt"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
msgstr ""
#: engines/scumm/help.cpp:89
@@ -1230,10 +1232,6 @@ msgid "Text speed slower / faster"
msgstr ""
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr ""
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr ""
@@ -1255,66 +1253,34 @@ msgid "Show / Hide console"
msgstr "Mostra/Oculta el cursor"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr ""
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr ""
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr ""
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr ""
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr ""
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
#, fuzzy
msgid "Toggle aspect-ratio correction"
msgstr "Correcciѓ de la relaciѓ d'aspecte"
@@ -1723,7 +1689,7 @@ msgstr ""
msgid "Fly to lower right"
msgstr ""
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1734,7 +1700,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1745,7 +1711,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1768,11 +1734,11 @@ msgstr "~T~ransicions activades"
msgid "~W~ater Effect Enabled"
msgstr "~E~fecte de l'aigua activat"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Desa la partida:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Restaura"
@@ -1925,8 +1891,6 @@ msgid "Touchpad mode disabled."
msgstr "Mode Touchpad desactivat."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (sense escalar)"
@@ -1935,19 +1899,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (no escalat)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2207,13 +2167,13 @@ msgstr "Cursor Esquerra"
msgid "Cursor Right"
msgstr "Cursor Dreta"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Voleu carregar o desar el joc?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Esteu segur de voler sortir? "
@@ -2237,35 +2197,32 @@ msgstr "Pantalla "
msgid "Do you want to perform an automatic scan ?"
msgstr "Voleu fer una cerca automрtica?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Desa"
diff --git a/po/cs_CZ.po b/po/cs_CZ.po
index 865e9647ff..fbd39ce0d7 100644
--- a/po/cs_CZ.po
+++ b/po/cs_CZ.po
@@ -2,12 +2,12 @@
# Copyright (C) YEAR ScummVM Team
# This file is distributed under the same license as the ScummVM package.
# Zbynьk Schwarz <zbynek.schwarz@gmail.com>, 2011.
-#
+#
msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2011-02-06 21:53+0100\n"
"Last-Translator: Zbynьk Schwarz <zbynek.schwarz@gmail.com>\n"
"Language-Team: \n"
@@ -68,11 +68,11 @@ msgstr "Zavјэt"
msgid "Mouse click"
msgstr "Kliknutэ myЙэ"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Zobrazit klсvesnici"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Pјemapovat klсvesy"
@@ -420,15 +420,15 @@ msgstr "Hledat:"
msgid "Clear value"
msgstr "Vyшistit hodnotu"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Nahrсt hru:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Nahrсt"
@@ -442,16 +442,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Ano"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Ne"
@@ -964,35 +964,35 @@ msgstr "Vykreslovaш s vyhlazen§mi hranami(16bpp)"
msgid "Antialiased (16bpp)"
msgstr "S vyhlazen§mi hranami (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Jсdro nepodporuje њroveђ ladьnэ '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menu"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Pјeskoшit"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pauza"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Pјeskoшit јсdek"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Chyba pјi spuЙtьnэ hry:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Nelze nalщzt Осdnщ jсdro schopnщ vybranou hru spustit"
@@ -1100,17 +1100,17 @@ msgid "~R~eturn to Launcher"
msgstr "~N~сvrat do SpouЙtьшe"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "UloОit hru:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "UloОit"
@@ -1169,17 +1169,23 @@ msgstr "Mezernэk"
msgid "Pause game"
msgstr "Pozastavit hru"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Nahrсt stav hry 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1192,13 +1198,9 @@ msgstr "UloОit stav hry 1-10"
msgid "Quit"
msgstr "Ukonшit"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x,Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1213,10 +1215,6 @@ msgid "Text speed slower / faster"
msgstr "Zv§Йit / SnэОit rychlost textu"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Napodobit levщ tlaшitko myЙi"
@@ -1237,66 +1235,34 @@ msgid "Show / Hide console"
msgstr "Ukсzat / Skr§t konzoli"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Spustit ladэcэ program"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Zobrazit spotјebu pamьti"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Spustit v rychlщm reОimu (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Spustit ve velmi rychlщm reОimu (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Povolit zachycovсnэ myЙi"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Pјepэnat mezi grafick§mi filtry"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +,-"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "ZvьtЙit / ZmenЙit faktor zmьny velikosti"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Povolit korekci pomьru stran"
@@ -1693,7 +1659,7 @@ msgstr "Letьt doprava"
msgid "Fly to lower right"
msgstr "Letьt doprava dolљ"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1704,7 +1670,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1715,7 +1681,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1738,11 +1704,11 @@ msgstr "~P~јechody zapnuty"
msgid "~W~ater Effect Enabled"
msgstr "~E~fekt Vody Zapnut"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Obnovit hru"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Obnovit"
@@ -1895,8 +1861,6 @@ msgid "Touchpad mode disabled."
msgstr "Touchpad reОim vypnut"
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normсlnэ (bez zmьny veliosti)"
@@ -1905,19 +1869,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normсlnэ (bez zmьny veliosti)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL Normсlnэ"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL Zachovсvajэcэ"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL Pљvodnэ"
@@ -2177,13 +2137,13 @@ msgstr "Љipka Doleva"
msgid "Cursor Right"
msgstr "Љipka Doprava"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Chcete hru nahrсt nebo uloОit?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Jste si jisti, Оe chcete odejэt ? "
@@ -2207,37 +2167,38 @@ msgstr "Displej"
msgid "Do you want to perform an automatic scan ?"
msgstr "Chcete provщst automatickщ hledсnэ?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Mapovat шinnost pravщ kliknutэ"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Musэte namapovat klсvesu pro шinnost 'Pravщ Kliknutэ', abyste tuto hru mohi "
"hrсt"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Mapovat шinnost skr§t panel nсstrojљ"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
"Musэte namapovat klсvesu pro шinnost 'Skr§t Panel nсstrojљ', abyste tuto hru "
"mohli hrсt"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Namapovat шinnost PјiblэОit Nahoru (nepovinnщ)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Namapovat шinnost PјiblэОit Dolљ (nepovinnщ)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Nezapomeђte namapovat klсvesu k шinnosti 'Skr§t Panel Nсstrojљ, abyste "
"vidьli cel§ inventсј"
+
diff --git a/po/da_DA.po b/po/da_DA.po
index 429d4493cb..af898b0cd1 100644
--- a/po/da_DA.po
+++ b/po/da_DA.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2011-01-08 22:53+0100\n"
"Last-Translator: Steffen Nyeland <steffen@nyeland.dk>\n"
"Language-Team: Steffen Nyeland <steffen@nyeland.dk>\n"
@@ -64,11 +64,11 @@ msgstr "Luk"
msgid "Mouse click"
msgstr "Muse klik"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Vis tastatur"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Kortlцg taster"
@@ -418,15 +418,15 @@ msgstr "Sјg:"
msgid "Clear value"
msgstr "Slet vцrdi"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Indlцs spil:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Indlцs"
@@ -440,16 +440,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Ja"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nej"
@@ -961,35 +961,35 @@ msgstr "Antialias renderer (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Antialias (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Motor understјtter ikke fejlfindingsniveau '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menu"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Spring over"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pause"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Spring linje over"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Fejl ved kјrsel af spil:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Kunne ikke finde nogen motor istand til at afvikle det valgte spil"
@@ -1097,17 +1097,17 @@ msgid "~R~eturn to Launcher"
msgstr "~R~etur til oversigt"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Gemmer:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Gem"
@@ -1166,17 +1166,23 @@ msgstr "Mellemrum"
msgid "Pause game"
msgstr "Pause spil"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Hent spil tilstand 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1189,13 +1195,9 @@ msgstr "Gem spil tilstand 1-10"
msgid "Quit"
msgstr "Afslut"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x, Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1210,10 +1212,6 @@ msgid "Text speed slower / faster"
msgstr "Tekst hastighed langsommere / hurtigere"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Simulere venstre museknap"
@@ -1234,66 +1232,34 @@ msgid "Show / Hide console"
msgstr "Vis / Skjul konsol"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Start fejlfinder"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Vis hukommelsesforbrug"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Kјr i hurtig tilstand (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Kјr i meget hurtig tilstand (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Skift muse fanger"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Skift mellem grafik filtre"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +, -"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "Hцv / Sцnk skaleringsfaktor"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Skift billedformat korrektion"
@@ -1690,7 +1656,7 @@ msgstr "Flyv til hјjre"
msgid "Fly to lower right"
msgstr "Flyv nederst til hјjre"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1701,7 +1667,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1712,7 +1678,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1735,11 +1701,11 @@ msgstr "~O~vergange aktiveret"
msgid "~W~ater Effect Enabled"
msgstr "~V~andeffekter aktiveret"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Gendan spil:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Gendan"
@@ -1892,8 +1858,6 @@ msgid "Touchpad mode disabled."
msgstr "Pegeplade tilstand deaktiveret."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (ingen skalering)"
@@ -1902,19 +1866,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (ingen skalering)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL Normal"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL Bevar"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL Original"
@@ -2174,13 +2134,13 @@ msgstr "Pil til venstre"
msgid "Cursor Right"
msgstr "Pil til hјjre"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Vil du hente eller gemme spillet?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Er du sikker pх at du vil afslutte ? "
@@ -2204,36 +2164,37 @@ msgstr "Vis"
msgid "Do you want to perform an automatic scan ?"
msgstr "Vil du udfјre en automatisk skanning ?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Tildel hјjreklikshandling"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Du skal tildele en tast til 'Hјjreklik' handlingen for at spille dette spil"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Tildel \"skjul vцrktјjslinje\" handling"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
"Du skal tildele en tast til 'Skjul vцrktјjslinje' handlingen for at spille "
"dette spil"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Tildel Formindsk handling (valgfri)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Tildel Forstјr handling (valgfri)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Glem ikke at tildele en tast til 'Skjul vцrktјjslinje' handling for at se "
"hele oversigten"
+
diff --git a/po/de_DE.po b/po/de_DE.po
index a3a7cdfd23..059fa959d1 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-11-27 22:15+0100\n"
"Last-Translator: Simon Sawatzki <SimSaw@gmx.de>\n"
"Language-Team: Lothar Serra Mari <Lothar@Windowsbase.de> & Simon Sawatzki "
@@ -66,11 +66,11 @@ msgstr "Schlieпen"
msgid "Mouse click"
msgstr "Mausklick"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Tastatur anzeigen"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Tasten neu zuweisen"
@@ -422,15 +422,15 @@ msgstr "Suchen:"
msgid "Clear value"
msgstr "Wert lіschen"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Spiel laden:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Laden"
@@ -444,16 +444,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Ja"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nein"
@@ -975,35 +975,35 @@ msgstr "Kantenglфttung (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Kantenglфttung (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Engine unterstќtzt den Debug-Level \"%s\" nicht."
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menќ"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "мberspringen"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pause"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Zeile ќberspringen"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Fehler beim Ausfќhren des Spiels:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Konnte keine Spiel-Engine finden, die dieses Spiel starten kann."
@@ -1111,17 +1111,17 @@ msgid "~R~eturn to Launcher"
msgstr "Zur Spiele~l~iste"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Speichern:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Speichern"
@@ -1180,16 +1180,22 @@ msgstr "Leertaste"
msgid "Pause game"
msgstr "Spielpause"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Spielstand 1-10 laden"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1203,13 +1209,9 @@ msgstr "Spielstand 1-10 speichern"
msgid "Quit"
msgstr "Beenden"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt+Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1224,10 +1226,6 @@ msgid "Text speed slower / faster"
msgstr "Texttempo langsamer/schneller"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Linke Maustaste simulieren"
@@ -1248,66 +1246,34 @@ msgid "Show / Hide console"
msgstr "Konsole zeigen/verbergen"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Debugger starten"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Speicherverbrauch anzeigen"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Schneller Modus (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Sehr schneller Modus (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Mauseingrenzung in Fenster an/aus"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Zwischen Grafikfiltern wechseln"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "Grіпenverhфtlnis hіher/niedriger"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Seitenverhфltnis anpassen: an/aus"
@@ -1704,7 +1670,7 @@ msgstr "Nach rechts fliegen"
msgid "Fly to lower right"
msgstr "Nach unten rechts fliegen"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1715,7 +1681,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1726,7 +1692,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1749,11 +1715,11 @@ msgstr "мber~g~фnge aktiviert"
msgid "~W~ater Effect Enabled"
msgstr "~W~assereffekt aktiviert"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Spiel laden:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Laden"
@@ -1906,8 +1872,6 @@ msgid "Touchpad mode disabled."
msgstr "Touchpad-Modus ausgeschaltet."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (keine Skalierung)"
@@ -1916,19 +1880,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal ohn.Skalieren"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2188,13 +2148,13 @@ msgstr "Zeiger nach links"
msgid "Cursor Right"
msgstr "Zeiger nach rechts"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Mіchten Sie ein Spiel laden oder speichern?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Mіchten Sie wirklich beenden? "
@@ -2218,69 +2178,38 @@ msgstr "Anzeige"
msgid "Do you want to perform an automatic scan ?"
msgstr "Mіchten Sie eine automatische Durchsuchung vornehmen?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Aktion \"Rechtsklick\" zuweisen"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Sie mќssen der Aktion \"Rechtsklick\" eine Taste zuweisen, um dieses Spiel "
"spielen zu kіnnen."
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Aktion \"Werkzeugleiste verbergen\" zuweisen"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
"Sie mќssen der Aktion \"Werkzeugleiste verbergen\" eine Taste zuweisen, um "
"dieses Spiel spielen zu kіnnen."
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Aktion \"Herauszoomen\" zuweisen (optional)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Aktion \"Hineinzoomen\" zuweisen (optional)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Vergessen Sie nicht, der Aktion \"Werkzeugleiste verbergen\" eine Taste "
"zuzuweisen, um das ganze Inventar sehen zu kіnnen."
-#~ msgid "Failed to load any GUI theme, aborting"
-#~ msgstr "Fehler: Konnte kein Benutzeroberflфchen-Thema laden. Abbruch..."
-
-#~ msgid "User picked target '%s' (gameid '%s')...\n"
-#~ msgstr "Gewфhltes Ziel: \"%s\" (Spielkennung \"%s\")...\n"
-
-#~ msgid " Looking for a plugin supporting this gameid... "
-#~ msgstr ""
-#~ " Suche nach einer Erweiterung, die diese Spielkennung unterstќtzt..."
-
-#~ msgid "failed\n"
-#~ msgstr "fehlgeschlagen\n"
-
-#~ msgid ""
-#~ "%s is an invalid gameid. Use the --list-games option to list supported "
-#~ "gameid"
-#~ msgstr ""
-#~ "%s ist eine ungќltige Spielkennung. Benutzen Sie die Option --list-games "
-#~ "zum Anzeigen der unterstќtzten Spielkennungen."
-
-#~ msgid " Starting '%s'\n"
-#~ msgstr " Starte \"%s\"\n"
-
-#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')"
-#~ msgstr "%s konnte Engine nicht starten: %s (Ziel \"%s\", Pfad \"%s\")"
-
-#~ msgid "Music driver:"
-#~ msgstr "Musiktreiber:"
-
-#~ msgid "Creative Music System"
-#~ msgstr "Creative-Musik-System"
diff --git a/po/es_ES.po b/po/es_ES.po
index 8b3c57fdb0..1f9ff77456 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-09-25 17:11+0100\n"
"Last-Translator: Tomсs Maidagan\n"
"Language-Team: \n"
@@ -64,11 +64,11 @@ msgstr "Cerrar"
msgid "Mouse click"
msgstr "Clic de ratѓn"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Mostrar el teclado"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Asignar teclas"
@@ -418,15 +418,15 @@ msgstr "Buscar:"
msgid "Clear value"
msgstr "Eliminar valor"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Cargar juego:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Cargar"
@@ -440,16 +440,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Sэ"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "No"
@@ -968,35 +968,35 @@ msgstr "Suavizado (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Suavizado (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "El motor no soporta el nivel de debug '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menњ"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Saltar"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pausar"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Saltar frase"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Error al ejecutar el juego:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "No se ha podido encontrar ningњn motor capaz de ejecutar el juego"
@@ -1104,17 +1104,17 @@ msgid "~R~eturn to Launcher"
msgstr "~V~olver al lanzador"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Guardar partida"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Guardar"
@@ -1177,8 +1177,12 @@ msgstr "Voz"
msgid "Pause game"
msgstr "Guardar partida"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
@@ -1186,8 +1190,10 @@ msgstr ""
msgid "Load game state 1-10"
msgstr "Cargar juego:"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1202,12 +1208,8 @@ msgstr "Guardar partida"
msgid "Quit"
msgstr "Salir"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
msgstr ""
#: engines/scumm/help.cpp:89
@@ -1224,10 +1226,6 @@ msgid "Text speed slower / faster"
msgstr ""
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr ""
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr ""
@@ -1249,66 +1247,34 @@ msgid "Show / Hide console"
msgstr "Mostrar/ocultar cursor"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr ""
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr ""
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr ""
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr ""
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr ""
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
#, fuzzy
msgid "Toggle aspect-ratio correction"
msgstr "Correcciѓn de aspecto"
@@ -1717,7 +1683,7 @@ msgstr ""
msgid "Fly to lower right"
msgstr ""
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1728,7 +1694,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1739,7 +1705,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1762,11 +1728,11 @@ msgstr "Tra~n~siciones activadas"
msgid "~W~ater Effect Enabled"
msgstr "Efecto ag~u~a activado"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Cargar partida:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Cargar"
@@ -1919,8 +1885,6 @@ msgid "Touchpad mode disabled."
msgstr "Modo Touchpad desactivado."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (sin reescalado)"
@@ -1929,19 +1893,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2201,13 +2161,13 @@ msgstr "Izquierda"
msgid "Cursor Right"
msgstr "Derecha"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "ПQuieres cargar o guardar el juego?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr "ПSeguro que quieres salir?"
@@ -2231,36 +2191,33 @@ msgstr "Pantalla"
msgid "Do you want to perform an automatic scan ?"
msgstr "ПQuieres realizar una bњsqueda automсtica?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
#, fuzzy
msgid "Map right click action"
msgstr "Clic derecho"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Guardar"
diff --git a/po/fr_FR.po b/po/fr_FR.po
index cdadf119cd..5465c2a629 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-11-23 22:43+0100\n"
"Last-Translator: Thierry Crozat <criezy@scummvm.org>\n"
"Language-Team: French <scummvm-devel@lists.sf.net>\n"
@@ -65,11 +65,11 @@ msgstr "Fermer"
msgid "Mouse click"
msgstr "Clic de souris"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Afficher le clavier"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Changer l'affectation des touches"
@@ -420,15 +420,15 @@ msgstr "Filtre:"
msgid "Clear value"
msgstr "Effacer la valeur"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Charger le jeu:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Charger"
@@ -442,16 +442,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Oui"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Non"
@@ -976,35 +976,35 @@ msgstr "Rendu Anti-crщnelщ (16 bpp)"
msgid "Antialiased (16bpp)"
msgstr "Anti-crщnelщ (16 bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Le niveau de debug '%s' n'est pas supportщ par ce moteur de jeu"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menu"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Passer"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Mettre en pause"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Passer la phrase"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Erreur lors de l'щxщcution du jeu:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Impossible de trouver un moteur pour exщcuter le jeu sщlectionnщ"
@@ -1112,17 +1112,17 @@ msgid "~R~eturn to Launcher"
msgstr "Retour au ~L~anceur"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Sauvegarde:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Sauver"
@@ -1181,16 +1181,22 @@ msgstr "Espace"
msgid "Pause game"
msgstr "Mettre en pause:"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Charger sauvegarde 1-10:"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1204,13 +1210,9 @@ msgstr "Щcrire sauvegarde 1-10:"
msgid "Quit"
msgstr "Quitter"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Entrer"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Entrer"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1225,10 +1227,6 @@ msgid "Text speed slower / faster"
msgstr "Diminuer/Augmenter vitesse du texte"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Entrer"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Simuler bouton gauche de la souris"
@@ -1249,66 +1247,34 @@ msgid "Show / Hide console"
msgstr "Afficher/Cacher la console"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Ouvrir le dщbugger"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Afficher la consomation de mщmoire"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Jouer en mode rapide (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Jouer en mode trшs rapide (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Capturer/Libщrer la souris"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Changer de filtre graphique"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "Augmenter/Diminuer le facteur d'щchelle"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Changer correction du rapport d'aspect"
@@ -1707,7 +1673,7 @@ msgstr "Voler vers la droite"
msgid "Fly to lower right"
msgstr "Voler vers la bas р droite"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1718,7 +1684,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1729,7 +1695,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1752,11 +1718,11 @@ msgstr "T~r~ansitions activщ"
msgid "~W~ater Effect Enabled"
msgstr "~E~ffets de l'Eau Activщs"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Charger le jeu:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Charger"
@@ -1909,8 +1875,6 @@ msgid "Touchpad mode disabled."
msgstr "Mode touchpad dщsactivщ"
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (щchelle d'origine)"
@@ -1919,19 +1883,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2191,13 +2151,13 @@ msgstr "Gauche"
msgid "Cursor Right"
msgstr "Droit"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Voulez-vous charger ou enregistrer le jeu?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr "Voulez-vous vraiment quitter?"
@@ -2221,104 +2181,38 @@ msgstr "Affichage"
msgid "Do you want to perform an automatic scan ?"
msgstr "Voulez-vous exщcuter une recherche automatique?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Affecter l'action 'Clic Droit'"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Vous devez affecter une touche р l'action de 'Clic Droit' pour pouvoir jouer "
"р ce jeu"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Affecter l'action 'Cacher Bar d'Outils'"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
"Vous devez affecter une touche р l'action 'Cacher Bar d'Outils' pour pouvoir "
"jouer р ce jeu"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Affecter l'action 'Dщzoomer' (optionnelle)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Affecter l'action 'Zoomer' (optionnelle)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Noubliez pas d'affecter une touche р l'action 'Cacher Bar d'Outils' pour "
"pouvoir voir entiшrement l'inventaire"
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Sauver"
-
-#~ msgid "Failed to load any GUI theme, aborting"
-#~ msgstr "Aucun thшme GUI n'a pu ъtre chargщ; abandon"
-
-#~ msgid "User picked target '%s' (gameid '%s')...\n"
-#~ msgstr "L'utilisateur a choisi la cible '%s' (ID '%s')...\n"
-
-#~ msgid " Looking for a plugin supporting this gameid... "
-#~ msgstr "Recherche d'un plugin supportant cet ID..."
-
-#~ msgid "failed\n"
-#~ msgstr "Echec\n"
-
-#~ msgid ""
-#~ "%s is an invalid gameid. Use the --list-games option to list supported "
-#~ "gameid"
-#~ msgstr ""
-#~ "%s n'est pas un ID de jeu valide. Utilisez l'option --list-games pour "
-#~ "obtenir la liste des ID reconnus"
-
-#~ msgid " Starting '%s'\n"
-#~ msgstr "Dщmarrage de '%s'\n"
-
-#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')"
-#~ msgstr ""
-#~ "Le plugin %s a щchouщ dans l'instanciation du moteur de jeu: %s (cible '%"
-#~ "s', chemin '%s')"
-
-#~ msgid "Music driver:"
-#~ msgstr "Pilote audio:"
-
-#~ msgid "Atari ST MIDI"
-#~ msgstr "MIDI Atari ST"
-
-#~ msgid "About..."
-#~ msgstr "A propos..."
-
-#~ msgid "Options..."
-#~ msgstr "Options..."
-
-#~ msgid "Start"
-#~ msgstr "Lancer"
-
-#~ msgid "Load..."
-#~ msgstr "Charger..."
-
-#~ msgid "Edit Game..."
-#~ msgstr "Prщfщrence du Jeu..."
-
-#~ msgid "Remove Game"
-#~ msgstr "Supprimer le Jeu"
-
-#~ msgid "Speech Only"
-#~ msgstr "Audio Uniquement"
-
-#~ msgid "Speech and Subtitles"
-#~ msgstr "Audio et Sous-titres"
-
-#~ msgid "Subtitles Only"
-#~ msgstr "Sous-titres Uniquement"
-
-#~ msgid "Speech & Subs"
-#~ msgstr "Parole & Sous-titres"
diff --git a/po/hu_HU.po b/po/hu_HU.po
index 80b40da1f4..4969629a45 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-12-01 09:23+0100\n"
"Last-Translator: Gruby <grubycza@hotmail.com>\n"
"Language-Team: Hungarian\n"
@@ -68,11 +68,11 @@ msgstr "Bezсr"
msgid "Mouse click"
msgstr "Egщrkattintсs"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Billentyћzet beсllэtсsok"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Billentyћk сtсllэtсsa"
@@ -420,15 +420,15 @@ msgstr "Keresщs:"
msgid "Clear value"
msgstr "Щrtщk tіrlщse"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Jсtщk betіltщse:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Betіltщs"
@@ -442,16 +442,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Igen"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nem"
@@ -963,35 +963,35 @@ msgstr "Щlsimэtсsos lekщpezѕ (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Щlsimэtott (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "A motor nem tсmogatja a '%s' debug szintet"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menќ"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Tovсbb"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Szќnet"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Sor сtlщpщse"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Hiba a jсtщk futtatсsakor:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Nem talсlhatѓ olyan jсtщkmotor ami a vсlasztott jсtщkot tсmogatja"
@@ -1099,17 +1099,17 @@ msgid "~R~eturn to Launcher"
msgstr "Visszatщrщs az indэtѓba"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Jсtщk mentщse:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Mentщs"
@@ -1168,17 +1168,23 @@ msgstr "Szѓkіz"
msgid "Pause game"
msgstr "Szќnet a jсtщkban"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "1-10 Jсtщkсllсs betіltщse"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1191,13 +1197,9 @@ msgstr "1-10 Jсtщkсllсs mentщse"
msgid "Quit"
msgstr "Kilщpщs"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x, Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1212,10 +1214,6 @@ msgid "Text speed slower / faster"
msgstr "Szіvegsebessщg gyors / lassњ"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Bal egщrgomb szimulсciѓ"
@@ -1236,66 +1234,34 @@ msgid "Show / Hide console"
msgstr "Konzol be / ki kapcsolсs"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Hibakeresѕ indэtсsa"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Memѓriakihasznсltsсg lсtszik"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Futtatсs gyors mѓdban (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Futtatсs tњlgyors mѓdban (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Egщr rіgzэtщs kapcsolѓ"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Kapcsolсs grafikus szћrѕk kіzіtt"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +, -"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "Lщptщk nіvelщs / csіkkentщs"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Mщretarсny korrekciѓ kapcsolѓ"
@@ -1692,7 +1658,7 @@ msgstr "Jobbra repќlщs"
msgid "Fly to lower right"
msgstr "Jobbra le repќlщs"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1703,7 +1669,7 @@ msgstr ""
"\n"
"%s fсjlba nem sikerќlt"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1714,7 +1680,7 @@ msgstr ""
"\n"
"%s fсjlbѓl nem sikerќlt"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1737,11 +1703,11 @@ msgstr "Сtmenetek engedщlyezve"
msgid "~W~ater Effect Enabled"
msgstr "Vэzeffektus engedщlyezve"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Jсtщkmenet visszaсllэtсsa:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Visszaсllэtсs"
@@ -1894,8 +1860,6 @@ msgid "Touchpad mode disabled."
msgstr "Touchpad mѓd letiltva."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normсl (nincs сtmщretezщs)"
@@ -1904,19 +1868,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normсl (nincs сtmщretezщs)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL Normсl"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL Megtartott"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL Eredeti"
@@ -2176,13 +2136,13 @@ msgstr "Kurzor Bal"
msgid "Cursor Right"
msgstr "Kurzor Jobb"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Jсtщkсllсs betіltщse vagy mentщse?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Biztos hogy ki akarsz lщpni ? "
@@ -2206,75 +2166,34 @@ msgstr "Kijelzѕ"
msgid "Do you want to perform an automatic scan ?"
msgstr "El akarod kezdeni az automatikus vizsgсlatot ?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Jobbkatt mћvelet gomb"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr "Vсlassz egy billentyћt a 'Jobbkatt' mћvelethez"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Eszkіztсr rejtщs gomb"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr "Vсlassz egy billentyћt az 'Eszkіztсr rejtщs' mћvelethez"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Nagyэtсs mћvelet (opcionсlis)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Kicsinyэtщs mћvelet (opcionсlis)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Ne felejts billentyћt tсrsэtani az 'Eszkіztсr rejtщs' mћvelethez, hogy lсsd "
"a teljes listсt"
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Mentщs"
-
-#, fuzzy
-#~ msgctxt "context"
-#~ msgid "Game Path:"
-#~ msgstr "Extra кtvonal:"
-
-#, fuzzy
-#~ msgctxt "lowres"
-#~ msgid "True Roland MT-32 (disable GM emulation)"
-#~ msgstr "Igaz Roland MT-32 (megbщnэt GM emulсciѓ)"
-
-#, fuzzy
-#~ msgctxt "lowres"
-#~ msgid "Save Path: "
-#~ msgstr "Extra кtvonal:"
-
-#~ msgid "Music driver:"
-#~ msgstr "Zenei vezet :"
-
-#, fuzzy
-#~ msgid "CoreAudio"
-#~ msgstr "Hang"
-
-#, fuzzy
-#~ msgid "AdLib"
-#~ msgstr "Hang"
-
-#~ msgid "Speech Only"
-#~ msgstr "Csak a beszщd"
-
-#~ msgid "Speech and Subtitles"
-#~ msgstr "Beszщd щs a Feliratok"
-
-#~ msgid "Subtitles Only"
-#~ msgstr "Csak feliratok"
-
-#~ msgid "Speech & Subs"
-#~ msgstr "Beszщd s Feliratok"
diff --git a/po/it_IT.po b/po/it_IT.po
index 705a6b4fb4..c9e1f89901 100644
--- a/po/it_IT.po
+++ b/po/it_IT.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-09-21 19:33+0100\n"
"Last-Translator: Matteo 'Maff' Angelino <matteo.maff at gmail dot com>\n"
"Language-Team: Italian\n"
@@ -64,11 +64,11 @@ msgstr "Chiudi"
msgid "Mouse click"
msgstr "Clic del mouse"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Mostra tastiera"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Riprogramma tasti"
@@ -417,15 +417,15 @@ msgstr "Cerca:"
msgid "Clear value"
msgstr "Cancella"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Carica gioco:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Carica"
@@ -439,16 +439,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Sь"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "No"
@@ -968,35 +968,35 @@ msgstr "Renderer con antialiasing (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Con antialiasing (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Il motore non supporta il livello di debug '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menu"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Salta"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pausa"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Salta battuta"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Errore nell'esecuzione del gioco:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr ""
"Impossibile trovare un motore in grado di eseguire il gioco selezionato"
@@ -1105,17 +1105,17 @@ msgid "~R~eturn to Launcher"
msgstr "~V~ai a elenco giochi"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Salva gioco:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Salva"
@@ -1178,8 +1178,12 @@ msgstr "Voci"
msgid "Pause game"
msgstr "Salva gioco:"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
@@ -1187,8 +1191,10 @@ msgstr ""
msgid "Load game state 1-10"
msgstr "Carica gioco:"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1203,12 +1209,8 @@ msgstr "Salva gioco:"
msgid "Quit"
msgstr "Esci"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
msgstr ""
#: engines/scumm/help.cpp:89
@@ -1225,10 +1227,6 @@ msgid "Text speed slower / faster"
msgstr ""
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr ""
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr ""
@@ -1250,66 +1248,34 @@ msgid "Show / Hide console"
msgstr "Mostra/nascondi cursore"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr ""
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr ""
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr ""
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr ""
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr ""
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
#, fuzzy
msgid "Toggle aspect-ratio correction"
msgstr "Correzione proporzioni"
@@ -1718,7 +1684,7 @@ msgstr ""
msgid "Fly to lower right"
msgstr ""
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1729,7 +1695,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1740,7 +1706,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1763,11 +1729,11 @@ msgstr "~T~ransizioni attive"
msgid "~W~ater Effect Enabled"
msgstr "~E~ffetto acqua attivo"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Ripristina gioco:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Ripristina"
@@ -1920,8 +1886,6 @@ msgid "Touchpad mode disabled."
msgstr "Modalitр touchpad disattivata."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normale (nessun ridimensionamento)"
@@ -1930,19 +1894,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normale (no ridim.)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2202,13 +2162,13 @@ msgstr "Cursore a sinistra"
msgid "Cursor Right"
msgstr "Cursore a destra"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Vuoi caricare o salvare il gioco?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Sei sicuro di voler uscire? "
@@ -2232,36 +2192,33 @@ msgstr "Visualizza "
msgid "Do you want to perform an automatic scan ?"
msgstr "Vuoi eseguire una scansione automatica?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
#, fuzzy
msgid "Map right click action"
msgstr "Clic destro"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Salva"
diff --git a/po/module.mk b/po/module.mk
index 30fcd0669d..d2d6127321 100644
--- a/po/module.mk
+++ b/po/module.mk
@@ -33,11 +33,8 @@ updatepot:
mv -f $@.new $@; \
fi;
-#$(srcdir)/common/messages.cpp: $(POFILES)
-# perl $(srcdir)/tools/po2c $^ > $(srcdir)/common/messages.cpp
-
-translations-dat: tools/create_translations
- tools/create_translations/create_translations $(POFILES)
+translations-dat: devtools/create_translations
+ devtools/create_translations/create_translations $(POFILES)
mv translations.dat $(srcdir)/gui/themes/
update-translations: updatepot $(POFILES) translations-dat
diff --git a/po/nb_NO.po b/po/nb_NO.po
index 54bc891595..9fd6038483 100644
--- a/po/nb_NO.po
+++ b/po/nb_NO.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-12-22 22:32+0100\n"
"Last-Translator: Einar Johan T. Sјmхen\n"
"Language-Team: somaen <einarjohants@gmail.com>\n"
@@ -68,11 +68,11 @@ msgstr "Lukk"
msgid "Mouse click"
msgstr "Musklikk"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Vis tastatur"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Omkoble taster"
@@ -422,15 +422,15 @@ msgstr "Sјk:"
msgid "Clear value"
msgstr "Tјm verdi"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Хpne spill:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Хpne"
@@ -444,16 +444,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Ja"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nei"
@@ -965,35 +965,35 @@ msgstr "Antialiased Tegner (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Antialiased (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Motoren stјtter ikke debug-nivх '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Meny"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Hopp over"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pause"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Hopp over linje"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Problem ved kjјring av spill:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Kunne ikke finne noen motor som kunne kjјre det valgte spillet"
@@ -1101,17 +1101,17 @@ msgid "~R~eturn to Launcher"
msgstr "~T~ilbake til oppstarter"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Lagret spill:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Lagre"
@@ -1170,17 +1170,23 @@ msgstr "Space"
msgid "Pause game"
msgstr "Pause spill"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Хpne spilltilstand 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1193,13 +1199,9 @@ msgstr "Lagre spilltilstand 1-10"
msgid "Quit"
msgstr "Avslutt"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x, Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1214,10 +1216,6 @@ msgid "Text speed slower / faster"
msgstr "Tekstfart saktere/raskere"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Simuler venstre mustast"
@@ -1238,66 +1236,34 @@ msgid "Show / Hide console"
msgstr "Vis / Skjul konsollen"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Start debuggeren"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Vis minneforbruk"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Kjјr i rask modus (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Kjјr i virkelig rask modus (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Veksle muslхsing"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Bytt grafikkfiltre"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +, -"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "иk / Minsk skaleringsfaktor"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Veksle aspekt-rate korrigering"
@@ -1694,7 +1660,7 @@ msgstr "Fly til hјyre"
msgid "Fly to lower right"
msgstr "Fly til nedre hјyre"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1705,7 +1671,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1716,7 +1682,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1739,11 +1705,11 @@ msgstr "~O~verganger aktivert"
msgid "~W~ater Effect Enabled"
msgstr "~V~anneffekt aktivert"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Gjennopprett spill:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Gjenopprett"
@@ -1896,8 +1862,6 @@ msgid "Touchpad mode disabled."
msgstr "Touchpad-modus deaktivert."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (ingen skalering)"
@@ -1906,19 +1870,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (ingen skalering)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL Normal"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL Bevar"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL Original"
@@ -2179,13 +2139,13 @@ msgstr "Peker venstre"
msgid "Cursor Right"
msgstr "Peker hјyre"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Vil du хpne eller lagre spillet?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Er du sikker pх at du vil avslutte ?"
@@ -2209,36 +2169,37 @@ msgstr "Skjerm"
msgid "Do you want to perform an automatic scan ?"
msgstr "Vil du utfјre et automatisk sјk?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Koble handling til hјyreklikk"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Du mх koble en tast til handlingen 'Hјyreklikk' for х spille dette spillet"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Koble skjul-verktјylinje-handlingen"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
"Du mх koble en tast til 'Skjul verktјylinje'-handlingen for х spille dette "
"spillet"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Koble handlingen Zoom Opp (valgfritt)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Koble handlingen Zoom Ned (valgfritt)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Ikke glem х koble en tast til handlingen 'Skjul verktјylinje' for х se hele "
"inventaret"
+
diff --git a/po/nn_NO.po b/po/nn_NO.po
index 7b2c54eed8..536daba496 100644
--- a/po/nn_NO.po
+++ b/po/nn_NO.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-12-23 00:42+0100\n"
"Last-Translator: Einar Johan T. Sјmхen\n"
"Language-Team: somaen <einarjohants@gmail.com>\n"
@@ -68,11 +68,11 @@ msgstr "Steng"
msgid "Mouse click"
msgstr "Musklikk"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Syn Tastatur"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Omkople tastar"
@@ -422,15 +422,15 @@ msgstr "Sјk:"
msgid "Clear value"
msgstr "Tјm verdi"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Хpne spel:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Хpne"
@@ -442,16 +442,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Ja"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nei"
@@ -964,35 +964,35 @@ msgstr "Antialiased Teiknar (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Antialiased (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Motoren stјttar ikkje debug-nivх '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Meny"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Hopp over"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pause"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Hopp over linje"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Feil under kјyring av spel:"
-#: base/main.cpp:460
+#: base/main.cpp:459
#, fuzzy
msgid "Could not find any engine capable of running the selected game"
msgstr "Kunne ikkje finne nokon motor som kunne kјyre det velde spelet."
@@ -1103,17 +1103,17 @@ msgid "~R~eturn to Launcher"
msgstr "~T~ilbake til oppstarter"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Lagra spel:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Lagre"
@@ -1173,17 +1173,23 @@ msgstr ""
msgid "Pause game"
msgstr "Pause spel"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Хpne speltilstand 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1196,13 +1202,9 @@ msgstr "Lagre speltilstand 1-10"
msgid "Quit"
msgstr "Avslutt"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x, Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1217,10 +1219,6 @@ msgid "Text speed slower / faster"
msgstr "Tekstfart saktare / fortare"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Simuler venstre musknapp"
@@ -1241,66 +1239,34 @@ msgid "Show / Hide console"
msgstr "Vis / Skjul konsoll"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Start debuggaren"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Vis minneforbruk"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Kјyr i rask modus (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Kјyr i verkeleg rask modus (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Veksle muslхsing"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Veksle grafikkfiltre"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +, -"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "иk/Minsk skaleringsfaktor"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Veksle aspekt-korrigering"
@@ -1697,7 +1663,7 @@ msgstr "Fly til hјgre"
msgid "Fly to lower right"
msgstr "Fly til nedre hјgre"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1705,7 +1671,7 @@ msgid ""
"%s"
msgstr ""
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1713,7 +1679,7 @@ msgid ""
"%s"
msgstr ""
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1733,11 +1699,11 @@ msgstr "~O~vergangar aktivert"
msgid "~W~ater Effect Enabled"
msgstr "~V~anneffekt aktivert"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Gjenopprett spel:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Gjenopprett"
@@ -1890,8 +1856,6 @@ msgid "Touchpad mode disabled."
msgstr ""
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (inga skalering)"
@@ -1900,19 +1864,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (inga skalering)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL Normal"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL Bevar"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL Original"
@@ -2172,13 +2132,13 @@ msgstr "Peikar venstre"
msgid "Cursor Right"
msgstr "Peikar hјgre"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Vil du хpne eller lagre spelet?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr "Er du sikker pх at du vil avslutte?"
@@ -2202,34 +2162,35 @@ msgstr "Skjerm"
msgid "Do you want to perform an automatic scan ?"
msgstr "Vil du utfјre eit automatisk sјk?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Kople hјgreklikkshandling"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Du mх kople ein tast til 'Hјgreklikk'-handlinga for х spele dette spelet"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Kople skjul-verktјylinje-handlinga"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr "Du mх kople ein tast til 'Skjul verktјylinje' for х spele dette spelet"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Kople Zoom Opp-handling (valfri)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Kople Zoom Ned-handling (valfri)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Ikkje glјym х kople ein tast til 'Skjul verktјylinje' for х se heile "
"inventaret"
+
diff --git a/po/pl_PL.po b/po/pl_PL.po
index 6d27cc8c65..2e645ae03c 100644
--- a/po/pl_PL.po
+++ b/po/pl_PL.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.2.0\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2011-01-10 19:42+0100\n"
"Last-Translator: \n"
"Language-Team: Grajpopolsku.pl <grajpopolsku@gmail.com>\n"
@@ -68,11 +68,11 @@ msgstr "Zamknij"
msgid "Mouse click"
msgstr "Klikniъcie"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "WyЖwietl klawiaturъ"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Dostosuj klawisze"
@@ -420,15 +420,15 @@ msgstr "Szukaj"
msgid "Clear value"
msgstr "WyczyЖц"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Wczytaj grъ:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Wczytaj"
@@ -441,16 +441,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Tak"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nie"
@@ -965,35 +965,35 @@ msgstr "WygГadzany renderer (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "WygГadzany (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Silnik nie wspiera poziomu debugowania '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menu"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Pomiё"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Wstrzymaj"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Pomiё liniъ"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "BГБd podczas uruchamiania gry:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Nie udaГo siъ znaleМц silnika zdolnego do uruchomienia zaznaczonej gry"
@@ -1101,17 +1101,17 @@ msgid "~R~eturn to Launcher"
msgstr "~P~owrѓt do launchera"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Zapis:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Zapisz"
@@ -1170,17 +1170,23 @@ msgstr "Spacja"
msgid "Pause game"
msgstr "Wstrzymaj grъ"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Wczytaj stan gry 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1193,13 +1199,9 @@ msgstr "Zapisz stan gry 1-10"
msgid "Quit"
msgstr "Zakoёcz"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x, Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1214,10 +1216,6 @@ msgid "Text speed slower / faster"
msgstr "Zwiъksz/zmniejsz prъdkoЖц tekstu"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Symuluje lewy przycisk myszy"
@@ -1238,66 +1236,34 @@ msgid "Show / Hide console"
msgstr "Schowaj / pokaП konsolъ"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "WГБcz debugger"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "PokaП zuПycie pamiъci"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "WГБcz w trybie szybkim (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "WГБcz w trybie bardzo szybkim (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "WГБcz/wyГБcz przechwytywanie myszy"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "PrzeГБczaj pomiъdzy filtrami grafiki"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +, -"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "Zwiъksz / zmniejsz wspѓГczynnik skalowania"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "WГБcz/wyГБcz korekcjъ formatu obrazu"
@@ -1694,7 +1660,7 @@ msgstr "Leц w prawo"
msgid "Fly to lower right"
msgstr "Leц w dѓГ, w prawo"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1705,7 +1671,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1716,7 +1682,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1739,11 +1705,11 @@ msgstr "~P~rzejЖcia wГБczone"
msgid "~W~ater Effect Enabled"
msgstr "~E~fekty wody wГБczone"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Wznѓw grъ:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Wznѓw"
@@ -1896,8 +1862,6 @@ msgid "Touchpad mode disabled."
msgstr "Tryb touchpada wyГБczony."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "ZwykГy (bez skalowania)"
@@ -1906,19 +1870,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "ZwykГy (bez skalowania)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL - normalny"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL - zachow."
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL - 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL - pierw."
@@ -2178,13 +2138,13 @@ msgstr "Kursor w lewo"
msgid "Cursor Right"
msgstr "Kursor w prawo"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Chcesz wczytaц bБdМ zapisaц grъ?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Na pewno chcesz wyjЖц? "
@@ -2208,33 +2168,34 @@ msgstr "Obraz "
msgid "Do you want to perform an automatic scan ?"
msgstr "Wykonaц automatyczne skanowanie?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Przypisz dziaГanie PPM"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr "Musisz przypisaц klawisz do 'PPM', by zagraц w tъ grъ"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Przypisz chowanie paska narzъdzi"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr "Musisz przypisaц przycisk 'Schowaj pasek narzъdzi', by zagraц w tъ grъ"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Przypisz PrzybliПanie (opcjonalne)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Przypisz Oddalenie (opcjonalne)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Nie zapomnij przypisaц klawisza 'Ukryj pasek narzъdzi', by widzieц caГy "
"ekwipunek"
+
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 3c477faa88..fced3d259c 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-12-09 11:11-0300\n"
"Last-Translator: Saulo Benigno <saulobenigno@gmail.com>\n"
"Language-Team: ScummBR (www.scummbr.com) <scummbr@yahoo.com.br>\n"
@@ -68,11 +68,11 @@ msgstr "Fechar"
msgid "Mouse click"
msgstr "Clique do mouse"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Mostrar teclado"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Remapear teclas"
@@ -421,15 +421,15 @@ msgstr "Pesquisar:"
msgid "Clear value"
msgstr "Limpar valor"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Carregar jogo:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Carregar"
@@ -443,16 +443,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Sim"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Nуo"
@@ -970,35 +970,35 @@ msgstr "Renderizador Anti-Serrilhamento (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Anti-Serrilhamento (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Essa engine nуo suporta o nэvel de debug '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Menu"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Pular"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Pausar"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Pula linha"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Erro ao executar o jogo:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr ""
"Nуo foi possэvel encontrar qualquer programa capaz de rodar o jogo "
@@ -1108,17 +1108,17 @@ msgid "~R~eturn to Launcher"
msgstr "~V~oltar ao menu"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Salvar jogo:"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Salvar"
@@ -1177,17 +1177,23 @@ msgstr "Espaчo"
msgid "Pause game"
msgstr "Pausar jogo:"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr "Carregar estado do jogo 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
msgid "Save game state 1-10"
@@ -1200,13 +1206,9 @@ msgstr "Salvar estado do jogo 1-10"
msgid "Quit"
msgstr "Sair"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr "Alt x, Ctrl z"
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
@@ -1221,10 +1223,6 @@ msgid "Text speed slower / faster"
msgstr "Velocidade do texto devagar / rсpido"
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr "Enter"
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr "Simula botуo esquerdo do mouse"
@@ -1245,66 +1243,34 @@ msgid "Show / Hide console"
msgstr "Mostrar / Ocultar console"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr "Ctrl d"
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr "Inicia o depurador"
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr "Ctrl s"
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr "Exibe o consumo de memѓria"
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr "Ctrl f"
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr "Joga em modo rсpido (*)"
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr "Ctrl g"
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr "Joga em modo super rсpido (*)"
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr "Ctrl m"
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr "Habilita captura do mouse"
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr "Ctrl Alt 1-8"
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr "Alterna entre os filtros grсficos"
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr "Ctrl Alt +, -"
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr "Aumenta / Diminui o fator de escala"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr "Ctrl Alt a"
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr "Habilita correчуo de proporчуo"
@@ -1701,7 +1667,7 @@ msgstr "Voar para direita"
msgid "Fly to lower right"
msgstr "Voar para direita inferior"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1712,7 +1678,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1723,7 +1689,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1746,11 +1712,11 @@ msgstr "Modo ~T~ransiчѕes ativado"
msgid "~W~ater Effect Enabled"
msgstr "Modo ~E~feitos de сgua ativado"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Restaurar jogo:"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Restaurar"
@@ -1903,8 +1869,6 @@ msgid "Touchpad mode disabled."
msgstr "Modo Touchpad desligado."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Normal (sem escala)"
@@ -1913,19 +1877,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (sem escala)"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr "OpenGL Normal"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr "OpenGL Conserve"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr "OpenGL 4/3"
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr "OpenGL Original"
@@ -2185,13 +2145,13 @@ msgstr "Cursor para a esquerda"
msgid "Cursor Right"
msgstr "Cursor para a direita"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Vocъ deseja carregar ou salvar o jogo?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Tem certeza de que deseja sair? "
@@ -2215,40 +2175,37 @@ msgstr "Tela"
msgid "Do you want to perform an automatic scan ?"
msgstr "Vocъ quer executar uma busca automсtica?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Mapear aчуo \"Clique da Direita\""
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
"Vocъ precisa mapear uma tecla para aчуo do \"Clique da Direita\" nesse jogo"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Mapear \"Ocultar barra de ferramentas\""
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
"Vocъ precisa mapear uma tecla para aчуo do \"Ocultar barra de ferramentas\" "
"nesse jogo"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Mapear Zoom para Cima (opcional)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Mapear Zoom para Baixo (opcional)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Nуo se esqueчa de mapear uma tecla para \"Ocultar a barra de ferramentas\" "
"para ver todo o seu inventсrio"
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Salvar"
diff --git a/po/ru_RU.po b/po/ru_RU.po
index 01f73849d4..c23e9a69ca 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: 2010-06-13 20:55+0300\n"
"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
"Language-Team: Russian\n"
@@ -66,11 +66,11 @@ msgstr "Закрыть"
msgid "Mouse click"
msgstr "Клик мышью"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Показать клавиатуру"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Переназначить клавиши"
@@ -420,15 +420,15 @@ msgstr "Поиск:"
msgid "Clear value"
msgstr "Очистить значение"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Загрузить игру:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Загрузить"
@@ -442,16 +442,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Да"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Нет"
@@ -971,35 +971,35 @@ msgstr "Растеризатор со сглаживанием (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Растеризатор со сглаживанием (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Движок не поддерживает уровень отладки '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Меню"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Пропустить"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Пауза"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Пропустить строку"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Ошибка запуска игры:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Не могу найти движок для запуска выбранной игры"
@@ -1107,17 +1107,17 @@ msgid "~R~eturn to Launcher"
msgstr "~В~ главное меню"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Сохранить игру: "
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Записать"
@@ -1180,8 +1180,12 @@ msgstr "Озв"
msgid "Pause game"
msgstr "Сохранить игру: "
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
@@ -1189,8 +1193,10 @@ msgstr ""
msgid "Load game state 1-10"
msgstr "Загрузить игру:"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1205,12 +1211,8 @@ msgstr "Сохранить игру: "
msgid "Quit"
msgstr "Выход"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
msgstr ""
#: engines/scumm/help.cpp:89
@@ -1227,10 +1229,6 @@ msgid "Text speed slower / faster"
msgstr ""
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr ""
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr ""
@@ -1252,66 +1250,34 @@ msgid "Show / Hide console"
msgstr "Показать/Убрать курсор"
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr ""
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr ""
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr ""
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr ""
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr ""
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
#, fuzzy
msgid "Toggle aspect-ratio correction"
msgstr "Коррекция соотношения сторон"
@@ -1720,7 +1686,7 @@ msgstr ""
msgid "Fly to lower right"
msgstr ""
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1731,7 +1697,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1742,7 +1708,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1765,11 +1731,11 @@ msgstr "Переходы активированы"
msgid "~W~ater Effect Enabled"
msgstr "Эффекты воды включены"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Восстановить игру: "
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Восствновить"
@@ -1922,8 +1888,6 @@ msgid "Touchpad mode disabled."
msgstr "Режим тачпада выключен."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Без увеличения"
@@ -1932,19 +1896,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Без увеличения"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2204,13 +2164,13 @@ msgstr "Курсор влево"
msgid "Cursor Right"
msgstr "Курсор вправо"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Вы хотите загрузить либо сохранить игру?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Вы уверены, что хотите выйти? "
@@ -2234,37 +2194,34 @@ msgstr "Показать "
msgid "Do you want to perform an automatic scan ?"
msgstr "Вы хотите произвести автоматический поиск?"
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr "Назначить действие по правому щелчку"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr "Вы должны назначить клавишу на действие 'Right Click' для этой игры"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr "Назначить действие 'спрятать панель инструментов'"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr "Вы должны назначить клавишу на дейтствие 'Hide toolbar' для этой игры"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr "Назначить действие Увеличить Масштаб (необязательно)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr "Назначить действие Уменьшить Масштаб (необязательно)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
"Не забудьте назначить клавишу для действия 'Hide Toolbar' чтобы увидеть весь "
"инвентарь в игре"
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Записать"
diff --git a/po/scummvm.pot b/po/scummvm.pot
index e1be51f70b..150885fb92 100644
--- a/po/scummvm.pot
+++ b/po/scummvm.pot
@@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: ScummVM 1.3.0svn\n"
+"Project-Id-Version: ScummVM 1.3.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -64,11 +64,11 @@ msgstr ""
msgid "Mouse click"
msgstr ""
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr ""
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr ""
@@ -414,15 +414,15 @@ msgstr ""
msgid "Clear value"
msgstr ""
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr ""
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr ""
@@ -434,16 +434,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr ""
@@ -948,35 +948,35 @@ msgstr ""
msgid "Antialiased (16bpp)"
msgstr ""
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr ""
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr ""
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr ""
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr ""
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr ""
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr ""
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr ""
@@ -1084,17 +1084,17 @@ msgid "~R~eturn to Launcher"
msgstr ""
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr ""
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr ""
@@ -1153,16 +1153,22 @@ msgstr ""
msgid "Pause game"
msgstr ""
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
msgstr ""
#: engines/scumm/help.cpp:82
msgid "Load game state 1-10"
msgstr ""
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
msgstr ""
#: engines/scumm/help.cpp:83
@@ -1176,12 +1182,8 @@ msgstr ""
msgid "Quit"
msgstr ""
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
msgstr ""
#: engines/scumm/help.cpp:89
@@ -1197,10 +1199,6 @@ msgid "Text speed slower / faster"
msgstr ""
#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr ""
-
-#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
msgstr ""
@@ -1221,66 +1219,34 @@ msgid "Show / Hide console"
msgstr ""
#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
-
-#: engines/scumm/help.cpp:98
msgid "Start the debugger"
msgstr ""
#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
msgstr ""
#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
msgstr ""
#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
msgstr ""
#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
msgstr ""
#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
msgstr ""
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
msgid "Toggle aspect-ratio correction"
msgstr ""
@@ -1677,7 +1643,7 @@ msgstr ""
msgid "Fly to lower right"
msgstr ""
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1685,7 +1651,7 @@ msgid ""
"%s"
msgstr ""
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1693,7 +1659,7 @@ msgid ""
"%s"
msgstr ""
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1713,11 +1679,11 @@ msgstr ""
msgid "~W~ater Effect Enabled"
msgstr ""
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr ""
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr ""
@@ -1870,8 +1836,6 @@ msgid "Touchpad mode disabled."
msgstr ""
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr ""
@@ -1880,19 +1844,15 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
msgstr ""
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
msgstr ""
@@ -2152,13 +2112,13 @@ msgstr ""
msgid "Cursor Right"
msgstr ""
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr ""
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr ""
@@ -2182,31 +2142,31 @@ msgstr ""
msgid "Do you want to perform an automatic scan ?"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:981
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
msgstr ""
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
diff --git a/po/se_SE.po b/po/se_SE.po
new file mode 100644
index 0000000000..465a2779bd
--- /dev/null
+++ b/po/se_SE.po
@@ -0,0 +1,2208 @@
+# Swedish translation for ScummVM.
+# Copyright (C) 2011 ScummVM Team
+# This file is distributed under the same license as the ScummVM package.
+# Hampus Flink <hampus.flink@gmail.com>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.3.0svn\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
+"PO-Revision-Date: 2011-03-21 13:45+0100\n"
+"Last-Translator: Hampus Flink <hampus.flink@gmail.com>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: Svenska\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"X-Poedit-Language: Swedish\n"
+"X-Poedit-Country: SWEDEN\n"
+"X-Poedit-SourceCharset: iso-8859-1\n"
+
+#: gui/about.cpp:96
+#, c-format
+msgid "(built on %s)"
+msgstr ""
+
+#: gui/about.cpp:103
+msgid "Features compiled in:"
+msgstr ""
+
+#: gui/about.cpp:112
+msgid "Available engines:"
+msgstr ""
+
+#: gui/browser.cpp:70
+msgid "Go up"
+msgstr "Uppхt"
+
+#: gui/browser.cpp:70 gui/browser.cpp:72
+msgid "Go to previous directory level"
+msgstr "Gх till fіregхende katalognivх"
+
+#: gui/browser.cpp:72
+msgctxt "lowres"
+msgid "Go up"
+msgstr "Uppхt"
+
+#: gui/browser.cpp:73 gui/chooser.cpp:49 gui/KeysDialog.cpp:46
+#: gui/launcher.cpp:319 gui/massadd.cpp:95 gui/options.cpp:1116
+#: gui/saveload.cpp:66 gui/saveload.cpp:158 gui/themebrowser.cpp:57
+#: backends/platform/wii/options.cpp:48
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: gui/browser.cpp:74 gui/chooser.cpp:50 gui/themebrowser.cpp:58
+msgid "Choose"
+msgstr "Vфlj"
+
+#: gui/gui-manager.cpp:106 engines/scumm/help.cpp:128
+#: engines/scumm/help.cpp:143 engines/scumm/help.cpp:168
+#: engines/scumm/help.cpp:193 engines/scumm/help.cpp:211
+#: backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Stфng"
+
+#: gui/gui-manager.cpp:109
+msgid "Mouse click"
+msgstr "Musklick"
+
+#: gui/gui-manager.cpp:112 base/main.cpp:286
+msgid "Display keyboard"
+msgstr "Visa tangentbord"
+
+#: gui/gui-manager.cpp:115 base/main.cpp:289
+msgid "Remap keys"
+msgstr "Stфll in tangenter"
+
+#: gui/KeysDialog.h:39 gui/KeysDialog.cpp:148
+msgid "Choose an action to map"
+msgstr "Vфlj en handling att stфlla in"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "Stфll in"
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:320 gui/launcher.cpp:945
+#: gui/launcher.cpp:949 gui/massadd.cpp:92 gui/options.cpp:1117
+#: backends/platform/wii/options.cpp:47
+#: backends/platform/wince/CELauncherDialog.cpp:58
+msgid "OK"
+msgstr "OK"
+
+#: gui/KeysDialog.cpp:52
+msgid "Select an action and click 'Map'"
+msgstr "Vфlj en handling och klicka pх \"Stфll in\""
+
+#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144
+#, c-format
+msgid "Associated key : %s"
+msgstr "Instфlld tangent: %s"
+
+#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146
+#, c-format
+msgid "Associated key : none"
+msgstr "Instфlld tangent: Ingen"
+
+#: gui/KeysDialog.cpp:93
+msgid "Please select an action"
+msgstr "Var god vфlj en handling"
+
+#: gui/KeysDialog.cpp:109
+msgid "Press the key to associate"
+msgstr "Tryck pх en tangent fіr att stфlla in"
+
+#: gui/launcher.cpp:172
+msgid "Game"
+msgstr "Spel"
+
+#: gui/launcher.cpp:176
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:176 gui/launcher.cpp:178 gui/launcher.cpp:179
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+"Kortnamn fіr spel. Anvфnds fіr att hфnvisa till spardata och att starta "
+"spelet frхn kommandoraden"
+
+#: gui/launcher.cpp:178
+msgctxt "lowres"
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:183
+msgid "Name:"
+msgstr "Namn:"
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:185 gui/launcher.cpp:186
+msgid "Full title of the game"
+msgstr "Spelets fullstфndiga titel"
+
+#: gui/launcher.cpp:185
+msgctxt "lowres"
+msgid "Name:"
+msgstr "Namn:"
+
+#: gui/launcher.cpp:189
+msgid "Language:"
+msgstr "Sprхk:"
+
+#: gui/launcher.cpp:189 gui/launcher.cpp:190
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Spelets sprхk. Den hфr instфllningen omvandlar inte din spanska spelversion "
+"till en engelsk"
+
+#: gui/launcher.cpp:191 gui/launcher.cpp:205 gui/options.cpp:80
+#: gui/options.cpp:646 gui/options.cpp:656 gui/options.cpp:1087
+#: audio/null.cpp:42
+msgid "<default>"
+msgstr "<standard>"
+
+#: gui/launcher.cpp:201
+msgid "Platform:"
+msgstr "Plattform:"
+
+#: gui/launcher.cpp:201 gui/launcher.cpp:203 gui/launcher.cpp:204
+msgid "Platform the game was originally designed for"
+msgstr "Plattformen spelet ursprungligen tillverkades fіr"
+
+#: gui/launcher.cpp:203
+msgctxt "lowres"
+msgid "Platform:"
+msgstr "Plattform:"
+
+#: gui/launcher.cpp:215 gui/options.cpp:956 gui/options.cpp:973
+msgid "Graphics"
+msgstr "Grafik"
+
+#: gui/launcher.cpp:215 gui/options.cpp:956 gui/options.cpp:973
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:218
+msgid "Override global graphic settings"
+msgstr "жverskrid globala grafikinstфllningar"
+
+#: gui/launcher.cpp:220
+msgctxt "lowres"
+msgid "Override global graphic settings"
+msgstr "жverskrid globala grafikinstфllningar"
+
+#: gui/launcher.cpp:227 gui/options.cpp:979
+msgid "Audio"
+msgstr "Ljud"
+
+#: gui/launcher.cpp:230
+msgid "Override global audio settings"
+msgstr "жverskrid globala ljudinstфllningar"
+
+#: gui/launcher.cpp:232
+msgctxt "lowres"
+msgid "Override global audio settings"
+msgstr "жverskrid globala ljudinstфllningar"
+
+#: gui/launcher.cpp:241 gui/options.cpp:984
+msgid "Volume"
+msgstr "Volym"
+
+#: gui/launcher.cpp:243 gui/options.cpp:986
+msgctxt "lowres"
+msgid "Volume"
+msgstr "Volym"
+
+#: gui/launcher.cpp:246
+msgid "Override global volume settings"
+msgstr "жverskrid globala volyminstфllningar"
+
+#: gui/launcher.cpp:248
+msgctxt "lowres"
+msgid "Override global volume settings"
+msgstr "жverskrid globala volyminstфllningar"
+
+#: gui/launcher.cpp:255 gui/options.cpp:994
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:258
+msgid "Override global MIDI settings"
+msgstr "жverskrid globala MIDI-instфllningar"
+
+#: gui/launcher.cpp:260
+msgctxt "lowres"
+msgid "Override global MIDI settings"
+msgstr "жverskrid globala MIDI-instфllningar"
+
+#: gui/launcher.cpp:270 gui/options.cpp:1000
+msgid "MT-32"
+msgstr "MT-32"
+
+#: gui/launcher.cpp:273
+msgid "Override global MT-32 settings"
+msgstr "жverskrid globala MT-32 instфllningar"
+
+#: gui/launcher.cpp:275
+msgctxt "lowres"
+msgid "Override global MT-32 settings"
+msgstr "жverskrid globala MT-32 instфllningar"
+
+#: gui/launcher.cpp:286 gui/options.cpp:1007
+msgid "Paths"
+msgstr "Sіkvфgar"
+
+#: gui/launcher.cpp:288 gui/options.cpp:1009
+msgctxt "lowres"
+msgid "Paths"
+msgstr "Sіkvфgar"
+
+#: gui/launcher.cpp:295
+msgid "Game Path:"
+msgstr "Sіkv. spel:"
+
+#: gui/launcher.cpp:297
+msgctxt "lowres"
+msgid "Game Path:"
+msgstr "Sіkv. spel:"
+
+#: gui/launcher.cpp:302 gui/options.cpp:1029
+msgid "Extra Path:"
+msgstr "Sіkv. extra:"
+
+#: gui/launcher.cpp:302 gui/launcher.cpp:304 gui/launcher.cpp:305
+msgid "Specifies path to additional data used the game"
+msgstr "Bestфmmer sіkvфgen till ytterligare data som spelet anvфnder"
+
+#: gui/launcher.cpp:304 gui/options.cpp:1031
+msgctxt "lowres"
+msgid "Extra Path:"
+msgstr "Sіkv. extra:"
+
+#: gui/launcher.cpp:309 gui/options.cpp:1017
+msgid "Save Path:"
+msgstr "Sіkv. sparat:"
+
+#: gui/launcher.cpp:309 gui/launcher.cpp:311 gui/launcher.cpp:312
+#: gui/options.cpp:1017 gui/options.cpp:1019 gui/options.cpp:1020
+msgid "Specifies where your savegames are put"
+msgstr "Bestфmmer var dina spardata lagras"
+
+#: gui/launcher.cpp:311 gui/options.cpp:1019
+msgctxt "lowres"
+msgid "Save Path:"
+msgstr "Sіkv. sparat:"
+
+#: gui/launcher.cpp:328 gui/launcher.cpp:411 gui/launcher.cpp:460
+#: gui/options.cpp:1026 gui/options.cpp:1032 gui/options.cpp:1039
+#: gui/options.cpp:1140 gui/options.cpp:1146 gui/options.cpp:1152
+#: gui/options.cpp:1160 gui/options.cpp:1184 gui/options.cpp:1188
+#: gui/options.cpp:1194 gui/options.cpp:1201 gui/options.cpp:1300
+msgctxt "path"
+msgid "None"
+msgstr "Ingen"
+
+#: gui/launcher.cpp:333 gui/launcher.cpp:415
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Standard"
+
+#: gui/launcher.cpp:453 gui/options.cpp:1294
+msgid "Select SoundFont"
+msgstr "Vфlj SoundFont"
+
+#: gui/launcher.cpp:472 gui/launcher.cpp:619
+msgid "Select directory with game data"
+msgstr "Vфlj katalog med speldata"
+
+#: gui/launcher.cpp:490
+msgid "Select additional game directory"
+msgstr "Vфlj en ytterligare spelkatalog"
+
+#: gui/launcher.cpp:502
+msgid "Select directory for saved games"
+msgstr "Vфlj katalog fіr spardata"
+
+#: gui/launcher.cpp:521
+msgid "This game ID is already taken. Please choose another one."
+msgstr "Detta ID-namn фr upptaget. Var god vфlj ett annat."
+
+#: gui/launcher.cpp:562 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~A~vsluta"
+
+#: gui/launcher.cpp:562
+msgid "Quit ScummVM"
+msgstr "Avsluta ScummVM"
+
+#: gui/launcher.cpp:563
+msgid "A~b~out..."
+msgstr "O~m~..."
+
+#: gui/launcher.cpp:563
+msgid "About ScummVM"
+msgstr "Om ScummVM"
+
+#: gui/launcher.cpp:564
+msgid "~O~ptions..."
+msgstr "~I~nstфllningar..."
+
+#: gui/launcher.cpp:564
+msgid "Change global ScummVM options"
+msgstr "Redigera globala ScummVM-instфllningar"
+
+#: gui/launcher.cpp:566
+msgid "~S~tart"
+msgstr "~S~tarta"
+
+#: gui/launcher.cpp:566
+msgid "Start selected game"
+msgstr "Starta det valda spelet"
+
+#: gui/launcher.cpp:569
+msgid "~L~oad..."
+msgstr "~L~adda..."
+
+#: gui/launcher.cpp:569
+msgid "Load savegame for selected game"
+msgstr "Ladda spardata fіr det valda spelet"
+
+#: gui/launcher.cpp:574
+msgid "~A~dd Game..."
+msgstr "Lф~g~g till spel..."
+
+#: gui/launcher.cpp:574 gui/launcher.cpp:581
+msgid "Hold Shift for Mass Add"
+msgstr "Hхll ned Skift fіr masstillфgg"
+
+#: gui/launcher.cpp:576
+msgid "~E~dit Game..."
+msgstr "R~e~digera spel..."
+
+#: gui/launcher.cpp:576 gui/launcher.cpp:583
+msgid "Change game options"
+msgstr "Redigera spelinstфllningarna"
+
+#: gui/launcher.cpp:578
+msgid "~R~emove Game"
+msgstr "~R~adera spel"
+
+#: gui/launcher.cpp:578 gui/launcher.cpp:585
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "Radera spelet frхn listan. Spelets datafiler pхverkas inte."
+
+#: gui/launcher.cpp:581
+msgctxt "lowres"
+msgid "~A~dd Game..."
+msgstr "Lф~g~g till spel..."
+
+#: gui/launcher.cpp:583
+msgctxt "lowres"
+msgid "~E~dit Game..."
+msgstr "R~e~digera spel..."
+
+#: gui/launcher.cpp:585
+msgctxt "lowres"
+msgid "~R~emove Game"
+msgstr "~R~adera spel"
+
+#: gui/launcher.cpp:593
+msgid "Search in game list"
+msgstr "Sіk i spellistan"
+
+#: gui/launcher.cpp:597 gui/launcher.cpp:1111
+msgid "Search:"
+msgstr "Sіk:"
+
+#: gui/launcher.cpp:600 gui/options.cpp:764
+msgid "Clear value"
+msgstr "Tіm sіkfфltet"
+
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+msgid "Load game:"
+msgstr "Ladda spel:"
+
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
+msgid "Load"
+msgstr "Ladda"
+
+#: gui/launcher.cpp:731
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"Vill du verkligen anvфnda mass-speldetektorn? Processen kan potentiellt "
+"lфgga till ett enormt antal spel."
+
+#: gui/launcher.cpp:732 gui/launcher.cpp:881
+#: backends/events/symbiansdl/symbiansdl-events.cpp:187
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
+#: backends/platform/wince/CELauncherDialog.cpp:106
+msgid "Yes"
+msgstr "Ja"
+
+#: gui/launcher.cpp:732 gui/launcher.cpp:881
+#: backends/events/symbiansdl/symbiansdl-events.cpp:187
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
+#: backends/platform/wince/CELauncherDialog.cpp:106
+msgid "No"
+msgstr "Nej"
+
+#: gui/launcher.cpp:779
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM kunde inte іppna den valda katalogen!"
+
+#: gui/launcher.cpp:791
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM kunde inte hitta nхgra spel i den valda katalogen!"
+
+#: gui/launcher.cpp:805
+msgid "Pick the game:"
+msgstr "Vфlj spel:"
+
+#: gui/launcher.cpp:881
+msgid "Do you really want to remove this game configuration?"
+msgstr "Vill du verkligen radera den hфr spelkonfigurationen?"
+
+#: gui/launcher.cpp:945
+msgid "This game does not support loading games from the launcher."
+msgstr "Det hфr spelet stіder inte laddning av spardata frхn launchern."
+
+#: gui/launcher.cpp:949
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+"ScummVM kunde inte hitta en motor kapabel till att kіra det valda spelet!"
+
+#: gui/launcher.cpp:1063
+msgctxt "lowres"
+msgid "Mass Add..."
+msgstr "Masstillфgg..."
+
+#: gui/launcher.cpp:1063
+msgid "Mass Add..."
+msgstr "Masstillфgg..."
+
+#: gui/launcher.cpp:1064
+msgctxt "lowres"
+msgid "Add Game..."
+msgstr "Lфgg till spel..."
+
+#: gui/launcher.cpp:1064
+msgid "Add Game..."
+msgstr "Lфgg till spel..."
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... progression ..."
+
+#: gui/massadd.cpp:244
+msgid "Scan complete!"
+msgstr "Scanning fфrdig!"
+
+#: gui/massadd.cpp:247
+#, c-format
+msgid "Discovered %d new games."
+msgstr "Nya spel upptфckta: %d."
+
+#: gui/massadd.cpp:251
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "Kataloger scannade: %d ..."
+
+#: gui/massadd.cpp:254
+#, c-format
+msgid "Discovered %d new games ..."
+msgstr "Nya spel upptфckta: %d ..."
+
+#: gui/options.cpp:78
+msgid "Never"
+msgstr "Aldrig"
+
+#: gui/options.cpp:78
+msgid "every 5 mins"
+msgstr "var 5:e minut"
+
+#: gui/options.cpp:78
+msgid "every 10 mins"
+msgstr "var 10:e minut"
+
+#: gui/options.cpp:78
+msgid "every 15 mins"
+msgstr "var 15:e minut"
+
+#: gui/options.cpp:78
+msgid "every 30 mins"
+msgstr "var 30:e minut"
+
+#: gui/options.cpp:80
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:80
+msgid "11kHz"
+msgstr "11 kHz"
+
+#: gui/options.cpp:80
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:80
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:80
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:241 gui/options.cpp:406 gui/options.cpp:504
+#: gui/options.cpp:563 gui/options.cpp:763
+msgctxt "soundfont"
+msgid "None"
+msgstr "Ingen"
+
+#: gui/options.cpp:643
+msgid "Graphics mode:"
+msgstr "Grafiklфge:"
+
+#: gui/options.cpp:654
+msgid "Render mode:"
+msgstr "Renderingslфge:"
+
+#: gui/options.cpp:654 gui/options.cpp:655
+msgid "Special dithering modes supported by some games"
+msgstr "Speciella gitterlфgen stіdda av vissa spel"
+
+#: gui/options.cpp:664
+msgid "Fullscreen mode"
+msgstr "Fullskфrmslфge"
+
+#: gui/options.cpp:667
+msgid "Aspect ratio correction"
+msgstr "Korrektion av bildfіrhхllande"
+
+#: gui/options.cpp:667
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Korrigerar bildfіrhхllanden fіr 320x200-spel"
+
+#: gui/options.cpp:668
+msgid "EGA undithering"
+msgstr "EGA anti-gitter"
+
+#: gui/options.cpp:668
+msgid "Enable undithering in EGA games that support it"
+msgstr "Aktiverar anti-gitter i EGA spel som stіder det"
+
+#: gui/options.cpp:676
+msgid "Preferred Device:"
+msgstr "Fіredragen enhet:"
+
+#: gui/options.cpp:676
+msgid "Music Device:"
+msgstr "Musikenhet:"
+
+#: gui/options.cpp:676 gui/options.cpp:678
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "Bestфmmer din fіredragna emulator fіr ljudenhet eller ljudkort"
+
+#: gui/options.cpp:676 gui/options.cpp:678 gui/options.cpp:679
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Bestфmmer emulator fіr ljudenhet eller ljudkort"
+
+#: gui/options.cpp:678
+msgctxt "lowres"
+msgid "Preferred Dev.:"
+msgstr "Fіredr. enhet:"
+
+#: gui/options.cpp:678
+msgctxt "lowres"
+msgid "Music Device:"
+msgstr "Musikenhet:"
+
+#: gui/options.cpp:704
+msgid "AdLib emulator:"
+msgstr "AdLib-emulator:"
+
+#: gui/options.cpp:704 gui/options.cpp:705
+msgid "AdLib is used for music in many games"
+msgstr "AdLib anvфnds fіr musik i mхnga spel"
+
+#: gui/options.cpp:715
+msgid "Output rate:"
+msgstr "Ljudfrekvens:"
+
+#: gui/options.cpp:715 gui/options.cpp:716
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"Ett hіgre vфrde betecknar bфttre ljudkvalitet men stіds kanske inte av ditt "
+"ljudkort"
+
+#: gui/options.cpp:726
+msgid "GM Device:"
+msgstr "GM-enhet:"
+
+#: gui/options.cpp:726
+msgid "Specifies default sound device for General MIDI output"
+msgstr "Bestфmmer standardenheten fіr General MIDI-uppspelning"
+
+#: gui/options.cpp:737
+msgid "Don't use General MIDI music"
+msgstr "Anvфnd inte General MIDI-musik"
+
+#: gui/options.cpp:748 gui/options.cpp:809
+msgid "Use first available device"
+msgstr "Anvфnd fіrsta tillgфngliga enhet"
+
+#: gui/options.cpp:760
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:760 gui/options.cpp:762 gui/options.cpp:763
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "SoundFont stіds endast av vissa ljudkort, Fluidsynth och Timidity"
+
+#: gui/options.cpp:762
+msgctxt "lowres"
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:767
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Blandat AdLib/MIDI-lфge"
+
+#: gui/options.cpp:767
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Anvфnd bхde MIDI och AdLib fіr ljudgeneration"
+
+#: gui/options.cpp:770
+msgid "MIDI gain:"
+msgstr "MIDI gain:"
+
+#: gui/options.cpp:780
+msgid "MT-32 Device:"
+msgstr "MT-32 enhet:"
+
+#: gui/options.cpp:780
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"Bestфmmer standardenheten fіr Roland MT-32/LAPC1/CM32I/CM64-uppspelning"
+
+#: gui/options.cpp:785
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Фkta Roland MT-32 (inaktivera GM-emulation)"
+
+#: gui/options.cpp:785 gui/options.cpp:787
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"Aktivera om du vill anvфnda din verkliga Roland-kompatibla och dator-"
+"anslutna ljudenhet"
+
+#: gui/options.cpp:787
+msgctxt "lowres"
+msgid "True Roland MT-32 (no GM emulation)"
+msgstr "Фkta Roland MT-32 (ingen GM-emulation)"
+
+#: gui/options.cpp:790
+msgid "Enable Roland GS Mode"
+msgstr "Aktivera Roland GS-lфge"
+
+#: gui/options.cpp:790
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+"Stфnger av General MIDI-kartlфggning fіr spel med Roland MT-32 soundtrack"
+
+#: gui/options.cpp:799
+msgid "Don't use Roland MT-32 music"
+msgstr "Anvфnd inte Roland MT-32 musik"
+
+#: gui/options.cpp:826
+msgid "Text and Speech:"
+msgstr "Undertext och tal:"
+
+#: gui/options.cpp:830 gui/options.cpp:840
+msgid "Speech"
+msgstr "Tal"
+
+#: gui/options.cpp:831 gui/options.cpp:841
+msgid "Subtitles"
+msgstr "Undertexter"
+
+#: gui/options.cpp:832
+msgid "Both"
+msgstr "Bхda"
+
+#: gui/options.cpp:834
+msgid "Subtitle speed:"
+msgstr "Texthastighet:"
+
+#: gui/options.cpp:836
+msgctxt "lowres"
+msgid "Text and Speech:"
+msgstr "Text och tal:"
+
+#: gui/options.cpp:840
+msgid "Spch"
+msgstr "Tal"
+
+#: gui/options.cpp:841
+msgid "Subs"
+msgstr "Text"
+
+#: gui/options.cpp:842
+msgctxt "lowres"
+msgid "Both"
+msgstr "Bхda"
+
+#: gui/options.cpp:842
+msgid "Show subtitles and play speech"
+msgstr "Visa undertexter och spela upp tal"
+
+#: gui/options.cpp:844
+msgctxt "lowres"
+msgid "Subtitle speed:"
+msgstr "Texthastighet:"
+
+#: gui/options.cpp:860
+msgid "Music volume:"
+msgstr "Musikvolym:"
+
+#: gui/options.cpp:862
+msgctxt "lowres"
+msgid "Music volume:"
+msgstr "Musikvolym:"
+
+#: gui/options.cpp:869
+msgid "Mute All"
+msgstr "Ljud av"
+
+#: gui/options.cpp:872
+msgid "SFX volume:"
+msgstr "SFX-volym:"
+
+#: gui/options.cpp:872 gui/options.cpp:874 gui/options.cpp:875
+msgid "Special sound effects volume"
+msgstr "Volym fіr specialeffekter"
+
+#: gui/options.cpp:874
+msgctxt "lowres"
+msgid "SFX volume:"
+msgstr "SFX-volym:"
+
+#: gui/options.cpp:882
+msgid "Speech volume:"
+msgstr "Talvolym:"
+
+#: gui/options.cpp:884
+msgctxt "lowres"
+msgid "Speech volume:"
+msgstr "Talvolym:"
+
+#: gui/options.cpp:1023
+msgid "Theme Path:"
+msgstr "Sіkv. tema:"
+
+#: gui/options.cpp:1025
+msgctxt "lowres"
+msgid "Theme Path:"
+msgstr "Sіkv. tema:"
+
+#: gui/options.cpp:1029 gui/options.cpp:1031 gui/options.cpp:1032
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+"Bestфmmer sіkvфg till andra data som anvфnds av alla spel eller ScummVM"
+
+#: gui/options.cpp:1036
+msgid "Plugins Path:"
+msgstr "Sіkv. tillфgg:"
+
+#: gui/options.cpp:1038
+msgctxt "lowres"
+msgid "Plugins Path:"
+msgstr "Sіkv. tillфgg:"
+
+#: gui/options.cpp:1047
+msgid "Misc"
+msgstr "Diverse"
+
+#: gui/options.cpp:1049
+msgctxt "lowres"
+msgid "Misc"
+msgstr "Diverse"
+
+#: gui/options.cpp:1051
+msgid "Theme:"
+msgstr "Tema:"
+
+#: gui/options.cpp:1055
+msgid "GUI Renderer:"
+msgstr "GUI-rendering:"
+
+#: gui/options.cpp:1067
+msgid "Autosave:"
+msgstr "Autospara:"
+
+#: gui/options.cpp:1069
+msgctxt "lowres"
+msgid "Autosave:"
+msgstr "Autospara:"
+
+#: gui/options.cpp:1077
+msgid "Keys"
+msgstr "Tangenter"
+
+#: gui/options.cpp:1084
+msgid "GUI Language:"
+msgstr "GUI-sprхk:"
+
+#: gui/options.cpp:1084
+msgid "Language of ScummVM GUI"
+msgstr "Sprхk fіr ScummVM:s anvфndargrфnssnitt"
+
+#: gui/options.cpp:1233
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Du mхste starta om ScummVM fіr att фndringarna ska fх effekt."
+
+#: gui/options.cpp:1246
+msgid "Select directory for savegames"
+msgstr "Vфlj katalog fіr spardata"
+
+#: gui/options.cpp:1253
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+"Det gхr inte att skriva till den valda katalogen. Var god vфlj en annan."
+
+#: gui/options.cpp:1262
+msgid "Select directory for GUI themes"
+msgstr "Vфlj katalog fіr GUI-teman"
+
+#: gui/options.cpp:1272
+msgid "Select directory for extra files"
+msgstr "Vфlj katalog fіr extra filer"
+
+#: gui/options.cpp:1283
+msgid "Select directory for plugins"
+msgstr "Vфlj katalog fіr tillфgg"
+
+#: gui/options.cpp:1328
+msgid ""
+"The theme you selected does not support your current language. If you want "
+"to use this theme you need to switch to another language first."
+msgstr ""
+"Temat du valde stіder inte ditt sprхk. Om du vill anvфnda det hфr temat "
+"mхste fіrst byta till ett annat sprхk."
+
+#: gui/saveload.cpp:61 gui/saveload.cpp:242
+msgid "No date saved"
+msgstr "Inget datum sparat"
+
+#: gui/saveload.cpp:62 gui/saveload.cpp:243
+msgid "No time saved"
+msgstr "Ingen tid sparad"
+
+#: gui/saveload.cpp:63 gui/saveload.cpp:244
+msgid "No playtime saved"
+msgstr "Ingen speltid sparad"
+
+#: gui/saveload.cpp:70 gui/saveload.cpp:158
+msgid "Delete"
+msgstr "Radera"
+
+#: gui/saveload.cpp:157
+msgid "Do you really want to delete this savegame?"
+msgstr "Vill du verkligen radera den hфr spardatan?"
+
+#: gui/saveload.cpp:266
+msgid "Date: "
+msgstr "Datum:"
+
+#: gui/saveload.cpp:269
+msgid "Time: "
+msgstr "Tid:"
+
+#: gui/saveload.cpp:274
+msgid "Playtime: "
+msgstr "Speltid:"
+
+#: gui/saveload.cpp:287 gui/saveload.cpp:354
+msgid "Untitled savestate"
+msgstr "Namnlіs spardata"
+
+#: gui/themebrowser.cpp:47
+msgid "Select a Theme"
+msgstr "Vфlj ett tema"
+
+#: gui/ThemeEngine.cpp:332
+msgid "Disabled GFX"
+msgstr "Inaktiverad GFX"
+
+#: gui/ThemeEngine.cpp:332
+msgctxt "lowres"
+msgid "Disabled GFX"
+msgstr "Inaktiverad GFX"
+
+#: gui/ThemeEngine.cpp:333
+msgid "Standard Renderer (16bpp)"
+msgstr "Standard rendering (16 bpp)"
+
+#: gui/ThemeEngine.cpp:333
+msgid "Standard (16bpp)"
+msgstr "Standard (16 bpp)"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Antialiased Renderer (16bpp)"
+msgstr "Antialiserad rendering (16 bpp)"
+
+#: gui/ThemeEngine.cpp:335
+msgid "Antialiased (16bpp)"
+msgstr "Antialiserad (16 bpp)"
+
+#: base/main.cpp:206
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "Motorn stіder inte debug-nivх '%s'"
+
+#: base/main.cpp:274
+msgid "Menu"
+msgstr "Meny"
+
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
+#: backends/platform/wince/CEActionsPocket.cpp:48
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Skip"
+msgstr "Skippa"
+
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
+#: backends/platform/wince/CEActionsPocket.cpp:45
+msgid "Pause"
+msgstr "Paus"
+
+#: base/main.cpp:283
+msgid "Skip line"
+msgstr "Skippa rad"
+
+#: base/main.cpp:435
+msgid "Error running game:"
+msgstr "Fel under kіrning av spel:"
+
+#: base/main.cpp:459
+msgid "Could not find any engine capable of running the selected game"
+msgstr "Kunde inte hitta en motor kapabel till att kіra det valda spelet"
+
+#: common/error.cpp:43
+msgid "Invalid Path"
+msgstr "Ogiltig sіkvфg"
+
+#: common/error.cpp:44
+msgid "Game Data not found"
+msgstr "Kunde inte hitta speldata"
+
+#: common/error.cpp:45
+msgid "Game Id not supported"
+msgstr "Spel-ID stіds inte"
+
+#: common/error.cpp:46
+msgid "Unsupported Color Mode"
+msgstr "Ej stіtt fфrglфge"
+
+#: common/error.cpp:48
+msgid "Read permission denied"
+msgstr "Lфstillbehіrighet nekad"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "Skrivtillbehіrighet nekad"
+
+#: common/error.cpp:52
+msgid "Path not exists"
+msgstr "Sіkvфgen existerar inte"
+
+#: common/error.cpp:53
+msgid "Path not a directory"
+msgstr "Sіkvфgen фr inte en katalog"
+
+#: common/error.cpp:54
+msgid "Path not a file"
+msgstr "Sіkvфgen фr inte en fil"
+
+#: common/error.cpp:56
+msgid "Cannot create file"
+msgstr "Kan inte skapa fil"
+
+#: common/error.cpp:57
+msgid "Reading failed"
+msgstr "Inlфsning misslyckades"
+
+#: common/error.cpp:58
+msgid "Writing data failed"
+msgstr "Skriva data misslyckades"
+
+#: common/error.cpp:60 common/error.cpp:71
+msgid "Unknown Error"
+msgstr "Okфnt fel"
+
+#: common/util.cpp:276
+msgid "Hercules Green"
+msgstr "Herkules grіn"
+
+#: common/util.cpp:277
+msgid "Hercules Amber"
+msgstr "Herkules bфrnsten"
+
+#: common/util.cpp:284
+msgctxt "lowres"
+msgid "Hercules Green"
+msgstr "Herkules grіn"
+
+#: common/util.cpp:285
+msgctxt "lowres"
+msgid "Hercules Amber"
+msgstr "Herkules bфrnsten"
+
+#: engines/dialogs.cpp:87
+msgid "~R~esume"
+msgstr "~F~ortsфtt"
+
+#: engines/dialogs.cpp:89
+msgid "~L~oad"
+msgstr "~L~adda"
+
+#: engines/dialogs.cpp:93
+msgid "~S~ave"
+msgstr "~S~para"
+
+#: engines/dialogs.cpp:97
+msgid "~O~ptions"
+msgstr "~I~nstфllningar"
+
+#: engines/dialogs.cpp:102
+msgid "~H~elp"
+msgstr "~H~jфlp"
+
+#: engines/dialogs.cpp:104
+msgid "~A~bout"
+msgstr "O~m~..."
+
+#: engines/dialogs.cpp:107 engines/dialogs.cpp:185
+msgid "~R~eturn to Launcher"
+msgstr "Хte~r~vфnd till launcher"
+
+#: engines/dialogs.cpp:109 engines/dialogs.cpp:187
+msgctxt "lowres"
+msgid "~R~eturn to Launcher"
+msgstr "Хte~r~vфnd till launcher"
+
+#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
+#: engines/sci/engine/kfile.cpp:577
+msgid "Save game:"
+msgstr "Spara spelet:"
+
+#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
+#: engines/sci/engine/kfile.cpp:577
+#: backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:46
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
+msgid "Save"
+msgstr "Spara"
+
+#: engines/dialogs.cpp:315 engines/mohawk/dialogs.cpp:84
+#: engines/mohawk/dialogs.cpp:118
+msgid "~O~K"
+msgstr "~O~K"
+
+#: engines/dialogs.cpp:316 engines/mohawk/dialogs.cpp:85
+#: engines/mohawk/dialogs.cpp:119
+msgid "~C~ancel"
+msgstr "A~v~bryt"
+
+#: engines/dialogs.cpp:319
+msgid "~K~eys"
+msgstr "~T~angenter"
+
+#: engines/scumm/dialogs.cpp:284
+msgid "~P~revious"
+msgstr "~F~іregхende"
+
+#: engines/scumm/dialogs.cpp:285
+msgid "~N~ext"
+msgstr "~N~фsta"
+
+#: engines/scumm/dialogs.cpp:286
+#: backends/platform/ds/arm9/source/dsoptions.cpp:59
+msgid "~C~lose"
+msgstr "~S~tфng"
+
+#: engines/scumm/help.cpp:76
+msgid "Common keyboard commands:"
+msgstr "Vanliga kortkommandon:"
+
+#: engines/scumm/help.cpp:77
+msgid "Save / Load dialog"
+msgstr "Spara / Ladda-fіnster"
+
+#: engines/scumm/help.cpp:79
+msgid "Skip line of text"
+msgstr "Skippa textrad"
+
+#: engines/scumm/help.cpp:80
+msgid "Esc"
+msgstr "Esc"
+
+#: engines/scumm/help.cpp:80
+msgid "Skip cutscene"
+msgstr "Skippa scen"
+
+#: engines/scumm/help.cpp:81
+msgid "Space"
+msgstr "Mellanslag"
+
+#: engines/scumm/help.cpp:81
+msgid "Pause game"
+msgstr "Pausa spelet"
+
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
+
+#: engines/scumm/help.cpp:82
+msgid "Load game state 1-10"
+msgstr "Ladda spardata 1-10"
+
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
+
+#: engines/scumm/help.cpp:83
+msgid "Save game state 1-10"
+msgstr "Spara speldata 1-10"
+
+#: engines/scumm/help.cpp:85 engines/scumm/help.cpp:87
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+#: backends/platform/wince/CEActionsPocket.cpp:47
+#: backends/platform/wince/CEActionsSmartphone.cpp:55
+msgid "Quit"
+msgstr "Avsluta"
+
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
+
+#: engines/scumm/help.cpp:89
+msgid "Toggle fullscreen"
+msgstr "Fullskфrmslфge"
+
+#: engines/scumm/help.cpp:90
+msgid "Music volume up / down"
+msgstr "Musikvolym hіj / sфnk"
+
+#: engines/scumm/help.cpp:91
+msgid "Text speed slower / faster"
+msgstr "Texthastighet sфnk / іka"
+
+#: engines/scumm/help.cpp:92
+msgid "Simulate left mouse button"
+msgstr "Simulera vфnster musknapp"
+
+#: engines/scumm/help.cpp:93
+msgid "Tab"
+msgstr "Tab"
+
+#: engines/scumm/help.cpp:93
+msgid "Simulate right mouse button"
+msgstr "Simulera hіger musknapp"
+
+#: engines/scumm/help.cpp:96
+msgid "Special keyboard commands:"
+msgstr "Specialkortkommandon:"
+
+#: engines/scumm/help.cpp:97
+msgid "Show / Hide console"
+msgstr "Visa / gіm konsol"
+
+#: engines/scumm/help.cpp:98
+msgid "Start the debugger"
+msgstr "жppna debug-konsolen"
+
+#: engines/scumm/help.cpp:99
+msgid "Show memory consumption"
+msgstr "Visa minnesfіrbrukning"
+
+#: engines/scumm/help.cpp:100
+msgid "Run in fast mode (*)"
+msgstr "Kіr i snabblфge (*)"
+
+#: engines/scumm/help.cpp:101
+msgid "Run in really fast mode (*)"
+msgstr "Kіr i extra snabbt lфge (*)"
+
+#: engines/scumm/help.cpp:102
+msgid "Toggle mouse capture"
+msgstr "Musrestriktion av/pх"
+
+#: engines/scumm/help.cpp:103
+msgid "Switch between graphics filters"
+msgstr "Vфxla grafikfilter"
+
+#: engines/scumm/help.cpp:104
+msgid "Increase / Decrease scale factor"
+msgstr "жka / sфnk skalningsfaktor"
+
+#: engines/scumm/help.cpp:105
+msgid "Toggle aspect-ratio correction"
+msgstr "Korrektion av bildfіrhхllande pх/av"
+
+#: engines/scumm/help.cpp:110
+msgid "* Note that using ctrl-f and"
+msgstr "* Observera att anvфndning av ctrl-f"
+
+#: engines/scumm/help.cpp:111
+msgid " ctrl-g are not recommended"
+msgstr "och ctrl-g inte rekommenderas"
+
+#: engines/scumm/help.cpp:112
+msgid " since they may cause crashes"
+msgstr "dх detta kan orsaka krascher"
+
+#: engines/scumm/help.cpp:113
+msgid " or incorrect game behaviour."
+msgstr "eller felaktigt spelbeteende."
+
+#: engines/scumm/help.cpp:117
+msgid "Spinning drafts on the keyboard:"
+msgstr "Vфva melodier med tangentbordet:"
+
+#: engines/scumm/help.cpp:119
+msgid "Main game controls:"
+msgstr "Huvudkontroller:"
+
+#: engines/scumm/help.cpp:124 engines/scumm/help.cpp:139
+#: engines/scumm/help.cpp:164
+msgid "Push"
+msgstr "Tryck"
+
+#: engines/scumm/help.cpp:125 engines/scumm/help.cpp:140
+#: engines/scumm/help.cpp:165
+msgid "Pull"
+msgstr "Dra"
+
+#: engines/scumm/help.cpp:126 engines/scumm/help.cpp:141
+#: engines/scumm/help.cpp:166 engines/scumm/help.cpp:199
+#: engines/scumm/help.cpp:209
+msgid "Give"
+msgstr "Ge"
+
+#: engines/scumm/help.cpp:127 engines/scumm/help.cpp:142
+#: engines/scumm/help.cpp:167 engines/scumm/help.cpp:192
+#: engines/scumm/help.cpp:210
+msgid "Open"
+msgstr "жppna"
+
+#: engines/scumm/help.cpp:129
+msgid "Go to"
+msgstr "Gх till"
+
+#: engines/scumm/help.cpp:130
+msgid "Get"
+msgstr "Ta emot"
+
+#: engines/scumm/help.cpp:131 engines/scumm/help.cpp:155
+#: engines/scumm/help.cpp:173 engines/scumm/help.cpp:200
+#: engines/scumm/help.cpp:215 engines/scumm/help.cpp:226
+#: engines/scumm/help.cpp:251
+msgid "Use"
+msgstr "Anvфnd"
+
+#: engines/scumm/help.cpp:132 engines/scumm/help.cpp:144
+msgid "Read"
+msgstr "Lфs"
+
+#: engines/scumm/help.cpp:133 engines/scumm/help.cpp:150
+msgid "New kid"
+msgstr "Ny unge"
+
+#: engines/scumm/help.cpp:134 engines/scumm/help.cpp:156
+#: engines/scumm/help.cpp:174
+msgid "Turn on"
+msgstr "Sфtt pх"
+
+#: engines/scumm/help.cpp:135 engines/scumm/help.cpp:157
+#: engines/scumm/help.cpp:175
+msgid "Turn off"
+msgstr "Stфng av"
+
+#: engines/scumm/help.cpp:145 engines/scumm/help.cpp:170
+#: engines/scumm/help.cpp:196
+msgid "Walk to"
+msgstr "Gх till"
+
+#: engines/scumm/help.cpp:146 engines/scumm/help.cpp:171
+#: engines/scumm/help.cpp:197 engines/scumm/help.cpp:212
+#: engines/scumm/help.cpp:229
+msgid "Pick up"
+msgstr "Ta"
+
+#: engines/scumm/help.cpp:147 engines/scumm/help.cpp:172
+msgid "What is"
+msgstr "Vad фr"
+
+#: engines/scumm/help.cpp:149
+msgid "Unlock"
+msgstr "Lхs upp"
+
+#: engines/scumm/help.cpp:152
+msgid "Put on"
+msgstr "Ta pх"
+
+#: engines/scumm/help.cpp:153
+msgid "Take off"
+msgstr "Ta av"
+
+#: engines/scumm/help.cpp:159
+msgid "Fix"
+msgstr "Laga"
+
+#: engines/scumm/help.cpp:161
+msgid "Switch"
+msgstr "Byt"
+
+#: engines/scumm/help.cpp:169 engines/scumm/help.cpp:230
+msgid "Look"
+msgstr "Titta"
+
+#: engines/scumm/help.cpp:176 engines/scumm/help.cpp:225
+msgid "Talk"
+msgstr "Tala"
+
+#: engines/scumm/help.cpp:177
+msgid "Travel"
+msgstr "Res"
+
+#: engines/scumm/help.cpp:178
+msgid "To Henry / To Indy"
+msgstr "Till Henry / Till Indy"
+
+#: engines/scumm/help.cpp:181
+msgid "play C minor on distaff"
+msgstr "spela C-moll pх staven"
+
+#: engines/scumm/help.cpp:182
+msgid "play D on distaff"
+msgstr "spela D pх staven"
+
+#: engines/scumm/help.cpp:183
+msgid "play E on distaff"
+msgstr "spela E pх staven"
+
+#: engines/scumm/help.cpp:184
+msgid "play F on distaff"
+msgstr "spela F pх staven"
+
+#: engines/scumm/help.cpp:185
+msgid "play G on distaff"
+msgstr "spela G pх staven"
+
+#: engines/scumm/help.cpp:186
+msgid "play A on distaff"
+msgstr "spela A pх staven"
+
+#: engines/scumm/help.cpp:187
+msgid "play B on distaff"
+msgstr "spela H pх staven"
+
+#: engines/scumm/help.cpp:188
+msgid "play C major on distaff"
+msgstr "spela C-dur pх staven"
+
+#: engines/scumm/help.cpp:194 engines/scumm/help.cpp:216
+msgid "puSh"
+msgstr "Tryck"
+
+#: engines/scumm/help.cpp:195 engines/scumm/help.cpp:217
+msgid "pull (Yank)"
+msgstr "Dra"
+
+#: engines/scumm/help.cpp:198 engines/scumm/help.cpp:214
+#: engines/scumm/help.cpp:249
+msgid "Talk to"
+msgstr "Tala med"
+
+#: engines/scumm/help.cpp:201 engines/scumm/help.cpp:213
+msgid "Look at"
+msgstr "Titta pх"
+
+#: engines/scumm/help.cpp:202
+msgid "turn oN"
+msgstr "Sфtt pх"
+
+#: engines/scumm/help.cpp:203
+msgid "turn oFf"
+msgstr "Stфng av"
+
+#: engines/scumm/help.cpp:219
+msgid "KeyUp"
+msgstr "Piltangent upp"
+
+#: engines/scumm/help.cpp:219
+msgid "Highlight prev dialogue"
+msgstr "Markera fіreg. dialog"
+
+#: engines/scumm/help.cpp:220
+msgid "KeyDown"
+msgstr "Piltangent ned"
+
+#: engines/scumm/help.cpp:220
+msgid "Highlight next dialogue"
+msgstr "Markera nфsta dialog"
+
+#: engines/scumm/help.cpp:224
+msgid "Walk"
+msgstr "Gх"
+
+#: engines/scumm/help.cpp:227 engines/scumm/help.cpp:236
+#: engines/scumm/help.cpp:243 engines/scumm/help.cpp:250
+msgid "Inventory"
+msgstr "Inventarie"
+
+#: engines/scumm/help.cpp:228
+msgid "Object"
+msgstr "Objekt"
+
+#: engines/scumm/help.cpp:231
+msgid "Black and White / Color"
+msgstr "Svartvitt / Fфrg"
+
+#: engines/scumm/help.cpp:234
+msgid "Eyes"
+msgstr "жgon"
+
+#: engines/scumm/help.cpp:235
+msgid "Tongue"
+msgstr "Tunga"
+
+#: engines/scumm/help.cpp:237
+msgid "Punch"
+msgstr "Slх"
+
+#: engines/scumm/help.cpp:238
+msgid "Kick"
+msgstr "Sparka"
+
+#: engines/scumm/help.cpp:241 engines/scumm/help.cpp:248
+msgid "Examine"
+msgstr "Undersіk"
+
+#: engines/scumm/help.cpp:242
+msgid "Regular cursor"
+msgstr "Vanlig pekare"
+
+#: engines/scumm/help.cpp:244
+msgid "Comm"
+msgstr "Comm"
+
+#: engines/scumm/help.cpp:247
+msgid "Save / Load / Options"
+msgstr "Spara / Ladda / Inst."
+
+#: engines/scumm/help.cpp:256
+msgid "Other game controls:"
+msgstr "жvriga spelkontroller:"
+
+#: engines/scumm/help.cpp:258 engines/scumm/help.cpp:268
+msgid "Inventory:"
+msgstr "Inventarie:"
+
+#: engines/scumm/help.cpp:259 engines/scumm/help.cpp:275
+msgid "Scroll list up"
+msgstr "Blфddra listan uppхt"
+
+#: engines/scumm/help.cpp:260 engines/scumm/help.cpp:276
+msgid "Scroll list down"
+msgstr "Blфddra listan nedхt"
+
+#: engines/scumm/help.cpp:261 engines/scumm/help.cpp:269
+msgid "Upper left item"
+msgstr "жvre vфnstra fіremхlet"
+
+#: engines/scumm/help.cpp:262 engines/scumm/help.cpp:271
+msgid "Lower left item"
+msgstr "Nedre vфnstra fіremхlet"
+
+#: engines/scumm/help.cpp:263 engines/scumm/help.cpp:272
+msgid "Upper right item"
+msgstr "жvre hіgra fіremхlet"
+
+#: engines/scumm/help.cpp:264 engines/scumm/help.cpp:274
+msgid "Lower right item"
+msgstr "Nedre hіgra fіremхlet"
+
+#: engines/scumm/help.cpp:270
+msgid "Middle left item"
+msgstr "Mellersta vфnstra fіremхlet"
+
+#: engines/scumm/help.cpp:273
+msgid "Middle right item"
+msgstr "Mellersta hіgra fіremхlet"
+
+#: engines/scumm/help.cpp:280 engines/scumm/help.cpp:285
+msgid "Switching characters:"
+msgstr "Byta karaktфrer:"
+
+#: engines/scumm/help.cpp:282
+msgid "Second kid"
+msgstr "Andra ungen"
+
+#: engines/scumm/help.cpp:283
+msgid "Third kid"
+msgstr "Tredje ungen"
+
+#: engines/scumm/help.cpp:295
+msgid "Fighting controls (numpad):"
+msgstr "Slagsmхlskontroller (nr. tangenter)"
+
+#: engines/scumm/help.cpp:296 engines/scumm/help.cpp:297
+#: engines/scumm/help.cpp:298
+msgid "Step back"
+msgstr "Steg bakхt"
+
+#: engines/scumm/help.cpp:299
+msgid "Block high"
+msgstr "Blockera hіgt"
+
+#: engines/scumm/help.cpp:300
+msgid "Block middle"
+msgstr "Blockera midjehіjd"
+
+#: engines/scumm/help.cpp:301
+msgid "Block low"
+msgstr "Blockera lхgt"
+
+#: engines/scumm/help.cpp:302
+msgid "Punch high"
+msgstr "Slх hіgt"
+
+#: engines/scumm/help.cpp:303
+msgid "Punch middle"
+msgstr "Slх midjehіjd"
+
+#: engines/scumm/help.cpp:304
+msgid "Punch low"
+msgstr "Slх lхgt"
+
+#: engines/scumm/help.cpp:307
+msgid "These are for Indy on left."
+msgstr "Gфller nфr Indy stхr till vфnster."
+
+#: engines/scumm/help.cpp:308
+msgid "When Indy is on the right,"
+msgstr "Nфr Indy stхr till hіger byter"
+
+#: engines/scumm/help.cpp:309
+msgid "7, 4, and 1 are switched with"
+msgstr "7, 4 och 1 plats med"
+
+#: engines/scumm/help.cpp:310
+msgid "9, 6, and 3, respectively."
+msgstr "9, 6 och 3."
+
+#: engines/scumm/help.cpp:317
+msgid "Biplane controls (numpad):"
+msgstr "Biplanskontroller (nr. tangenter)"
+
+#: engines/scumm/help.cpp:318
+msgid "Fly to upper left"
+msgstr "Flyg хt іvre vфnster"
+
+#: engines/scumm/help.cpp:319
+msgid "Fly to left"
+msgstr "Flyg хt vфnster"
+
+#: engines/scumm/help.cpp:320
+msgid "Fly to lower left"
+msgstr "Flyg хt nedre vфnster"
+
+#: engines/scumm/help.cpp:321
+msgid "Fly upwards"
+msgstr "Flyg uppхt"
+
+#: engines/scumm/help.cpp:322
+msgid "Fly straight"
+msgstr "Flyg rakt fram"
+
+#: engines/scumm/help.cpp:323
+msgid "Fly down"
+msgstr "Flyg nedхt"
+
+#: engines/scumm/help.cpp:324
+msgid "Fly to upper right"
+msgstr "Flyg хt іvre hіger"
+
+#: engines/scumm/help.cpp:325
+msgid "Fly to right"
+msgstr "Flyg хt hіger"
+
+#: engines/scumm/help.cpp:326
+msgid "Fly to lower right"
+msgstr "Flyg хt nedre hіger"
+
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
+#, c-format
+msgid ""
+"Failed to save game state to file:\n"
+"\n"
+"%s"
+msgstr ""
+"Kunde inte skriva spardata till file:\n"
+"\n"
+"%s"
+
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
+#, c-format
+msgid ""
+"Failed to load game state from file:\n"
+"\n"
+"%s"
+msgstr ""
+"Kunde inte lфsa spardata frхn file:\n"
+"\n"
+"%s"
+
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
+#, c-format
+msgid ""
+"Successfully saved game state in file:\n"
+"\n"
+"%s"
+msgstr ""
+"Sparade framgхngsrikt spardata i file\n"
+"\n"
+"%s"
+
+#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115
+msgid "~Z~ip Mode Activated"
+msgstr "~Z~iplфge aktiverat"
+
+#: engines/mohawk/dialogs.cpp:82
+msgid "~T~ransitions Enabled"
+msgstr "жv~e~rgхngar aktiverade"
+
+#: engines/mohawk/dialogs.cpp:116
+msgid "~W~ater Effect Enabled"
+msgstr "~V~atteneffekt aktiverad"
+
+#: engines/sci/engine/kfile.cpp:680
+msgid "Restore game:"
+msgstr "Хterstфll spel:"
+
+#: engines/sci/engine/kfile.cpp:680
+msgid "Restore"
+msgstr "Хterstфll"
+
+#: audio/fmopl.cpp:51
+msgid "MAME OPL emulator"
+msgstr "MAME OPL-emulator"
+
+#: audio/fmopl.cpp:53
+msgid "DOSBox OPL emulator"
+msgstr "DOSBox OPL-emulator"
+
+#: audio/null.h:45
+msgid "No music"
+msgstr "Ingen musik"
+
+#: audio/mods/paula.cpp:192
+msgid "Amiga Audio Emulator"
+msgstr "Amiga ljudemulator"
+
+#: audio/softsynth/adlib.cpp:1590
+msgid "AdLib Emulator"
+msgstr "AdLib-emulator"
+
+#: audio/softsynth/appleiigs.cpp:36
+msgid "Apple II GS Emulator (NOT IMPLEMENTED)"
+msgstr "Apple II GS-emulator (INTE IMPLEMENTERAD)"
+
+#: audio/softsynth/sid.cpp:1434
+msgid "C64 Audio Emulator"
+msgstr "C64 ljudemulator"
+
+#: audio/softsynth/mt32.cpp:327
+msgid "Initialising MT-32 Emulator"
+msgstr "Initialiserar MT-32 emulator"
+
+#: audio/softsynth/mt32.cpp:541
+msgid "MT-32 Emulator"
+msgstr "MT-32 emulator"
+
+#: audio/softsynth/pcspk.cpp:142
+msgid "PC Speaker Emulator"
+msgstr "PC Speaker-emulator"
+
+#: audio/softsynth/pcspk.cpp:161
+msgid "IBM PCjr Emulator"
+msgstr "IBM PCjr-emulator"
+
+#: audio/softsynth/ym2612.cpp:762
+msgid "FM Towns Emulator"
+msgstr "FM Towns-emulator"
+
+#: backends/keymapper/remap-dialog.cpp:49
+msgid "Keymap:"
+msgstr "Tangenter:"
+
+#: backends/keymapper/remap-dialog.cpp:66
+msgid " (Active)"
+msgstr "(Aktiv)"
+
+#: backends/keymapper/remap-dialog.cpp:100
+msgid " (Global)"
+msgstr "(Global)"
+
+#: backends/keymapper/remap-dialog.cpp:110
+msgid " (Game)"
+msgstr "(Spel)"
+
+#: backends/midi/windows.cpp:162
+msgid "Windows MIDI"
+msgstr "Windows MIDI"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:60
+msgid "ScummVM Main Menu"
+msgstr "ScummVM huvudmeny"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "~L~eft handed mode"
+msgstr "~V~фnsterhфnt lфge"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:67
+msgid "~I~ndy fight controls"
+msgstr "~I~ndy slagsmхlskontroller"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Show mouse cursor"
+msgstr "Visa muspekare"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:69
+msgid "Snap to edges"
+msgstr "Lфgg till kant"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:71
+msgid "Touch X Offset"
+msgstr "Gх till X-position"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:78
+msgid "Touch Y Offset"
+msgstr "Gх till Y-position"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Anvфnd bфrbar trackpad-stil fіr pekarkontroll"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:91
+msgid "Tap for left click, double tap right click"
+msgstr "Tappa fіr vфnsterklick, dubbel-tappa fіr hіgerklick"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:93
+msgid "Sensitivity"
+msgstr "Kфnslighet"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:102
+msgid "Initial top screen scale:"
+msgstr "Standardskala fіr іvre skфrm:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Main screen scaling:"
+msgstr "Skalning huvudskфrm:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:110
+msgid "Hardware scale (fast, but low quality)"
+msgstr "Hхrdvaruskalning (snabbt, men lхg kvalitet)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Software scale (good quality, but slower)"
+msgstr "Mjukvaruskalning (bra kvalitet, men lхngsamt)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:112
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Oskalat (du mхste blфddra till vфnster och hіger)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:114
+msgid "Brightness:"
+msgstr "Ljusstyrka:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:124
+msgid "High quality audio (slower) (reboot)"
+msgstr "Hіg ljudkvalitet (lхngsammare) (omstart)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:125
+msgid "Disable power off"
+msgstr "Inaktivera strіmsparning"
+
+#: backends/platform/iphone/osys_events.cpp:360
+msgid "Touchpad mode enabled."
+msgstr "Touchpad-lфge aktiverat."
+
+#: backends/platform/iphone/osys_events.cpp:362
+msgid "Touchpad mode disabled."
+msgstr "Touchpad-lфge inaktiverat."
+
+#: backends/graphics/sdl/sdl-graphics.cpp:47
+msgid "Normal (no scaling)"
+msgstr "Normalt (ingen skalning)"
+
+#: backends/graphics/sdl/sdl-graphics.cpp:66
+msgctxt "lowres"
+msgid "Normal (no scaling)"
+msgstr "Normalt (ingen skalning)"
+
+#: backends/graphics/opengl/opengl-graphics.cpp:133
+msgid "OpenGL Normal"
+msgstr "OpenGL normal"
+
+#: backends/graphics/opengl/opengl-graphics.cpp:134
+msgid "OpenGL Conserve"
+msgstr "OpenGL konservation"
+
+#: backends/graphics/opengl/opengl-graphics.cpp:135
+msgid "OpenGL Original"
+msgstr "OpenGL original"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Up"
+msgstr "Upp"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Down"
+msgstr "Ned"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+msgid "Left"
+msgstr "Vфnster"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+msgid "Right"
+msgstr "Hіger"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:63
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Left Click"
+msgstr "Vфnsterklick"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Right Click"
+msgstr "Hіgerklick"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Zone"
+msgstr "Zon"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:57
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Multi Function"
+msgstr "Multifunktion"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Swap character"
+msgstr "Byt karaktфr"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+msgid "Skip text"
+msgstr "Skippa text"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Fast mode"
+msgstr "Snabblфge"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Debugger"
+msgstr "Debug-konsol"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:57
+msgid "Global menu"
+msgstr "Global meny"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:58
+msgid "Virtual keyboard"
+msgstr "Virtuellt tangentbord"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:59
+msgid "Key mapper"
+msgstr "Tangentinst."
+
+#: backends/events/symbiansdl/symbiansdl-events.cpp:187
+msgid "Do you want to quit ?"
+msgstr "Vill du avsluta?"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Video"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Aktivt videolфge:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "Ej sammanflфtad"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "Vхgrфt underskanning:"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "Lodrфt underskanning:"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Ingхng"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "GC Pad kфnslighet:"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "GC Pad acceleration:"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Status:"
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Okфnd"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "Montera DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "Mata ut DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Server:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "Delad:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Anv. namn:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Lіsenord:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Init. nфtverk"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "Montera SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "Mata ut SMB"
+
+#: backends/platform/wii/options.cpp:143
+msgid "DVD Mounted successfully"
+msgstr "Montering av DVD lyckades"
+
+#: backends/platform/wii/options.cpp:146
+msgid "Error while mounting the DVD"
+msgstr "Fel vid montering av DVD"
+
+#: backends/platform/wii/options.cpp:148
+msgid "DVD not mounted"
+msgstr "DVD ej monterad"
+
+#: backends/platform/wii/options.cpp:161
+msgid "Network up, share mounted"
+msgstr "Nфtverk aktivt, delade kataloger monterade"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up"
+msgstr "Nфtverk aktivt"
+
+#: backends/platform/wii/options.cpp:166
+msgid ", error while mounting the share"
+msgstr ", fel under montering av delade kataloger"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", share not mounted"
+msgstr ", delade kataloger ej monterade"
+
+#: backends/platform/wii/options.cpp:174
+msgid "Network down"
+msgstr "Nфtverk inaktivt"
+
+#: backends/platform/wii/options.cpp:178
+msgid "Initialising network"
+msgstr "Initialiserar nфtverk"
+
+#: backends/platform/wii/options.cpp:182
+msgid "Timeout while initialising network"
+msgstr "Timeout under initialisering av nфtverk"
+
+#: backends/platform/wii/options.cpp:186
+#, c-format
+msgid "Network not initialised (%d)"
+msgstr "Nфtverk ej initialiserat (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Hide Toolbar"
+msgstr "Gіm verktygsrad"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Show Keyboard"
+msgstr "Visa tangentbord"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Sound on/off"
+msgstr "Ljud av/pх"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Right click"
+msgstr "Hіgerklick"
+
+#: backends/platform/wince/CEActionsPocket.cpp:53
+msgid "Show/Hide Cursor"
+msgstr "Gіm/visa pekare"
+
+#: backends/platform/wince/CEActionsPocket.cpp:54
+msgid "Free look"
+msgstr "Frititt"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+msgid "Zoom up"
+msgstr "Zooma upp"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Zoom down"
+msgstr "Zooma ned"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+#: backends/platform/wince/CEActionsSmartphone.cpp:52
+msgid "Bind Keys"
+msgstr "Fіrbind tangenter"
+
+#: backends/platform/wince/CEActionsPocket.cpp:59
+msgid "Cursor Up"
+msgstr "Pekare upp"
+
+#: backends/platform/wince/CEActionsPocket.cpp:60
+msgid "Cursor Down"
+msgstr "Pekare ned"
+
+#: backends/platform/wince/CEActionsPocket.cpp:61
+msgid "Cursor Left"
+msgstr "Pekare vфnster"
+
+#: backends/platform/wince/CEActionsPocket.cpp:62
+msgid "Cursor Right"
+msgstr "Pekare hіger"
+
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
+msgid "Do you want to load or save the game?"
+msgstr "Vill du ladda eller spara spelet?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
+msgid " Are you sure you want to quit ? "
+msgstr "Фr du sфker pх att du vill avsluta?"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:53
+msgid "Keyboard"
+msgstr "Tangentbord"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:54
+msgid "Rotate"
+msgstr "Rotera"
+
+#: backends/platform/wince/CELauncherDialog.cpp:60
+msgid "Using SDL driver "
+msgstr "Anvфnd SDL-driver"
+
+#: backends/platform/wince/CELauncherDialog.cpp:64
+msgid "Display "
+msgstr "Skфrm"
+
+#: backends/platform/wince/CELauncherDialog.cpp:106
+msgid "Do you want to perform an automatic scan ?"
+msgstr "Vill du utfіra en automatisk scan?"
+
+#: backends/platform/wince/wince-sdl.cpp:486
+msgid "Map right click action"
+msgstr "Stфll in hіgerklick"
+
+#: backends/platform/wince/wince-sdl.cpp:490
+msgid "You must map a key to the 'Right Click' action to play this game"
+msgstr ""
+"Du mхste vфlja en tangent fіr \"Hіgerklick\" fіr att spela det hфr spelet"
+
+#: backends/platform/wince/wince-sdl.cpp:499
+msgid "Map hide toolbar action"
+msgstr "Stфll in gіm verktygsrad"
+
+#: backends/platform/wince/wince-sdl.cpp:503
+msgid "You must map a key to the 'Hide toolbar' action to play this game"
+msgstr ""
+"Du mхste vфlja en tangent fіr \"Gіm verktygsrad\" fіr att spela det hфr "
+"spelet"
+
+#: backends/platform/wince/wince-sdl.cpp:512
+msgid "Map Zoom Up action (optional)"
+msgstr "Stфll in Zooma up (valfritt)"
+
+#: backends/platform/wince/wince-sdl.cpp:515
+msgid "Map Zoom Down action (optional)"
+msgstr "Stфll in Zooma ned (valfritt)"
+
+#: backends/platform/wince/wince-sdl.cpp:523
+msgid ""
+"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
+msgstr ""
+"Glіm inte att vфlja en tangent fіr \"Gіm verktygsrad\" fіr att se hela "
+"inventariet"
+
diff --git a/po/uk_UA.po b/po/uk_UA.po
index 50e7871355..b901aed055 100644
--- a/po/uk_UA.po
+++ b/po/uk_UA.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2011-01-19 22:30+0000\n"
-"PO-Revision-Date: 2010-09-21 18:46+0200\n"
+"POT-Creation-Date: 2011-03-22 21:55+0000\n"
+"PO-Revision-Date: 2011-03-26 22:38+0200\n"
"Last-Translator: Lubomyr Lisen\n"
"Language-Team: Ukrainian\n"
"MIME-Version: 1.0\n"
@@ -66,11 +66,11 @@ msgstr "Закрити"
msgid "Mouse click"
msgstr "Клік мишкою"
-#: gui/gui-manager.cpp:112 base/main.cpp:287
+#: gui/gui-manager.cpp:112 base/main.cpp:286
msgid "Display keyboard"
msgstr "Показати клавіатуру"
-#: gui/gui-manager.cpp:115 base/main.cpp:290
+#: gui/gui-manager.cpp:115 base/main.cpp:289
msgid "Remap keys"
msgstr "Перепризначити клавіші"
@@ -213,7 +213,7 @@ msgstr "Гучність"
#: gui/launcher.cpp:243 gui/options.cpp:986
msgctxt "lowres"
msgid "Volume"
-msgstr "Гучність"
+msgstr "Гучн-ть"
#: gui/launcher.cpp:246
msgid "Override global volume settings"
@@ -420,15 +420,15 @@ msgstr "Пошук:"
msgid "Clear value"
msgstr "Очистити значення"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
msgid "Load game:"
msgstr "Завантажити гру:"
-#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:258
-#: engines/mohawk/riven.cpp:669 engines/cruise/menu.cpp:218
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: gui/launcher.cpp:622 engines/dialogs.cpp:117 engines/mohawk/myst.cpp:255
+#: engines/mohawk/riven.cpp:711 engines/cruise/menu.cpp:218
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Load"
msgstr "Завантажити"
@@ -442,16 +442,16 @@ msgstr ""
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "Yes"
msgstr "Так"
#: gui/launcher.cpp:732 gui/launcher.cpp:881
#: backends/events/symbiansdl/symbiansdl-events.cpp:187
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
#: backends/platform/wince/CELauncherDialog.cpp:106
msgid "No"
msgstr "Ні"
@@ -593,11 +593,11 @@ msgstr "Коригувати співвідношення сторін для ігор з графікою 320x200"
#: gui/options.cpp:668
msgid "EGA undithering"
-msgstr ""
+msgstr "EGA без згладжування"
#: gui/options.cpp:668
msgid "Enable undithering in EGA games that support it"
-msgstr ""
+msgstr "Вімкнути без згладжування в EGA іграх які підтримують це."
#: gui/options.cpp:676
msgid "Preferred Device:"
@@ -618,7 +618,7 @@ msgstr "Вказує вихідний звуковий пристрій або емулятор звукової карти"
#: gui/options.cpp:678
msgctxt "lowres"
msgid "Preferred Dev.:"
-msgstr "Пристрій якому віддається перевага:"
+msgstr "Реком. пристрій:"
#: gui/options.cpp:678
msgctxt "lowres"
@@ -655,11 +655,11 @@ msgstr "Вказує вихідний звуковий пристрій для MIDI"
#: gui/options.cpp:737
msgid "Don't use General MIDI music"
-msgstr ""
+msgstr "не використовувати General MIDI музику"
#: gui/options.cpp:748 gui/options.cpp:809
msgid "Use first available device"
-msgstr ""
+msgstr "Використовувати перший наявний пристрій"
#: gui/options.cpp:760
msgid "SoundFont:"
@@ -724,9 +724,8 @@ msgstr ""
"Вимикає маппінг General MIDI для ігор із звуковою доріжкою для Roland MT-32"
#: gui/options.cpp:799
-#, fuzzy
msgid "Don't use Roland MT-32 music"
-msgstr "Справжній Roland MT-32 (вимкнути емуляцию GM)"
+msgstr "Не використовувати Roland MT-32"
#: gui/options.cpp:826
msgid "Text and Speech:"
@@ -773,7 +772,7 @@ msgstr "Показувати субтитри і відтворювати мову"
#: gui/options.cpp:844
msgctxt "lowres"
msgid "Subtitle speed:"
-msgstr "Швидкість субтитрів:"
+msgstr "Швид. субтитрів:"
#: gui/options.cpp:860
msgid "Music volume:"
@@ -799,7 +798,7 @@ msgstr "Гучність спеціальних звукових ефектів"
#: gui/options.cpp:874
msgctxt "lowres"
msgid "SFX volume:"
-msgstr "Гучність ефектів:"
+msgstr "Гучніс. ефектів:"
#: gui/options.cpp:882
msgid "Speech volume:"
@@ -808,7 +807,7 @@ msgstr "Гучність озвучки:"
#: gui/options.cpp:884
msgctxt "lowres"
msgid "Speech volume:"
-msgstr "Гучність озвучки:"
+msgstr "Гучніс. озвучки:"
#: gui/options.cpp:1023
msgid "Theme Path:"
@@ -849,7 +848,7 @@ msgstr "Тема:"
#: gui/options.cpp:1055
msgid "GUI Renderer:"
-msgstr "Растеризат. GUI:"
+msgstr "Растер. GUI:"
#: gui/options.cpp:1067
msgid "Autosave:"
@@ -858,7 +857,7 @@ msgstr "Автозбереження:"
#: gui/options.cpp:1069
msgctxt "lowres"
msgid "Autosave:"
-msgstr "Автозбереження:"
+msgstr "Автозбереж.:"
#: gui/options.cpp:1077
msgid "Keys"
@@ -866,7 +865,7 @@ msgstr "Клавіші"
#: gui/options.cpp:1084
msgid "GUI Language:"
-msgstr "Мова інтерфейсу:"
+msgstr "Мова інтерф.:"
#: gui/options.cpp:1084
msgid "Language of ScummVM GUI"
@@ -901,6 +900,8 @@ msgid ""
"The theme you selected does not support your current language. If you want "
"to use this theme you need to switch to another language first."
msgstr ""
+"Вибрану тему не підтримує поточна мова. Якщо ви хочете використовувати цю "
+"тему потрібно в першу чергу змінити мову."
#: gui/saveload.cpp:61 gui/saveload.cpp:242
msgid "No date saved"
@@ -967,35 +968,35 @@ msgstr "Растеризатор зі згладжуванням (16bpp)"
msgid "Antialiased (16bpp)"
msgstr "Растеризатор зі згладжуванням (16bpp)"
-#: base/main.cpp:207
+#: base/main.cpp:206
#, c-format
msgid "Engine does not support debug level '%s'"
msgstr "Движок не підтримує рівень відладки '%s'"
-#: base/main.cpp:275
+#: base/main.cpp:274
msgid "Menu"
msgstr "Меню"
-#: base/main.cpp:278 backends/platform/symbian/src/SymbianActions.cpp:48
+#: base/main.cpp:277 backends/platform/symbian/src/SymbianActions.cpp:48
#: backends/platform/wince/CEActionsPocket.cpp:48
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Skip"
msgstr "Пропустити"
-#: base/main.cpp:281 backends/platform/symbian/src/SymbianActions.cpp:53
+#: base/main.cpp:280 backends/platform/symbian/src/SymbianActions.cpp:53
#: backends/platform/wince/CEActionsPocket.cpp:45
msgid "Pause"
msgstr "Пауза"
-#: base/main.cpp:284
+#: base/main.cpp:283
msgid "Skip line"
msgstr "Пропустити рядок"
-#: base/main.cpp:436
+#: base/main.cpp:435
msgid "Error running game:"
msgstr "Помилка запуску гри:"
-#: base/main.cpp:460
+#: base/main.cpp:459
msgid "Could not find any engine capable of running the selected game"
msgstr "Не можу знайти движок для запуску вибраної гри"
@@ -1100,20 +1101,20 @@ msgstr "~П~овер. в головне меню"
#: engines/dialogs.cpp:109 engines/dialogs.cpp:187
msgctxt "lowres"
msgid "~R~eturn to Launcher"
-msgstr "~П~овернутись в головне меню"
+msgstr "~П~овер.в головне меню"
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
msgid "Save game:"
msgstr "Зберегти гру: "
#: engines/dialogs.cpp:119 engines/cruise/menu.cpp:216
-#: engines/sci/engine/kfile.cpp:576
+#: engines/sci/engine/kfile.cpp:577
#: backends/platform/symbian/src/SymbianActions.cpp:47
#: backends/platform/wince/CEActionsPocket.cpp:46
-#: backends/platform/wince/CEActionsPocket.cpp:266
+#: backends/platform/wince/CEActionsPocket.cpp:268
#: backends/platform/wince/CEActionsSmartphone.cpp:48
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Save"
msgstr "Записати"
@@ -1146,53 +1147,53 @@ msgstr "~З~акрити"
#: engines/scumm/help.cpp:76
msgid "Common keyboard commands:"
-msgstr ""
+msgstr "Основні команди клавіатури:"
#: engines/scumm/help.cpp:77
msgid "Save / Load dialog"
-msgstr ""
+msgstr "Зберегти / Завантажити діалог"
#: engines/scumm/help.cpp:79
-#, fuzzy
msgid "Skip line of text"
-msgstr "Пропустити рядок"
+msgstr "Пропустити рядок тексту"
#: engines/scumm/help.cpp:80
msgid "Esc"
-msgstr ""
+msgstr "Esc"
#: engines/scumm/help.cpp:80
-#, fuzzy
msgid "Skip cutscene"
-msgstr "Пропустити рядок"
+msgstr "Пропустити заставку"
#: engines/scumm/help.cpp:81
-#, fuzzy
msgid "Space"
-msgstr "Озв"
+msgstr "Space"
#: engines/scumm/help.cpp:81
-#, fuzzy
msgid "Pause game"
-msgstr "Зберегти гру: "
+msgstr "Пауза"
-#: engines/scumm/help.cpp:82
-msgid "Ctrl 0-9"
-msgstr ""
+#: engines/scumm/help.cpp:82 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Ctrl"
+msgstr "Ctrl"
#: engines/scumm/help.cpp:82
-#, fuzzy
msgid "Load game state 1-10"
-msgstr "Завантажити гру:"
+msgstr "Завантажити стан гри 1-10"
-#: engines/scumm/help.cpp:83
-msgid "Alt 0-9"
-msgstr ""
+#: engines/scumm/help.cpp:83 engines/scumm/help.cpp:87
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:103
+#: engines/scumm/help.cpp:104 engines/scumm/help.cpp:105
+msgid "Alt"
+msgstr "Alt"
#: engines/scumm/help.cpp:83
-#, fuzzy
msgid "Save game state 1-10"
-msgstr "Зберегти гру: "
+msgstr "Зберегти стан гри 1-10"
#: engines/scumm/help.cpp:85 engines/scumm/help.cpp:87
#: backends/platform/symbian/src/SymbianActions.cpp:55
@@ -1201,522 +1202,468 @@ msgstr "Зберегти гру: "
msgid "Quit"
msgstr "Вихід"
-#: engines/scumm/help.cpp:87
-msgid "Alt x, Ctrl z"
-msgstr ""
-
-#: engines/scumm/help.cpp:89
-msgid "Alt Enter"
-msgstr ""
+#: engines/scumm/help.cpp:89 engines/scumm/help.cpp:92
+msgid "Enter"
+msgstr "Enter"
#: engines/scumm/help.cpp:89
msgid "Toggle fullscreen"
-msgstr ""
+msgstr "Увімкнути повноекранний режим"
#: engines/scumm/help.cpp:90
-#, fuzzy
msgid "Music volume up / down"
-msgstr "Гучність музики:"
+msgstr "Гучність музики вверх/вниз"
#: engines/scumm/help.cpp:91
msgid "Text speed slower / faster"
-msgstr ""
-
-#: engines/scumm/help.cpp:92
-msgid "Enter"
-msgstr ""
+msgstr "Швидкість тексту повільніше / швидше"
#: engines/scumm/help.cpp:92
msgid "Simulate left mouse button"
-msgstr ""
+msgstr "Симулювати лівий клік"
#: engines/scumm/help.cpp:93
msgid "Tab"
-msgstr ""
+msgstr "Tab"
#: engines/scumm/help.cpp:93
msgid "Simulate right mouse button"
-msgstr ""
+msgstr "Симулювати правий клік"
#: engines/scumm/help.cpp:96
msgid "Special keyboard commands:"
-msgstr ""
+msgstr "Спеціальні команди клавіатури:"
#: engines/scumm/help.cpp:97
-#, fuzzy
msgid "Show / Hide console"
-msgstr "Показати/Сховати курсор"
-
-#: engines/scumm/help.cpp:98
-msgid "Ctrl d"
-msgstr ""
+msgstr "Показати / Сховати консоль"
#: engines/scumm/help.cpp:98
msgid "Start the debugger"
-msgstr ""
-
-#: engines/scumm/help.cpp:99
-msgid "Ctrl s"
-msgstr ""
+msgstr "Запуск відладчика"
#: engines/scumm/help.cpp:99
msgid "Show memory consumption"
-msgstr ""
-
-#: engines/scumm/help.cpp:100
-msgid "Ctrl f"
-msgstr ""
+msgstr "Показати споживання пам'яті"
#: engines/scumm/help.cpp:100
msgid "Run in fast mode (*)"
-msgstr ""
-
-#: engines/scumm/help.cpp:101
-msgid "Ctrl g"
-msgstr ""
+msgstr "Виконати в швидкому режимі (*)"
#: engines/scumm/help.cpp:101
msgid "Run in really fast mode (*)"
-msgstr ""
-
-#: engines/scumm/help.cpp:102
-msgid "Ctrl m"
-msgstr ""
+msgstr "Виконати в дійсно швидкому режимі (*)"
#: engines/scumm/help.cpp:102
msgid "Toggle mouse capture"
-msgstr ""
-
-#: engines/scumm/help.cpp:103
-msgid "Ctrl Alt 1-8"
-msgstr ""
+msgstr "Увімкнути захоплення миші"
#: engines/scumm/help.cpp:103
msgid "Switch between graphics filters"
-msgstr ""
-
-#: engines/scumm/help.cpp:104
-msgid "Ctrl Alt +, -"
-msgstr ""
+msgstr "Переключення між графічними фільтрами"
#: engines/scumm/help.cpp:104
msgid "Increase / Decrease scale factor"
-msgstr ""
+msgstr "Збільшення / зменшення масштабу"
#: engines/scumm/help.cpp:105
-msgid "Ctrl Alt a"
-msgstr ""
-
-#: engines/scumm/help.cpp:105
-#, fuzzy
msgid "Toggle aspect-ratio correction"
msgstr "Корекція співвідношення сторін"
#: engines/scumm/help.cpp:110
msgid "* Note that using ctrl-f and"
-msgstr ""
+msgstr "* Зауважимо, що використання Ctrl-F і"
#: engines/scumm/help.cpp:111
msgid " ctrl-g are not recommended"
-msgstr ""
+msgstr " ctrl-G не рекомендується"
#: engines/scumm/help.cpp:112
msgid " since they may cause crashes"
-msgstr ""
+msgstr " оскільки вони можуть викликати збої"
#: engines/scumm/help.cpp:113
msgid " or incorrect game behaviour."
-msgstr ""
+msgstr " або неправильну поведінку гри."
#: engines/scumm/help.cpp:117
msgid "Spinning drafts on the keyboard:"
-msgstr ""
+msgstr "Спінінг проекти на клавіатурі:"
#: engines/scumm/help.cpp:119
-#, fuzzy
msgid "Main game controls:"
-msgstr "Змінити опції гри"
+msgstr "Основні опції керування:"
#: engines/scumm/help.cpp:124 engines/scumm/help.cpp:139
#: engines/scumm/help.cpp:164
-#, fuzzy
msgid "Push"
-msgstr "Пауза"
+msgstr "Натиск"
#: engines/scumm/help.cpp:125 engines/scumm/help.cpp:140
#: engines/scumm/help.cpp:165
msgid "Pull"
-msgstr ""
+msgstr "Тягти"
#: engines/scumm/help.cpp:126 engines/scumm/help.cpp:141
#: engines/scumm/help.cpp:166 engines/scumm/help.cpp:199
#: engines/scumm/help.cpp:209
msgid "Give"
-msgstr ""
+msgstr "Дати"
#: engines/scumm/help.cpp:127 engines/scumm/help.cpp:142
#: engines/scumm/help.cpp:167 engines/scumm/help.cpp:192
#: engines/scumm/help.cpp:210
msgid "Open"
-msgstr ""
+msgstr "Відкрити"
#: engines/scumm/help.cpp:129
-#, fuzzy
msgid "Go to"
-msgstr "Вверх"
+msgstr "Йти до"
#: engines/scumm/help.cpp:130
msgid "Get"
-msgstr ""
+msgstr "Отримати"
#: engines/scumm/help.cpp:131 engines/scumm/help.cpp:155
#: engines/scumm/help.cpp:173 engines/scumm/help.cpp:200
#: engines/scumm/help.cpp:215 engines/scumm/help.cpp:226
#: engines/scumm/help.cpp:251
msgid "Use"
-msgstr ""
+msgstr "Використати"
#: engines/scumm/help.cpp:132 engines/scumm/help.cpp:144
msgid "Read"
-msgstr ""
+msgstr "Читати"
#: engines/scumm/help.cpp:133 engines/scumm/help.cpp:150
msgid "New kid"
-msgstr ""
+msgstr "Нова дитина"
#: engines/scumm/help.cpp:134 engines/scumm/help.cpp:156
#: engines/scumm/help.cpp:174
msgid "Turn on"
-msgstr ""
+msgstr "Увімкнути"
#: engines/scumm/help.cpp:135 engines/scumm/help.cpp:157
#: engines/scumm/help.cpp:175
-#, fuzzy
msgid "Turn off"
-msgstr "Звук увім/вимк"
+msgstr "Вимкнути"
#: engines/scumm/help.cpp:145 engines/scumm/help.cpp:170
#: engines/scumm/help.cpp:196
msgid "Walk to"
-msgstr ""
+msgstr "Іти до"
#: engines/scumm/help.cpp:146 engines/scumm/help.cpp:171
#: engines/scumm/help.cpp:197 engines/scumm/help.cpp:212
#: engines/scumm/help.cpp:229
msgid "Pick up"
-msgstr ""
+msgstr "Підібрати"
#: engines/scumm/help.cpp:147 engines/scumm/help.cpp:172
msgid "What is"
-msgstr ""
+msgstr "Що це"
#: engines/scumm/help.cpp:149
msgid "Unlock"
-msgstr ""
+msgstr "Розблокувати"
#: engines/scumm/help.cpp:152
msgid "Put on"
-msgstr ""
+msgstr "Поставити на"
#: engines/scumm/help.cpp:153
msgid "Take off"
-msgstr ""
+msgstr "Зняти"
#: engines/scumm/help.cpp:159
msgid "Fix"
-msgstr ""
+msgstr "Зафіксувати"
#: engines/scumm/help.cpp:161
-#, fuzzy
msgid "Switch"
-msgstr "Озв"
+msgstr "Перемкнути"
#: engines/scumm/help.cpp:169 engines/scumm/help.cpp:230
msgid "Look"
-msgstr ""
+msgstr "Глянути"
#: engines/scumm/help.cpp:176 engines/scumm/help.cpp:225
msgid "Talk"
-msgstr ""
+msgstr "Говорити"
#: engines/scumm/help.cpp:177
-#, fuzzy
msgid "Travel"
-msgstr "Записати"
+msgstr "Подорож"
#: engines/scumm/help.cpp:178
msgid "To Henry / To Indy"
-msgstr ""
+msgstr "До Генрі / ДО Інді"
#: engines/scumm/help.cpp:181
msgid "play C minor on distaff"
-msgstr ""
+msgstr "грати C незначний на прядці"
#: engines/scumm/help.cpp:182
msgid "play D on distaff"
-msgstr ""
+msgstr "грати D на прядці"
#: engines/scumm/help.cpp:183
msgid "play E on distaff"
-msgstr ""
+msgstr "грати E на прядці"
#: engines/scumm/help.cpp:184
msgid "play F on distaff"
-msgstr ""
+msgstr "грати F на прядці"
#: engines/scumm/help.cpp:185
msgid "play G on distaff"
-msgstr ""
+msgstr "грати G на прядці"
#: engines/scumm/help.cpp:186
msgid "play A on distaff"
-msgstr ""
+msgstr "грати A на прядці"
#: engines/scumm/help.cpp:187
msgid "play B on distaff"
-msgstr ""
+msgstr "грати B на прядці"
#: engines/scumm/help.cpp:188
msgid "play C major on distaff"
-msgstr ""
+msgstr "грати C значний yf ghzlws"
#: engines/scumm/help.cpp:194 engines/scumm/help.cpp:216
msgid "puSh"
-msgstr ""
+msgstr "Поштовх"
#: engines/scumm/help.cpp:195 engines/scumm/help.cpp:217
msgid "pull (Yank)"
-msgstr ""
+msgstr "тягнути (Смикнути)"
#: engines/scumm/help.cpp:198 engines/scumm/help.cpp:214
#: engines/scumm/help.cpp:249
msgid "Talk to"
-msgstr ""
+msgstr "Говорити до"
#: engines/scumm/help.cpp:201 engines/scumm/help.cpp:213
msgid "Look at"
-msgstr ""
+msgstr "Глянути на"
#: engines/scumm/help.cpp:202
msgid "turn oN"
-msgstr ""
+msgstr "Увімкнути"
#: engines/scumm/help.cpp:203
msgid "turn oFf"
-msgstr ""
+msgstr "Вимкнути"
#: engines/scumm/help.cpp:219
-#, fuzzy
msgid "KeyUp"
-msgstr "Клавіші"
+msgstr "Натиснути"
#: engines/scumm/help.cpp:219
msgid "Highlight prev dialogue"
-msgstr ""
+msgstr "Виділити попередній діалог"
#: engines/scumm/help.cpp:220
-#, fuzzy
msgid "KeyDown"
-msgstr "Вниз"
+msgstr "Відпустити"
#: engines/scumm/help.cpp:220
msgid "Highlight next dialogue"
-msgstr ""
+msgstr "Виділити наступний діалог"
#: engines/scumm/help.cpp:224
msgid "Walk"
-msgstr ""
+msgstr "Іти"
#: engines/scumm/help.cpp:227 engines/scumm/help.cpp:236
#: engines/scumm/help.cpp:243 engines/scumm/help.cpp:250
msgid "Inventory"
-msgstr ""
+msgstr "Інвентар"
#: engines/scumm/help.cpp:228
msgid "Object"
-msgstr ""
+msgstr "Об'єкт"
#: engines/scumm/help.cpp:231
msgid "Black and White / Color"
-msgstr ""
+msgstr "Чорний і Білий / Колір"
#: engines/scumm/help.cpp:234
msgid "Eyes"
-msgstr ""
+msgstr "Очі"
#: engines/scumm/help.cpp:235
-#, fuzzy
msgid "Tongue"
-msgstr "Зона"
+msgstr "Розмовляти"
#: engines/scumm/help.cpp:237
msgid "Punch"
-msgstr ""
+msgstr "Вдарити кулаком"
#: engines/scumm/help.cpp:238
msgid "Kick"
-msgstr ""
+msgstr "Вдарити ногою"
#: engines/scumm/help.cpp:241 engines/scumm/help.cpp:248
msgid "Examine"
-msgstr ""
+msgstr "Розглянути"
#: engines/scumm/help.cpp:242
msgid "Regular cursor"
-msgstr ""
+msgstr "Регулярний курсор"
#: engines/scumm/help.cpp:244
msgid "Comm"
-msgstr ""
+msgstr "Comm"
#: engines/scumm/help.cpp:247
msgid "Save / Load / Options"
-msgstr ""
+msgstr "Збереження / Завантаження / Опції"
#: engines/scumm/help.cpp:256
-#, fuzzy
msgid "Other game controls:"
-msgstr "Змінити опції гри"
+msgstr "Інші опції керування:"
#: engines/scumm/help.cpp:258 engines/scumm/help.cpp:268
msgid "Inventory:"
-msgstr ""
+msgstr "Інвентар:"
#: engines/scumm/help.cpp:259 engines/scumm/help.cpp:275
msgid "Scroll list up"
-msgstr ""
+msgstr "Прокручення списку вверх"
#: engines/scumm/help.cpp:260 engines/scumm/help.cpp:276
msgid "Scroll list down"
-msgstr ""
+msgstr "Прокручення списку вниз"
#: engines/scumm/help.cpp:261 engines/scumm/help.cpp:269
msgid "Upper left item"
-msgstr ""
+msgstr "Верхня зліва річ"
#: engines/scumm/help.cpp:262 engines/scumm/help.cpp:271
msgid "Lower left item"
-msgstr ""
+msgstr "Нижня зліва річ"
#: engines/scumm/help.cpp:263 engines/scumm/help.cpp:272
msgid "Upper right item"
-msgstr ""
+msgstr "Верхня справа річ"
#: engines/scumm/help.cpp:264 engines/scumm/help.cpp:274
msgid "Lower right item"
-msgstr ""
+msgstr "Нижня справа річ"
#: engines/scumm/help.cpp:270
msgid "Middle left item"
-msgstr ""
+msgstr "Середня зліва річ"
#: engines/scumm/help.cpp:273
msgid "Middle right item"
-msgstr ""
+msgstr "Середня справа річ"
#: engines/scumm/help.cpp:280 engines/scumm/help.cpp:285
-#, fuzzy
msgid "Switching characters:"
-msgstr "Змінити героя"
+msgstr "Переключення героїв"
#: engines/scumm/help.cpp:282
msgid "Second kid"
-msgstr ""
+msgstr "Друга дитина"
#: engines/scumm/help.cpp:283
msgid "Third kid"
-msgstr ""
+msgstr "Третя дитина"
#: engines/scumm/help.cpp:295
msgid "Fighting controls (numpad):"
-msgstr ""
+msgstr "Керування бійкою (numpad):"
#: engines/scumm/help.cpp:296 engines/scumm/help.cpp:297
#: engines/scumm/help.cpp:298
msgid "Step back"
-msgstr ""
+msgstr "Крок назад"
#: engines/scumm/help.cpp:299
msgid "Block high"
-msgstr ""
+msgstr "Блокувати вище"
#: engines/scumm/help.cpp:300
msgid "Block middle"
-msgstr ""
+msgstr "Блокувати посередині"
#: engines/scumm/help.cpp:301
msgid "Block low"
-msgstr ""
+msgstr "Блокувати нище"
#: engines/scumm/help.cpp:302
msgid "Punch high"
-msgstr ""
+msgstr "Бити вище"
#: engines/scumm/help.cpp:303
msgid "Punch middle"
-msgstr ""
+msgstr "Бити посередині"
#: engines/scumm/help.cpp:304
msgid "Punch low"
-msgstr ""
+msgstr "Бити нище"
#: engines/scumm/help.cpp:307
msgid "These are for Indy on left."
-msgstr ""
+msgstr "У випадку для Інді зліва."
#: engines/scumm/help.cpp:308
msgid "When Indy is on the right,"
-msgstr ""
+msgstr "Коли Інді є справа,"
#: engines/scumm/help.cpp:309
msgid "7, 4, and 1 are switched with"
-msgstr ""
+msgstr "7, 4, і 1 перемикаються з"
#: engines/scumm/help.cpp:310
msgid "9, 6, and 3, respectively."
-msgstr ""
+msgstr "9, 6 і 3 відповідно."
#: engines/scumm/help.cpp:317
msgid "Biplane controls (numpad):"
-msgstr ""
+msgstr "Керування біпланом (numpad):"
#: engines/scumm/help.cpp:318
msgid "Fly to upper left"
-msgstr ""
+msgstr "Летіти вище вліво"
#: engines/scumm/help.cpp:319
msgid "Fly to left"
-msgstr ""
+msgstr "Летіти вліво"
#: engines/scumm/help.cpp:320
msgid "Fly to lower left"
-msgstr ""
+msgstr "Летіти нижче вліво"
#: engines/scumm/help.cpp:321
msgid "Fly upwards"
-msgstr ""
+msgstr "Летіти вгору"
#: engines/scumm/help.cpp:322
msgid "Fly straight"
-msgstr ""
+msgstr "Летіти прямо"
#: engines/scumm/help.cpp:323
msgid "Fly down"
-msgstr ""
+msgstr "Летіти вниз"
#: engines/scumm/help.cpp:324
msgid "Fly to upper right"
-msgstr ""
+msgstr "Летіти вище вправо"
#: engines/scumm/help.cpp:325
msgid "Fly to right"
-msgstr ""
+msgstr "Летіти направо"
#: engines/scumm/help.cpp:326
msgid "Fly to lower right"
-msgstr ""
+msgstr "Летіти нижче вправо"
-#: engines/scumm/scumm.cpp:2260 engines/agos/saveload.cpp:192
+#: engines/scumm/scumm.cpp:2256 engines/agos/saveload.cpp:192
#, c-format
msgid ""
"Failed to save game state to file:\n"
@@ -1727,7 +1674,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2267 engines/agos/saveload.cpp:157
+#: engines/scumm/scumm.cpp:2263 engines/agos/saveload.cpp:157
#, c-format
msgid ""
"Failed to load game state from file:\n"
@@ -1738,7 +1685,7 @@ msgstr ""
"\n"
"%s"
-#: engines/scumm/scumm.cpp:2279 engines/agos/saveload.cpp:200
+#: engines/scumm/scumm.cpp:2275 engines/agos/saveload.cpp:200
#, c-format
msgid ""
"Successfully saved game state in file:\n"
@@ -1761,11 +1708,11 @@ msgstr "Переходи активовані"
msgid "~W~ater Effect Enabled"
msgstr "Ефекти води включені"
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore game:"
msgstr "Відновити гру: "
-#: engines/sci/engine/kfile.cpp:676
+#: engines/sci/engine/kfile.cpp:680
msgid "Restore"
msgstr "Відновити"
@@ -1918,8 +1865,6 @@ msgid "Touchpad mode disabled."
msgstr "Режим тачпаду вимкнений."
#: backends/graphics/sdl/sdl-graphics.cpp:47
-#: backends/platform/wince/wince-sdl.cpp:114
-#: backends/platform/wince/wince-sdl.cpp:121
msgid "Normal (no scaling)"
msgstr "Без збільшення"
@@ -1928,21 +1873,17 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Без збільшення"
-#: backends/graphics/opengl/opengl-graphics.cpp:117
+#: backends/graphics/opengl/opengl-graphics.cpp:133
msgid "OpenGL Normal"
-msgstr ""
+msgstr "OpenGL нормальний"
-#: backends/graphics/opengl/opengl-graphics.cpp:118
+#: backends/graphics/opengl/opengl-graphics.cpp:134
msgid "OpenGL Conserve"
-msgstr ""
+msgstr "OpenGL консервований"
-#: backends/graphics/opengl/opengl-graphics.cpp:119
-msgid "OpenGL 4/3"
-msgstr ""
-
-#: backends/graphics/opengl/opengl-graphics.cpp:120
+#: backends/graphics/opengl/opengl-graphics.cpp:135
msgid "OpenGL Original"
-msgstr ""
+msgstr "OpenGL оригінальний"
#: backends/platform/symbian/src/SymbianActions.cpp:41
#: backends/platform/wince/CEActionsSmartphone.cpp:42
@@ -2200,13 +2141,13 @@ msgstr "Курсор вліво"
msgid "Cursor Right"
msgstr "Курсор вправо"
-#: backends/platform/wince/CEActionsPocket.cpp:266
-#: backends/platform/wince/CEActionsSmartphone.cpp:229
+#: backends/platform/wince/CEActionsPocket.cpp:268
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
msgstr "Ви хочете завантажити або зберегти гру?"
-#: backends/platform/wince/CEActionsPocket.cpp:316
-#: backends/platform/wince/CEActionsSmartphone.cpp:276
+#: backends/platform/wince/CEActionsPocket.cpp:330
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
msgstr " Ви упевнені, що хочете вийти? "
@@ -2230,59 +2171,35 @@ msgstr "Показати "
msgid "Do you want to perform an automatic scan ?"
msgstr "Ви хочете здійснити автоматичний пошук?"
-#: backends/platform/wince/wince-sdl.cpp:981
-#, fuzzy
+#: backends/platform/wince/wince-sdl.cpp:486
msgid "Map right click action"
-msgstr "Правий клік"
+msgstr "Перепризначення правого кліку"
-#: backends/platform/wince/wince-sdl.cpp:985
+#: backends/platform/wince/wince-sdl.cpp:490
msgid "You must map a key to the 'Right Click' action to play this game"
-msgstr ""
+msgstr "Ви повинні пере"
-#: backends/platform/wince/wince-sdl.cpp:994
+#: backends/platform/wince/wince-sdl.cpp:499
msgid "Map hide toolbar action"
-msgstr ""
+msgstr "Перепризначити дію 'Сховати Панель інстр.'"
-#: backends/platform/wince/wince-sdl.cpp:998
+#: backends/platform/wince/wince-sdl.cpp:503
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
+"Ви повинні перепризначити кнопку для дії 'Сховати Панель інстр.', щоб грати "
+"в цю гру"
-#: backends/platform/wince/wince-sdl.cpp:1007
+#: backends/platform/wince/wince-sdl.cpp:512
msgid "Map Zoom Up action (optional)"
-msgstr ""
+msgstr "Перепризначити дію Збільшення (необовязково)"
-#: backends/platform/wince/wince-sdl.cpp:1010
+#: backends/platform/wince/wince-sdl.cpp:515
msgid "Map Zoom Down action (optional)"
-msgstr ""
+msgstr "Перепризначити дію Зменшення (необовязково)"
-#: backends/platform/wince/wince-sdl.cpp:1018
+#: backends/platform/wince/wince-sdl.cpp:523
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
-
-#, fuzzy
-#~ msgid "Dave"
-#~ msgstr "Записати"
-
-#~ msgctxt "lowres"
-#~ msgid "Preferred Device:"
-#~ msgstr "Пристрій якому віддається перевага:"
-
-#~ msgctxt "lowres"
-#~ msgid "True Roland MT-32 (disable GM emulation)"
-#~ msgstr "Справжній Roland MT-32 (вимкнути емуляцию GM)"
-
-#, fuzzy
-#~ msgctxt "lowres"
-#~ msgid "Standard Renderer (16bpp)"
-#~ msgstr "Стандартний растеризатор (16bpp)"
-
-#, fuzzy
-#~ msgctxt "lowres"
-#~ msgid "Antialiased Renderer (16bpp)"
-#~ msgstr "Растеризатор зі згладжуванням (16bpp)"
-
-#, fuzzy
-#~ msgctxt "lowres"
-#~ msgid "Special sound effects volume"
-#~ msgstr "Гучність спеціальних звукових ефектів"
+"Не забудьте перепризначити кнопку для дії 'Сховати Панель інстр.' щоб "
+"побачити весь інвентар"
diff --git a/ports.mk b/ports.mk
index c56031ef11..13b4e48c52 100644
--- a/ports.mk
+++ b/ports.mk
@@ -47,7 +47,7 @@ bundle: scummvm-static
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) $(bundle_name)/Contents/Resources/
endif
- $(srcdir)/tools/credits.pl --rtf > $(bundle_name)/Contents/Resources/Credits.rtf
+ $(srcdir)/devtools/credits.pl --rtf > $(bundle_name)/Contents/Resources/Credits.rtf
chmod 644 $(bundle_name)/Contents/Resources/*
cp scummvm-static $(bundle_name)/Contents/MacOS/scummvm
chmod 755 $(bundle_name)/Contents/MacOS/scummvm
@@ -138,7 +138,7 @@ iphone: $(OBJS)
# TODO: Replace AUTHORS by Credits.rtf
osxsnap: bundle
mkdir ScummVM-snapshot
- $(srcdir)/tools/credits.pl --text > $(srcdir)/AUTHORS
+ $(srcdir)/devtools/credits.pl --text > $(srcdir)/AUTHORS
cp $(srcdir)/AUTHORS ./ScummVM-snapshot/Authors
cp $(srcdir)/COPYING ./ScummVM-snapshot/License\ \(GPL\)
cp $(srcdir)/COPYING.LGPL ./ScummVM-snapshot/License\ \(LGPL\)
diff --git a/rules.mk b/rules.mk
index fde462fc0b..c531d49a29 100644
--- a/rules.mk
+++ b/rules.mk
@@ -28,12 +28,12 @@ $(TOOL-$(MODULE)): $(MODULE_OBJS-$(MODULE))
# Reset TOOL_EXECUTABLE var
TOOL_EXECUTABLE:=
-# Add to "tools" target
-tools: $(TOOL-$(MODULE))
+# Add to "devtools" target
+devtools: $(TOOL-$(MODULE))
-# Pseudo target for comfort, allows for "make tools/skycpt", etc.
+# Pseudo target for comfort, allows for "make devtools/skycpt", etc.
$(MODULE): $(TOOL-$(MODULE))
-clean-tools: clean-$(MODULE)
+clean-devtools: clean-$(MODULE)
else
ifdef PLUGIN
diff --git a/test/audio/helper.h b/test/audio/helper.h
index 262ca1c060..e0d034aaea 100644
--- a/test/audio/helper.h
+++ b/test/audio/helper.h
@@ -18,7 +18,7 @@ static T *createSine(const int sampleRate, const int time) {
const T maxValue = std::numeric_limits<T>::max() ^ xorMask;
for (int i = 0; i < time * sampleRate; ++i)
- sine[i] = ((T)(sin((double)i / sampleRate * 2 * PI) * maxValue)) ^ xorMask;
+ sine[i] = ((T)(sin((double)i / sampleRate * 2 * M_PI) * maxValue)) ^ xorMask;
return sine;
}
diff --git a/test/common/endian.h b/test/common/endian.h
new file mode 100644
index 0000000000..cba7618c43
--- /dev/null
+++ b/test/common/endian.h
@@ -0,0 +1,36 @@
+#include <cxxtest/TestSuite.h>
+#include "common/endian.h"
+
+class EndianTestSuite : public CxxTest::TestSuite
+{
+ public:
+ void test_MKTAG() {
+ const char *str_tag = "ABCD";
+ uint32 tag = READ_BE_UINT32(str_tag);
+ TS_ASSERT_EQUALS(MKTAG('A','B','C','D'), tag);
+ }
+
+ void test_READ_BE_UINT32() {
+ const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
+ uint32 value = READ_BE_UINT32(data);
+ TS_ASSERT_EQUALS(value, 0x12345678UL);
+ }
+
+ void test_READ_LE_UINT32() {
+ const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
+ uint32 value = READ_LE_UINT32(data);
+ TS_ASSERT_EQUALS(value, 0x78563412UL);
+ }
+
+ void test_READ_BE_UINT16() {
+ const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
+ uint32 value = READ_BE_UINT16(data);
+ TS_ASSERT_EQUALS(value, 0x1234UL);
+ }
+
+ void test_READ_LE_UINT16() {
+ const char data[4] = { 0x12, 0x34, 0x56, 0x78 };
+ uint32 value = READ_LE_UINT16(data);
+ TS_ASSERT_EQUALS(value, 0x3412UL);
+ }
+};
diff --git a/tools/module.mk b/tools/module.mk
deleted file mode 100644
index 3368f5e527..0000000000
--- a/tools/module.mk
+++ /dev/null
@@ -1,86 +0,0 @@
-# $URL$
-# $Id$
-
-MODULE := tools
-
-MODULE_DIRS += \
- tools/
-
-
-#######################################################################
-# Tools directory
-#######################################################################
-
-TOOLS := \
- tools/convbdf$(EXEEXT) \
- tools/md5table$(EXEEXT) \
- tools/make-scumm-fontdata$(EXEEXT)
-
-include $(srcdir)/tools/*/module.mk
-
-.PHONY: $(srcdir)/tools/*/module.mk
-
-# Make sure the 'all' / 'clean' targets build/clean the tools, too
-#all:
-clean: clean-tools
-
-# Main target
-tools: $(TOOLS)
-
-clean-tools:
- -$(RM) $(TOOLS)
-
-#
-# Build rules for the tools
-#
-
-tools/convbdf$(EXEEXT): $(srcdir)/tools/convbdf.c
- $(QUIET)$(MKDIR) tools/$(DEPDIR)
- $(QUIET_LINK)$(LD) $(CFLAGS) -Wall -o $@ $<
-
-tools/md5table$(EXEEXT): $(srcdir)/tools/md5table.c
- $(QUIET)$(MKDIR) tools/$(DEPDIR)
- $(QUIET_LINK)$(LD) $(CFLAGS) -Wall -o $@ $<
-
-tools/make-scumm-fontdata$(EXEEXT): $(srcdir)/tools/make-scumm-fontdata.c
- $(QUIET)$(MKDIR) tools/$(DEPDIR)
- $(QUIET_LINK)$(LD) $(CFLAGS) -Wall -o $@ $<
-
-#
-# Rules to explicitly rebuild the credits / MD5 tables.
-# The rules for the files in the "web" resp. "docs" modules
-# assume that you are invoking "make" from within a complete
-# checkout of the ScummVM repository. Of course if that is not the
-# case, then you have to modify those paths...
-#
-
-credits:
- $(srcdir)/tools/credits.pl --text > $(srcdir)/AUTHORS
-# $(srcdir)/tools/credits.pl --rtf > $(srcdir)/Credits.rtf
- $(srcdir)/tools/credits.pl --cpp > $(srcdir)/gui/credits.h
- $(srcdir)/tools/credits.pl --xml-website > $(srcdir)/../../web/trunk/data/credits.xml
-# $(srcdir)/tools/credits.pl --xml-docbook > $(srcdir)/../../docs/trunk/docbook/credits.xml
-
-md5scumm: tools/md5table$(EXEEXT)
- tools/md5table$(EXEEXT) --c++ < $(srcdir)/tools/scumm-md5.txt > $(srcdir)/engines/scumm/scumm-md5.h
-
-#
-# Rules which automatically and implicitly rebuild the credits and
-# MD5 tables when needed.
-# These are currently disabled, because if the input data changes, then
-# the generated files should be checked in, too. Otherwise, we'd reduce
-# portability to system on which our tools can't (automatically) be
-# run for some reason.
-#
-
-#scumm/scumm-md5.h: $(srcdir)/tools/scumm-md5.txt tools/md5table$(EXEEXT)
-# tools/md5table$(EXEEXT) --c++ < $< > $@
-
-#AUTHORS: $(srcdir)/tools/credits.pl
-# $(srcdir)/tools/credits.pl --text > $@
-
-#gui/credits.h: $(srcdir)/tools/credits.pl
-# $(srcdir)/tools/credits.pl --cpp > $@
-
-
-.PHONY: clean-tools tools credits md5scumm
diff --git a/tools/svnpropset.sh b/tools/svnpropset.sh
deleted file mode 100755
index a6e331956c..0000000000
--- a/tools/svnpropset.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-# This script adds common svn properties to files
-
-if [ $# -eq 0 ]; then
- echo "Usage: $0 [FILE]..."
- exit 1
-fi
-
-for filename in $@; do
- if [ -f $filename ]; then
- svn propset svn:mime-type text/plain $filename
- svn propset svn:keywords "Date Rev Author URL Id" $filename
- svn propset svn:eol-style native $filename
- elif [ -e $filename ]; then
- echo "$0: error: '$filename' is not a regular file"
- else
- echo "$0: error: '$filename' does not exist"
- fi
-done
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index c2551454db..33189910c7 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -37,35 +37,35 @@ namespace Video {
// IDs used throughout the AVI files
// that will be handled by this player
-#define ID_RIFF MKID_BE('RIFF')
-#define ID_AVI MKID_BE('AVI ')
-#define ID_LIST MKID_BE('LIST')
-#define ID_HDRL MKID_BE('hdrl')
-#define ID_AVIH MKID_BE('avih')
-#define ID_STRL MKID_BE('strl')
-#define ID_STRH MKID_BE('strh')
-#define ID_VIDS MKID_BE('vids')
-#define ID_AUDS MKID_BE('auds')
-#define ID_MIDS MKID_BE('mids')
-#define ID_TXTS MKID_BE('txts')
-#define ID_JUNK MKID_BE('JUNK')
-#define ID_STRF MKID_BE('strf')
-#define ID_MOVI MKID_BE('movi')
-#define ID_REC MKID_BE('rec ')
-#define ID_VEDT MKID_BE('vedt')
-#define ID_IDX1 MKID_BE('idx1')
-#define ID_STRD MKID_BE('strd')
-#define ID_00AM MKID_BE('00AM')
-//#define ID_INFO MKID_BE('INFO')
+#define ID_RIFF MKTAG('R','I','F','F')
+#define ID_AVI MKTAG('A','V','I',' ')
+#define ID_LIST MKTAG('L','I','S','T')
+#define ID_HDRL MKTAG('h','d','r','l')
+#define ID_AVIH MKTAG('a','v','i','h')
+#define ID_STRL MKTAG('s','t','r','l')
+#define ID_STRH MKTAG('s','t','r','h')
+#define ID_VIDS MKTAG('v','i','d','s')
+#define ID_AUDS MKTAG('a','u','d','s')
+#define ID_MIDS MKTAG('m','i','d','s')
+#define ID_TXTS MKTAG('t','x','t','s')
+#define ID_JUNK MKTAG('J','U','N','K')
+#define ID_STRF MKTAG('s','t','r','f')
+#define ID_MOVI MKTAG('m','o','v','i')
+#define ID_REC MKTAG('r','e','c',' ')
+#define ID_VEDT MKTAG('v','e','d','t')
+#define ID_IDX1 MKTAG('i','d','x','1')
+#define ID_STRD MKTAG('s','t','r','d')
+#define ID_00AM MKTAG('0','0','A','M')
+//#define ID_INFO MKTAG('I','N','F','O')
// Codec tags
-#define ID_RLE MKID_BE('RLE ')
-#define ID_CRAM MKID_BE('CRAM')
-#define ID_MSVC MKID_BE('msvc')
-#define ID_WHAM MKID_BE('WHAM')
-#define ID_CVID MKID_BE('cvid')
-#define ID_IV32 MKID_BE('iv32')
-#define ID_DUCK MKID_BE('DUCK')
+#define ID_RLE MKTAG('R','L','E',' ')
+#define ID_CRAM MKTAG('C','R','A','M')
+#define ID_MSVC MKTAG('m','s','v','c')
+#define ID_WHAM MKTAG('W','H','A','M')
+#define ID_CVID MKTAG('c','v','i','d')
+#define ID_IV32 MKTAG('i','v','3','2')
+#define ID_DUCK MKTAG('D','U','C','K')
struct BITMAPINFOHEADER {
uint32 size;
diff --git a/video/codecs/cdtoons.cpp b/video/codecs/cdtoons.cpp
index eaa8f53602..bdca5f9c80 100644
--- a/video/codecs/cdtoons.cpp
+++ b/video/codecs/cdtoons.cpp
@@ -170,7 +170,7 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
nextPos += size;
switch (tag) {
- case MKID_BE('Diff'):
+ case MKTAG('D','i','f','f'):
{
debugN(5, "CDToons: Diff\n");
uint16 count = stream->readUint16BE();
@@ -206,7 +206,7 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
}
}
break;
- case MKID_BE('XFrm'):
+ case MKTAG('X','F','r','m'):
{
debugN(5, "CDToons: XFrm\n");
if (!(flags & 0x10))
@@ -229,7 +229,7 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
dirtyRect2XFrm.left, dirtyRect2XFrm.top, dirtyRect2XFrm.right, dirtyRect2XFrm.bottom);
}
break;
- case MKID_BE('Mrks'):
+ case MKTAG('M','r','k','s'):
debugN(5, "CDToons: Mrks\n");
if (!(flags & 0x2))
error("CDToons: useless Mrks?");
@@ -237,14 +237,14 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
// TODO
warning("CDToons: encountered Mrks, not implemented yet");
break;
- case MKID_BE('Scal'):
+ case MKTAG('S','c','a','l'):
// TODO
warning("CDToons: encountered Scal, not implemented yet");
break;
- case MKID_BE('WrMp'):
+ case MKTAG('W','r','M','p'):
warning("CDToons: encountered WrMp, ignoring");
break;
- case MKID_BE('FrtR'):
+ case MKTAG('F','r','t','R'):
{
debugN(5, "CDToons: FrtR\n");
if (!(flags & 0x40))
@@ -259,7 +259,7 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
}
}
break;
- case MKID_BE('BckR'):
+ case MKTAG('B','c','k','R'):
{
debugN(5, "CDToons: BckR\n");
if (!(flags & 0x20))
diff --git a/video/codecs/indeo3.cpp b/video/codecs/indeo3.cpp
index d9dde1e8e5..e7f470bd3a 100644
--- a/video/codecs/indeo3.cpp
+++ b/video/codecs/indeo3.cpp
@@ -85,7 +85,7 @@ bool Indeo3Decoder::isIndeo3(Common::SeekableReadStream &stream) {
return false;
// These 4 uint32s XOR'd need to spell "FRMH"
- if ((id0 ^ id1 ^ id2 ^ id3) != MKID_BE('FRMH'))
+ if ((id0 ^ id1 ^ id2 ^ id3) != MKTAG('F','R','M','H'))
return false;
return true;
diff --git a/video/codecs/qdm2.cpp b/video/codecs/qdm2.cpp
index d592548580..61e59c8aba 100644
--- a/video/codecs/qdm2.cpp
+++ b/video/codecs/qdm2.cpp
@@ -376,13 +376,7 @@ static inline unsigned int getBits(GetBitContext *s, int n) {
}
static inline void skipBits(GetBitContext *s, int n) {
- int reIndex, reCache;
-
- reIndex = s->index;
- reCache = 0;
-
- reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
- s->index = reIndex + n;
+ s->index += n;
}
#define BITS_LEFT(length, gb) ((length) - getBitsCount((gb)))
@@ -448,7 +442,7 @@ float *ff_cos_tabs[] = {
void initCosineTables(int index) {
int m = 1 << index;
- double freq = 2 * PI / m;
+ double freq = 2 * M_PI / m;
float *tab = ff_cos_tabs[index];
for (int i = 0; i <= m / 4; i++)
@@ -776,7 +770,7 @@ int fftInit(FFTContext *s, int nbits, int inverse) {
s->tmpBuf = (FFTComplex *)malloc(n * sizeof(FFTComplex));
} else {
for (i = 0; i < n / 2; i++) {
- alpha = 2 * PI * (float)i / (float)n;
+ alpha = 2 * M_PI * (float)i / (float)n;
c1 = cos(alpha);
s1 = sin(alpha) * s2;
s->exptab[i].re = c1;
@@ -814,7 +808,7 @@ int fftInit(FFTContext *s, int nbits, int inverse) {
*/
int rdftInit(RDFTContext *s, int nbits, RDFTransformType trans) {
int n = 1 << nbits;
- const double theta = (trans == RDFT || trans == IRIDFT ? -1 : 1) * 2 * PI / n;
+ const double theta = (trans == RDFT || trans == IRIDFT ? -1 : 1) * 2 * M_PI / n;
s->nbits = nbits;
s->inverse = trans == IRDFT || trans == IRIDFT;
@@ -1775,14 +1769,14 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
tmp = extraData->readUint32BE();
debug(1, "QDM2Stream::QDM2Stream() extraTag: %d", tmp);
- if (tmp != MKID_BE('frma'))
+ if (tmp != MKTAG('f','r','m','a'))
warning("QDM2Stream::QDM2Stream() extraTag mismatch");
tmp = extraData->readUint32BE();
debug(1, "QDM2Stream::QDM2Stream() extraType: %d", tmp);
- if (tmp == MKID_BE('QDMC'))
+ if (tmp == MKTAG('Q','D','M','C'))
warning("QDM2Stream::QDM2Stream() QDMC stream type not supported");
- else if (tmp != MKID_BE('QDM2'))
+ else if (tmp != MKTAG('Q','D','M','2'))
error("QDM2Stream::QDM2Stream() Unsupported stream type");
tmp_s = extraData->readSint32BE();
@@ -1792,7 +1786,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
tmp = extraData->readUint32BE();
debug(1, "QDM2Stream::QDM2Stream() extraTag2: %d", tmp);
- if (tmp != MKID_BE('QDCA'))
+ if (tmp != MKTAG('Q','D','C','A'))
warning("QDM2Stream::QDM2Stream() extraTag2 mismatch");
if (extraData->readUint32BE() != 1)
@@ -1824,7 +1818,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
tmp = extraData->readUint32BE();
debug(1, "QDM2Stream::QDM2Stream() extraTag3: %d", tmp);
- if (tmp != MKID_BE('QDCP'))
+ if (tmp != MKTAG('Q','D','C','P'))
warning("QDM2Stream::QDM2Stream() extraTag3 mismatch");
if ((float)extraData->readUint32BE() != 1.0)
@@ -3009,7 +3003,7 @@ void QDM2Stream::qdm2_fft_generate_tone(FFTTone *tone)
float level, f[6];
int i;
QDM2Complex c;
- const double iscale = 2.0 * PI / 512.0;
+ const double iscale = 2.0 * M_PI / 512.0;
tone->phase += tone->phase_shift;
@@ -3050,7 +3044,7 @@ void QDM2Stream::qdm2_fft_generate_tone(FFTTone *tone)
void QDM2Stream::qdm2_fft_tone_synthesizer(uint8 sub_packet) {
int i, j, ch;
- const double iscale = 0.25 * PI;
+ const double iscale = 0.25 * M_PI;
for (ch = 0; ch < _channels; ch++) {
memset(_fft.complex[ch], 0, _frameSize * sizeof(QDM2Complex));
diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp
index c8beb3b604..a755d18bb0 100644
--- a/video/coktel_decoder.cpp
+++ b/video/coktel_decoder.cpp
@@ -36,7 +36,7 @@
#include "audio/decoders/raw.h"
#include "common/memstream.h"
-static const uint32 kVideoCodecIndeo3 = MKID_BE('iv32');
+static const uint32 kVideoCodecIndeo3 = MKTAG('i','v','3','2');
namespace Video {
@@ -556,10 +556,7 @@ void CoktelDecoder::renderBlockSparse2Y(Graphics::Surface &dstSurf, const byte *
int16 pixCount = *src++;
if (pixCount & 0x80) { // Data
- int16 copyCount;
-
pixCount = MIN((pixCount & 0x7F) + 1, srcRect.width() - pixWritten);
- copyCount = CLIP<int16>(rect.width() - pixWritten, 0, pixCount);
memcpy(dstRow , src, pixCount);
memcpy(dstRow + dstSurf.pitch, src, pixCount);
@@ -1377,12 +1374,13 @@ bool IMDDecoder::renderFrame(Common::Rect &rect) {
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
// Directly uncompress onto the video surface
- int offsetX = rect.left * _surface.bytesPerPixel;
- int offsetY = (_y + rect.top) * _surface.pitch;
+ const int offsetX = rect.left * _surface.bytesPerPixel;
+ const int offsetY = (_y + rect.top) * _surface.pitch;
+ const int offset = offsetX + offsetY;
- deLZ77((byte *)_surface.pixels + offsetX + offsetY, dataPtr, dataSize,
- _surface.w * _surface.h * _surface.bytesPerPixel);
- return true;
+ if (deLZ77((byte *)_surface.pixels + offset, dataPtr, dataSize,
+ _surface.w * _surface.h * _surface.bytesPerPixel - offset))
+ return true;
}
_videoBufferLen[1] = deLZ77(_videoBuffer[1], dataPtr, dataSize, _videoBufferSize);
@@ -2244,12 +2242,13 @@ bool VMDDecoder::renderFrame(Common::Rect &rect) {
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0) && (_blitMode == 0)) {
// Directly uncompress onto the video surface
- int offsetX = rect.left * _surface.bytesPerPixel;
- int offsetY = (_y + rect.top) * _surface.pitch;
+ const int offsetX = rect.left * _surface.bytesPerPixel;
+ const int offsetY = (_y + rect.top) * _surface.pitch;
+ const int offset = offsetX - offsetY;
- deLZ77((byte *)_surface.pixels + offsetX + offsetY, dataPtr, dataSize,
- _surface.w * _surface.h * _surface.bytesPerPixel);
- return true;
+ if (deLZ77((byte *)_surface.pixels + offset, dataPtr, dataSize,
+ _surface.w * _surface.h * _surface.bytesPerPixel - offset))
+ return true;
}
srcBuffer = 1;
diff --git a/video/dxa_decoder.cpp b/video/dxa_decoder.cpp
index 3a8b3acae9..a64b8f6fee 100644
--- a/video/dxa_decoder.cpp
+++ b/video/dxa_decoder.cpp
@@ -73,7 +73,7 @@ bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
_fileStream = stream;
uint32 tag = _fileStream->readUint32BE();
- assert(tag == MKID_BE('DEXA'));
+ assert(tag == MKTAG('D','E','X','A'));
uint8 flags = _fileStream->readByte();
_frameCount = _fileStream->readUint16BE();
@@ -136,7 +136,7 @@ bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
switch (tag) {
case 0: // No more tags
break;
- case MKID_BE('MAXD'):
+ case MKTAG('M','A','X','D'):
assert(size == 4);
_decompBufferSize = _fileStream->readUint32BE();
break;
@@ -306,11 +306,11 @@ void DXADecoder::decode13(int size) {
memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
int codeSize = _width * _curHeight / 16;
- int dataSize, motSize, maskSize;
+ int dataSize, motSize;
dataSize = READ_BE_UINT32(&_decompBuffer[0]);
motSize = READ_BE_UINT32(&_decompBuffer[4]);
- maskSize = READ_BE_UINT32(&_decompBuffer[8]);
+ //maskSize = READ_BE_UINT32(&_decompBuffer[8]);
codeBuf = &_decompBuffer[12];
dataBuf = &codeBuf[codeSize];
@@ -479,13 +479,13 @@ void DXADecoder::decode13(int size) {
const Graphics::Surface *DXADecoder::decodeNextFrame() {
uint32 tag = _fileStream->readUint32BE();
- if (tag == MKID_BE('CMAP')) {
+ if (tag == MKTAG('C','M','A','P')) {
_fileStream->read(_palette, 256 * 3);
_dirtyPalette = true;
}
tag = _fileStream->readUint32BE();
- if (tag == MKID_BE('FRAM')) {
+ if (tag == MKTAG('F','R','A','M')) {
byte type = _fileStream->readByte();
uint32 size = _fileStream->readUint32BE();
if ((_inBuffer == NULL) || (_inBufferSize < size)) {
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index 6944fd5a77..826b7bfcaf 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -267,28 +267,28 @@ void QuickTimeDecoder::seekToTime(Audio::Timestamp time) {
}
Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) {
- if (codecTag == MKID_BE('cvid')) {
+ if (codecTag == MKTAG('c','v','i','d')) {
// Cinepak: As used by most Myst and all Riven videos as well as some Myst ME videos. "The Chief" videos also use this.
return new CinepakDecoder(bitsPerPixel);
- } else if (codecTag == MKID_BE('rpza')) {
+ } else if (codecTag == MKTAG('r','p','z','a')) {
// Apple Video ("Road Pizza"): Used by some Myst videos.
return new RPZADecoder(getWidth(), getHeight());
- } else if (codecTag == MKID_BE('rle ')) {
+ } else if (codecTag == MKTAG('r','l','e',' ')) {
// QuickTime RLE: Used by some Myst ME videos.
return new QTRLEDecoder(getWidth(), getHeight(), bitsPerPixel);
- } else if (codecTag == MKID_BE('smc ')) {
+ } else if (codecTag == MKTAG('s','m','c',' ')) {
// Apple SMC: Used by some Myst videos.
return new SMCDecoder(getWidth(), getHeight());
- } else if (codecTag == MKID_BE('SVQ1')) {
+ } else if (codecTag == MKTAG('S','V','Q','1')) {
// Sorenson Video 1: Used by some Myst ME videos.
warning("Sorenson Video 1 not yet supported");
- } else if (codecTag == MKID_BE('SVQ3')) {
+ } else if (codecTag == MKTAG('S','V','Q','3')) {
// Sorenson Video 3: Used by some Myst ME videos.
warning("Sorenson Video 3 not yet supported");
- } else if (codecTag == MKID_BE('jpeg')) {
+ } else if (codecTag == MKTAG('j','p','e','g')) {
// Motion JPEG: Used by some Myst ME 10th Anniversary videos.
return new JPEGDecoder();
- } else if (codecTag == MKID_BE('QkBk')) {
+ } else if (codecTag == MKTAG('Q','k','B','k')) {
// CDToons: Used by most of the Broderbund games.
return new CDToonsDecoder(getWidth(), getHeight());
} else {
@@ -424,10 +424,10 @@ bool QuickTimeDecoder::loadFile(const Common::String &filename) {
if (_resFork->hasResFork()) {
// Search for a 'moov' resource
- Common::MacResIDArray idArray = _resFork->getResIDArray(MKID_BE('moov'));
+ Common::MacResIDArray idArray = _resFork->getResIDArray(MKTAG('m','o','o','v'));
if (!idArray.empty())
- _fd = _resFork->getResource(MKID_BE('moov'), idArray[0]);
+ _fd = _resFork->getResource(MKTAG('m','o','o','v'), idArray[0]);
if (_fd) {
atom.size = _fd->size();
@@ -507,7 +507,7 @@ void QuickTimeDecoder::init() {
_curAudioChunk = 0;
// Make sure the bits per sample transfers to the sample size
- if (entry->codecTag == MKID_BE('raw ') || entry->codecTag == MKID_BE('twos'))
+ if (entry->codecTag == MKTAG('r','a','w',' ') || entry->codecTag == MKTAG('t','w','o','s'))
_streams[_audioStreamIndex]->sample_size = (entry->bitsPerSample / 8) * entry->channels;
startAudio();
@@ -533,31 +533,31 @@ void QuickTimeDecoder::init() {
void QuickTimeDecoder::initParseTable() {
static const ParseTable p[] = {
- { &QuickTimeDecoder::readDefault, MKID_BE('dinf') },
- { &QuickTimeDecoder::readLeaf, MKID_BE('dref') },
- { &QuickTimeDecoder::readDefault, MKID_BE('edts') },
- { &QuickTimeDecoder::readELST, MKID_BE('elst') },
- { &QuickTimeDecoder::readHDLR, MKID_BE('hdlr') },
- { &QuickTimeDecoder::readDefault, MKID_BE('mdat') },
- { &QuickTimeDecoder::readMDHD, MKID_BE('mdhd') },
- { &QuickTimeDecoder::readDefault, MKID_BE('mdia') },
- { &QuickTimeDecoder::readDefault, MKID_BE('minf') },
- { &QuickTimeDecoder::readMOOV, MKID_BE('moov') },
- { &QuickTimeDecoder::readMVHD, MKID_BE('mvhd') },
- { &QuickTimeDecoder::readLeaf, MKID_BE('smhd') },
- { &QuickTimeDecoder::readDefault, MKID_BE('stbl') },
- { &QuickTimeDecoder::readSTCO, MKID_BE('stco') },
- { &QuickTimeDecoder::readSTSC, MKID_BE('stsc') },
- { &QuickTimeDecoder::readSTSD, MKID_BE('stsd') },
- { &QuickTimeDecoder::readSTSS, MKID_BE('stss') },
- { &QuickTimeDecoder::readSTSZ, MKID_BE('stsz') },
- { &QuickTimeDecoder::readSTTS, MKID_BE('stts') },
- { &QuickTimeDecoder::readTKHD, MKID_BE('tkhd') },
- { &QuickTimeDecoder::readTRAK, MKID_BE('trak') },
- { &QuickTimeDecoder::readLeaf, MKID_BE('udta') },
- { &QuickTimeDecoder::readLeaf, MKID_BE('vmhd') },
- { &QuickTimeDecoder::readCMOV, MKID_BE('cmov') },
- { &QuickTimeDecoder::readWAVE, MKID_BE('wave') },
+ { &QuickTimeDecoder::readDefault, MKTAG('d','i','n','f') },
+ { &QuickTimeDecoder::readLeaf, MKTAG('d','r','e','f') },
+ { &QuickTimeDecoder::readDefault, MKTAG('e','d','t','s') },
+ { &QuickTimeDecoder::readELST, MKTAG('e','l','s','t') },
+ { &QuickTimeDecoder::readHDLR, MKTAG('h','d','l','r') },
+ { &QuickTimeDecoder::readDefault, MKTAG('m','d','a','t') },
+ { &QuickTimeDecoder::readMDHD, MKTAG('m','d','h','d') },
+ { &QuickTimeDecoder::readDefault, MKTAG('m','d','i','a') },
+ { &QuickTimeDecoder::readDefault, MKTAG('m','i','n','f') },
+ { &QuickTimeDecoder::readMOOV, MKTAG('m','o','o','v') },
+ { &QuickTimeDecoder::readMVHD, MKTAG('m','v','h','d') },
+ { &QuickTimeDecoder::readLeaf, MKTAG('s','m','h','d') },
+ { &QuickTimeDecoder::readDefault, MKTAG('s','t','b','l') },
+ { &QuickTimeDecoder::readSTCO, MKTAG('s','t','c','o') },
+ { &QuickTimeDecoder::readSTSC, MKTAG('s','t','s','c') },
+ { &QuickTimeDecoder::readSTSD, MKTAG('s','t','s','d') },
+ { &QuickTimeDecoder::readSTSS, MKTAG('s','t','s','s') },
+ { &QuickTimeDecoder::readSTSZ, MKTAG('s','t','s','z') },
+ { &QuickTimeDecoder::readSTTS, MKTAG('s','t','t','s') },
+ { &QuickTimeDecoder::readTKHD, MKTAG('t','k','h','d') },
+ { &QuickTimeDecoder::readTRAK, MKTAG('t','r','a','k') },
+ { &QuickTimeDecoder::readLeaf, MKTAG('u','d','t','a') },
+ { &QuickTimeDecoder::readLeaf, MKTAG('v','m','h','d') },
+ { &QuickTimeDecoder::readCMOV, MKTAG('c','m','o','v') },
+ { &QuickTimeDecoder::readWAVE, MKTAG('w','a','v','e') },
{ 0, 0 }
};
@@ -581,7 +581,7 @@ int QuickTimeDecoder::readDefault(MOVatom atom) {
// Some QuickTime videos with resource forks have mdat chunks
// that are of size 0. Adjust it so it's the correct size.
- if (a.type == MKID_BE('mdat') && a.size == 0)
+ if (a.type == MKTAG('m','d','a','t') && a.size == 0)
a.size = _fd->size();
}
@@ -654,16 +654,16 @@ int QuickTimeDecoder::readCMOV(MOVatom atom) {
#ifdef USE_ZLIB
// Read in the dcom atom
_fd->readUint32BE();
- if (_fd->readUint32BE() != MKID_BE('dcom'))
+ if (_fd->readUint32BE() != MKTAG('d','c','o','m'))
return -1;
- if (_fd->readUint32BE() != MKID_BE('zlib')) {
+ if (_fd->readUint32BE() != MKTAG('z','l','i','b')) {
warning("Unknown cmov compression type");
return -1;
}
// Read in the cmvd atom
uint32 compressedSize = _fd->readUint32BE() - 12;
- if (_fd->readUint32BE() != MKID_BE('cmvd'))
+ if (_fd->readUint32BE() != MKTAG('c','m','v','d'))
return -1;
uint32 uncompressedSize = _fd->readUint32BE();
@@ -688,7 +688,7 @@ int QuickTimeDecoder::readCMOV(MOVatom atom) {
_fd = new Common::MemoryReadStream(uncompressedData, uncompressedSize, DisposeAfterUse::YES);
// Read the contents of the uncompressed data
- MOVatom a = { MKID_BE('moov'), 0, uncompressedSize };
+ MOVatom a = { MKTAG('m','o','o','v'), 0, uncompressedSize };
int err = readDefault(a);
// Assign the file handle back to the original handle
@@ -820,19 +820,25 @@ int QuickTimeDecoder::readTKHD(MOVatom atom) {
// edit list atom
int QuickTimeDecoder::readELST(MOVatom atom) {
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
_fd->readByte(); // version
_fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
- uint32 editCount = _streams[_numStreams - 1]->edit_count = _fd->readUint32BE(); // entries
- for (uint32 i = 0; i < editCount; i++){
- _fd->readUint32BE(); // Track duration
- _fd->readUint32BE(); // Media time
- _fd->readUint32BE(); // Media rate
- }
+ st->editCount = _fd->readUint32BE();
+ st->editList = new EditListEntry[st->editCount];
- debug(0, "track[%i].edit_count = %i", _numStreams - 1, _streams[_numStreams - 1]->edit_count);
+ debug(2, "Track %d edit list count: %d", _numStreams - 1, st->editCount);
+
+ for (uint32 i = 0; i < st->editCount; i++){
+ st->editList[i].trackDuration = _fd->readUint32BE();
+ st->editList[i].mediaTime = _fd->readSint32BE();
+ st->editList[i].mediaRate = Common::Rational(_fd->readUint32BE(), 0x10000);
+ debugN(3, "\tDuration = %d, Media Time = %d, ", st->editList[i].trackDuration, st->editList[i].mediaTime);
+ st->editList[i].mediaRate.debugPrint(3, "Media Rate =");
+ }
- if (editCount != 1)
+ if (st->editCount != 1)
warning("Multiple edit list entries. Things may go awry");
return 0;
@@ -851,19 +857,19 @@ int QuickTimeDecoder::readHDLR(MOVatom atom) {
debug(0, "ctype= %s (0x%08lx)", tag2str(ctype), (long)ctype);
debug(0, "stype= %s", tag2str(type));
- if(ctype == MKID_BE('mhlr')) // MOV
+ if(ctype == MKTAG('m','h','l','r')) // MOV
debug(0, "MOV detected");
else if(ctype == 0) {
warning("MP4 streams are not supported");
return -1;
}
- if (type == MKID_BE('vide'))
+ if (type == MKTAG('v','i','d','e'))
st->codec_type = CODEC_TYPE_VIDEO;
- else if (type == MKID_BE('soun'))
+ else if (type == MKTAG('s','o','u','n'))
st->codec_type = CODEC_TYPE_AUDIO;
- _fd->readUint32BE(); // component manufacture
+ _fd->readUint32BE(); // component manufacture
_fd->readUint32BE(); // component flags
_fd->readUint32BE(); // component flags mask
@@ -1052,7 +1058,7 @@ int QuickTimeDecoder::readSTSD(MOVatom atom) {
// Version 0 videos (such as the Riven ones) don't have this set,
// but we need it later on. Add it in here.
- if (format == MKID_BE('ima4')) {
+ if (format == MKTAG('i','m','a','4')) {
entry->samplesPerFrame = 64;
entry->bytesPerFrame = 34 * entry->channels;
}
@@ -1225,7 +1231,7 @@ int QuickTimeDecoder::readWAVE(MOVatom atom) {
if (atom.size > (1 << 30))
return -1;
- if (st->stsdEntries[0].codecTag == MKID_BE('QDM2')) // Read extradata for QDM2
+ if (st->stsdEntries[0].codecTag == MKTAG('Q','D','M','2')) // Read extradata for QDM2
st->extradata = _fd->readStream(atom.size - 8);
else if (atom.size > 8)
return readDefault(atom);
@@ -1312,11 +1318,11 @@ Common::SeekableReadStream *QuickTimeDecoder::getNextFramePacket(uint32 &descId)
bool QuickTimeDecoder::checkAudioCodecSupport(uint32 tag) {
// Check if the codec is a supported codec
- if (tag == MKID_BE('twos') || tag == MKID_BE('raw ') || tag == MKID_BE('ima4'))
+ if (tag == MKTAG('t','w','o','s') || tag == MKTAG('r','a','w',' ') || tag == MKTAG('i','m','a','4'))
return true;
#ifdef VIDEO_CODECS_QDM2_H
- if (tag == MKID_BE('QDM2'))
+ if (tag == MKTAG('Q','D','M','2'))
return true;
#endif
@@ -1331,10 +1337,10 @@ Audio::AudioStream *QuickTimeDecoder::createAudioStream(Common::SeekableReadStre
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0];
- if (entry->codecTag == MKID_BE('twos') || entry->codecTag == MKID_BE('raw ')) {
+ if (entry->codecTag == MKTAG('t','w','o','s') || entry->codecTag == MKTAG('r','a','w',' ')) {
// Fortunately, most of the audio used in Myst videos is raw...
uint16 flags = 0;
- if (entry->codecTag == MKID_BE('raw '))
+ if (entry->codecTag == MKTAG('r','a','w',' '))
flags |= Audio::FLAG_UNSIGNED;
if (entry->channels == 2)
flags |= Audio::FLAG_STEREO;
@@ -1345,11 +1351,11 @@ Audio::AudioStream *QuickTimeDecoder::createAudioStream(Common::SeekableReadStre
stream->read(data, dataSize);
delete stream;
return Audio::makeRawStream(data, dataSize, entry->sampleRate, flags);
- } else if (entry->codecTag == MKID_BE('ima4')) {
+ } else if (entry->codecTag == MKTAG('i','m','a','4')) {
// Riven uses this codec (as do some Myst ME videos)
return Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMApple, entry->sampleRate, entry->channels, 34);
#ifdef VIDEO_CODECS_QDM2_H
- } else if (entry->codecTag == MKID_BE('QDM2')) {
+ } else if (entry->codecTag == MKTAG('Q','D','M','2')) {
// Several Myst ME videos use this codec
return makeQDM2Stream(stream, _streams[_audioStreamIndex]->extradata);
#endif
@@ -1465,12 +1471,30 @@ QuickTimeDecoder::STSDEntry::~STSDEntry() {
}
QuickTimeDecoder::MOVStreamContext::MOVStreamContext() {
- // FIXME: Setting all members to 0 via memset is a hack -- it works
- // because the only non-POD member of MOVStreamContext is of type
- // Common::Rational, and that luckily has no virtual methods nor
- // does it keep internal pointers or anything like that. But watch
- // out if you ever extend MOVStreamContext!
- memset(this, 0, sizeof(MOVStreamContext));
+ chunk_count = 0;
+ chunk_offsets = 0;
+ stts_count = 0;
+ stts_data = 0;
+ sample_to_chunk_sz = 0;
+ sample_to_chunk = 0;
+ sample_size = 0;
+ sample_count = 0;
+ sample_sizes = 0;
+ keyframe_count = 0;
+ keyframes = 0;
+ time_scale = 0;
+ time_rate = 0;
+ width = 0;
+ height = 0;
+ codec_type = CODEC_TYPE_MOV_OTHER;
+ stsdEntryCount = 0;
+ stsdEntries = 0;
+ editCount = 0;
+ editList = 0;
+ extradata = 0;
+ nb_frames = 0;
+ duration = 0;
+ start_time = 0;
}
QuickTimeDecoder::MOVStreamContext::~MOVStreamContext() {
@@ -1480,6 +1504,7 @@ QuickTimeDecoder::MOVStreamContext::~MOVStreamContext() {
delete[] sample_sizes;
delete[] keyframes;
delete[] stsdEntries;
+ delete[] editList;
delete extradata;
}
diff --git a/video/qt_decoder.h b/video/qt_decoder.h
index 809c8a718d..f11689e021 100644
--- a/video/qt_decoder.h
+++ b/video/qt_decoder.h
@@ -122,6 +122,7 @@ public:
// SeekableVideoDecoder API
void seekToFrame(uint32 frame);
void seekToTime(Audio::Timestamp time);
+ uint32 getDuration() const { return _duration * 1000 / _timeScale; }
private:
// This is the file handle from which data is read from. It can be the actual file handle or a decompressed stream.
@@ -149,6 +150,12 @@ private:
uint32 id;
};
+ struct EditListEntry {
+ uint32 trackDuration;
+ int32 mediaTime;
+ Common::Rational mediaRate;
+ };
+
struct STSDEntry {
STSDEntry();
~STSDEntry();
@@ -183,7 +190,6 @@ private:
uint32 *chunk_offsets;
int stts_count;
MOVstts *stts_data;
- int edit_count; /* number of 'edit' (elst atom) */
uint32 sample_to_chunk_sz;
MOVstsc *sample_to_chunk;
uint32 sample_size;
@@ -201,6 +207,9 @@ private:
uint32 stsdEntryCount;
STSDEntry *stsdEntries;
+ uint32 editCount;
+ EditListEntry *editList;
+
Common::SeekableReadStream *extradata;
uint32 nb_frames;
diff --git a/video/smk_decoder.cpp b/video/smk_decoder.cpp
index a9f2eeeb5b..760d0045d9 100644
--- a/video/smk_decoder.cpp
+++ b/video/smk_decoder.cpp
@@ -379,13 +379,13 @@ bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
_header.signature = _fileStream->readUint32BE();
// No BINK support available
- if (_header.signature == MKID_BE('BIKi')) {
+ if (_header.signature == MKTAG('B','I','K','i')) {
delete _fileStream;
_fileStream = 0;
return false;
}
- assert(_header.signature == MKID_BE('SMK2') || _header.signature == MKID_BE('SMK4'));
+ assert(_header.signature == MKTAG('S','M','K','2') || _header.signature == MKTAG('S','M','K','4'));
uint32 width = _fileStream->readUint32LE();
uint32 height = _fileStream->readUint32LE();
@@ -615,7 +615,7 @@ const Graphics::Surface *SmackerDecoder::decodeNextFrame() {
break;
case SMK_BLOCK_FULL:
// Smacker v2 has one mode, Smacker v4 has three
- if (_header.signature == MKID_BE('SMK2')) {
+ if (_header.signature == MKTAG('S','M','K','2')) {
mode = 0;
} else {
// 00 - mode 0
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index 3f23d83761..a6317bac8f 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -50,18 +50,7 @@ uint32 VideoDecoder::getElapsedTime() const {
}
void VideoDecoder::setSystemPalette() {
- const byte *vidPalette = getPalette();
- byte *sysPalette = new byte[256 * 4];
-
- for (uint16 i = 0; i < 256; i++) {
- sysPalette[i * 4] = vidPalette[i * 3];
- sysPalette[i * 4 + 1] = vidPalette[i * 3 + 1];
- sysPalette[i * 4 + 2] = vidPalette[i * 3 + 2];
- sysPalette[i * 4 + 3] = 0;
- }
-
- g_system->getPaletteManager()->setPalette(sysPalette, 0, 256);
- delete[] sysPalette;
+ g_system->getPaletteManager()->setPalette(getPalette(), 0, 256);
}
bool VideoDecoder::needsUpdate() const {
diff --git a/video/video_decoder.h b/video/video_decoder.h
index 97cd133bc0..348b5dc0a3 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -266,6 +266,11 @@ public:
* Implementation of RewindableVideoDecoder::rewind().
*/
virtual void rewind() { seekToTime(0); }
+
+ /**
+ * Get the total duration of the video (in ms).
+ */
+ virtual uint32 getDuration() const = 0;
};
} // End of namespace Video