aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS5
-rw-r--r--NEWS14
-rw-r--r--README129
-rw-r--r--backends/events/default/default-events.cpp74
-rw-r--r--backends/events/default/default-events.h4
-rw-r--r--backends/fs/abstract-fs.cpp40
-rw-r--r--backends/fs/abstract-fs.h53
-rw-r--r--backends/fs/amigaos4/amigaos4-fs-factory.cpp4
-rw-r--r--backends/fs/amigaos4/amigaos4-fs-factory.h13
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp49
-rw-r--r--backends/fs/ds/ds-fs-factory.cpp2
-rw-r--r--backends/fs/ds/ds-fs-factory.h4
-rw-r--r--backends/fs/ds/ds-fs.cpp250
-rw-r--r--backends/fs/ds/ds-fs.h47
-rw-r--r--backends/fs/palmos/palmos-fs-factory.cpp2
-rw-r--r--backends/fs/palmos/palmos-fs-factory.h4
-rw-r--r--backends/fs/palmos/palmos-fs.cpp72
-rw-r--r--backends/fs/posix/posix-fs-factory.cpp11
-rw-r--r--backends/fs/posix/posix-fs-factory.h14
-rw-r--r--backends/fs/posix/posix-fs.cpp212
-rw-r--r--backends/fs/posix/posix-fs.h86
-rw-r--r--backends/fs/ps2/ps2-fs-factory.cpp2
-rw-r--r--backends/fs/ps2/ps2-fs-factory.h4
-rw-r--r--backends/fs/ps2/ps2-fs.cpp73
-rw-r--r--backends/fs/psp/psp-fs-factory.cpp2
-rw-r--r--backends/fs/psp/psp-fs-factory.h4
-rw-r--r--backends/fs/psp/psp-fs.cpp64
-rw-r--r--backends/fs/stdiostream.cpp161
-rw-r--r--backends/fs/stdiostream.h (renamed from engines/scumm/smush/chunk.h)76
-rw-r--r--backends/fs/symbian/symbian-fs-factory.cpp4
-rw-r--r--backends/fs/symbian/symbian-fs-factory.h13
-rw-r--r--backends/fs/symbian/symbian-fs.cpp162
-rw-r--r--backends/fs/symbian/symbianstream.cpp274
-rw-r--r--backends/fs/symbian/symbianstream.h62
-rw-r--r--backends/fs/wii/wii-fs-factory.cpp2
-rw-r--r--backends/fs/wii/wii-fs-factory.h4
-rw-r--r--backends/fs/wii/wii-fs.cpp70
-rw-r--r--backends/fs/windows/windows-fs-factory.cpp4
-rw-r--r--backends/fs/windows/windows-fs-factory.h13
-rw-r--r--backends/fs/windows/windows-fs.cpp86
-rw-r--r--backends/midi/seq.cpp2
-rw-r--r--backends/midi/stmidi.cpp155
-rw-r--r--backends/module.mk3
-rw-r--r--backends/platform/dc/dc-fs.cpp79
-rw-r--r--backends/platform/dc/selector.cpp12
-rw-r--r--backends/platform/dc/vmsave.cpp26
-rw-r--r--backends/platform/ds/arm7/Makefile2
-rw-r--r--backends/platform/ds/arm7/source/main.cpp5
-rw-r--r--backends/platform/ds/arm9/dist/readme_ds.txt840
-rw-r--r--backends/platform/ds/arm9/makefile90
-rw-r--r--backends/platform/ds/arm9/source/blitters_arm.s137
-rw-r--r--backends/platform/ds/arm9/source/cdaudio.h2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp709
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h13
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.cpp283
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.h13
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.cpp43
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.h8
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp232
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h26
-rw-r--r--backends/platform/ds/arm9/source/portdefs.h5
-rw-r--r--backends/platform/ds/arm9/source/ramsave.cpp30
-rw-r--r--backends/platform/ds/arm9/source/ramsave.h14
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.cpp30
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.h1
-rw-r--r--backends/platform/ds/logog.bmpbin0 -> 630 bytes
-rw-r--r--backends/platform/ds/makefile20
-rw-r--r--backends/platform/iphone/iphone_keyboard.m3
-rw-r--r--backends/platform/iphone/iphone_main.m13
-rw-r--r--backends/platform/iphone/iphone_video.m14
-rw-r--r--backends/platform/iphone/osys_iphone.cpp753
-rw-r--r--backends/platform/iphone/osys_iphone.h30
-rw-r--r--backends/platform/null/null.cpp29
-rw-r--r--backends/platform/ps2/rawsavefile.cpp13
-rw-r--r--backends/platform/ps2/rawsavefile.h3
-rw-r--r--backends/platform/ps2/savefile.cpp59
-rw-r--r--backends/platform/ps2/savefile.h37
-rw-r--r--backends/platform/psp/osys_psp.cpp15
-rw-r--r--backends/platform/psp/osys_psp_gu.cpp14
-rw-r--r--backends/platform/psp/portdefs.h1
-rw-r--r--backends/platform/psp/psp_main.cpp10
-rw-r--r--backends/platform/sdl/sdl.cpp146
-rw-r--r--backends/platform/sdl/sdl.h4
-rw-r--r--backends/platform/symbian/AdaptAllMMPs.pl16
-rw-r--r--backends/platform/symbian/BuildPackageUpload_AllVersions.pl10
-rw-r--r--backends/platform/symbian/BuildPackageUpload_LocalSettings.pl76
-rw-r--r--backends/platform/symbian/README12
-rw-r--r--backends/platform/symbian/S60/ScummVM_S60.mmp.in1
-rw-r--r--backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg4
-rw-r--r--backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg2
-rw-r--r--backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in1
-rw-r--r--backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg4
-rw-r--r--backends/platform/symbian/S80/ScummVM_S80.mmp.in1
-rw-r--r--backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg2
-rw-r--r--backends/platform/symbian/S90/Scummvm_S90.mmp.in1
-rw-r--r--backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg2
-rw-r--r--backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in1
-rw-r--r--backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg4
-rw-r--r--backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg2
-rw-r--r--backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in1
-rw-r--r--backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg2
-rw-r--r--backends/platform/symbian/mmp/scummvm_base.mmp.in8
-rw-r--r--backends/platform/symbian/mmp/scummvm_tinsel.mmp.in56
-rw-r--r--backends/platform/symbian/src/SymbianActions.cpp2
-rw-r--r--backends/platform/symbian/src/SymbianOS.cpp292
-rw-r--r--backends/platform/symbian/src/SymbianOS.h11
-rw-r--r--backends/platform/symbian/src/main_features.inl92
-rw-r--r--backends/platform/symbian/src/portdefs.h44
-rw-r--r--backends/platform/symbian/src/vsnprintf.h668
-rw-r--r--backends/platform/wince/CEActionsPocket.cpp2
-rw-r--r--backends/platform/wince/CEActionsSmartphone.cpp2
-rw-r--r--backends/platform/wince/CELauncherDialog.cpp12
-rw-r--r--backends/platform/wince/CELauncherDialog.h2
-rw-r--r--backends/platform/wince/Makefile6
-rw-r--r--backends/platform/wince/README-WinCE.txt189
-rw-r--r--backends/platform/wince/wince-sdl.cpp13
-rw-r--r--backends/platform/wince/wince-sdl.h1
-rw-r--r--backends/saves/compressed/compressed-saves.cpp270
-rw-r--r--backends/saves/default/default-saves.cpp35
-rw-r--r--backends/saves/default/default-saves.h3
-rw-r--r--base/commandLine.cpp19
-rw-r--r--base/main.cpp38
-rw-r--r--base/module.mk1
-rw-r--r--base/plugins.cpp28
-rw-r--r--base/plugins.h9
-rw-r--r--base/version.cpp11
-rw-r--r--common/advancedDetector.cpp6
-rw-r--r--common/advancedDetector.h2
-rw-r--r--common/archive.cpp344
-rw-r--r--common/archive.h231
-rw-r--r--common/array.h66
-rw-r--r--common/config-file.cpp68
-rw-r--r--common/config-manager.cpp9
-rw-r--r--common/events.h23
-rw-r--r--common/file.cpp444
-rw-r--r--common/file.h48
-rw-r--r--common/fs.cpp58
-rw-r--r--common/fs.h46
-rw-r--r--common/hash-str.h4
-rw-r--r--common/hashmap.cpp116
-rw-r--r--common/hashmap.h272
-rw-r--r--common/iff_container.h16
-rw-r--r--common/keyboard.h2
-rw-r--r--common/list.h5
-rw-r--r--common/md5.cpp11
-rw-r--r--common/md5.h5
-rw-r--r--common/memorypool.cpp111
-rw-r--r--common/memorypool.h45
-rw-r--r--common/module.mk1
-rw-r--r--common/ptr.h4
-rw-r--r--common/queue.h94
-rw-r--r--common/str.cpp244
-rw-r--r--common/str.h107
-rw-r--r--common/stream.cpp94
-rw-r--r--common/stream.h193
-rw-r--r--common/system.cpp10
-rw-r--r--common/system.h13
-rw-r--r--common/unarj.cpp348
-rw-r--r--common/unarj.h83
-rw-r--r--common/unzip.h50
-rw-r--r--common/util.cpp50
-rw-r--r--common/util.h23
-rw-r--r--common/xmlparser.cpp11
-rw-r--r--common/zlib.cpp308
-rw-r--r--common/zlib.h57
-rwxr-xr-xconfigure10
-rw-r--r--dists/engine-data/drascula.datbin213737 -> 218411 bytes
-rw-r--r--dists/engine-data/kyra.datbin240402 -> 242675 bytes
-rw-r--r--dists/macosx/Info.plist.in4
-rw-r--r--dists/msvc7/agi.vcproj15
-rw-r--r--dists/msvc7/agos.vcproj17
-rw-r--r--dists/msvc7/cine.vcproj17
-rw-r--r--dists/msvc7/cruise.vcproj20
-rw-r--r--dists/msvc7/drascula.vcproj15
-rw-r--r--dists/msvc7/gob.vcproj26
-rw-r--r--dists/msvc7/igor.vcproj15
-rw-r--r--dists/msvc7/kyra.vcproj23
-rw-r--r--dists/msvc7/lure.vcproj17
-rw-r--r--dists/msvc7/m4.vcproj15
-rw-r--r--dists/msvc7/made.vcproj15
-rw-r--r--dists/msvc7/parallaction.vcproj18
-rw-r--r--dists/msvc7/queen.vcproj17
-rw-r--r--dists/msvc7/saga.vcproj19
-rw-r--r--dists/msvc7/scumm.vcproj26
-rw-r--r--dists/msvc7/scummvm.vcproj66
-rw-r--r--dists/msvc7/sky.vcproj17
-rw-r--r--dists/msvc7/sword1.vcproj17
-rw-r--r--dists/msvc7/sword2.vcproj17
-rw-r--r--dists/msvc7/tinsel.vcproj349
-rw-r--r--dists/msvc7/touche.vcproj15
-rw-r--r--dists/msvc71/agi.vcproj15
-rw-r--r--dists/msvc71/agos.vcproj17
-rw-r--r--dists/msvc71/cine.vcproj17
-rw-r--r--dists/msvc71/cruise.vcproj20
-rw-r--r--dists/msvc71/drascula.vcproj15
-rw-r--r--dists/msvc71/gob.vcproj26
-rw-r--r--dists/msvc71/igor.vcproj15
-rw-r--r--dists/msvc71/kyra.vcproj23
-rw-r--r--dists/msvc71/lure.vcproj17
-rw-r--r--dists/msvc71/m4.vcproj15
-rw-r--r--dists/msvc71/made.vcproj15
-rw-r--r--dists/msvc71/parallaction.vcproj18
-rw-r--r--dists/msvc71/queen.vcproj17
-rw-r--r--dists/msvc71/saga.vcproj19
-rw-r--r--dists/msvc71/scumm.vcproj26
-rw-r--r--dists/msvc71/scummvm.vcproj66
-rw-r--r--dists/msvc71/sky.vcproj17
-rw-r--r--dists/msvc71/sword1.vcproj17
-rw-r--r--dists/msvc71/sword2.vcproj17
-rw-r--r--dists/msvc71/tinsel.vcproj363
-rw-r--r--dists/msvc71/touche.vcproj15
-rw-r--r--dists/msvc8/agi.vcproj10
-rw-r--r--dists/msvc8/agos.vcproj14
-rw-r--r--dists/msvc8/cine.vcproj14
-rw-r--r--dists/msvc8/cruise.vcproj18
-rw-r--r--dists/msvc8/drascula.vcproj10
-rw-r--r--dists/msvc8/gob.vcproj28
-rw-r--r--dists/msvc8/igor.vcproj10
-rw-r--r--dists/msvc8/kyra.vcproj22
-rw-r--r--dists/msvc8/lure.vcproj14
-rw-r--r--dists/msvc8/m4.vcproj10
-rw-r--r--dists/msvc8/made.vcproj10
-rw-r--r--dists/msvc8/parallaction.vcproj14
-rw-r--r--dists/msvc8/queen.vcproj14
-rw-r--r--dists/msvc8/saga.vcproj16
-rw-r--r--dists/msvc8/scumm.vcproj25
-rw-r--r--dists/msvc8/scummvm.vcproj78
-rw-r--r--dists/msvc8/sky.vcproj13
-rw-r--r--dists/msvc8/sword1.vcproj14
-rw-r--r--dists/msvc8/sword2.vcproj14
-rw-r--r--dists/msvc8/tinsel.vcproj12
-rw-r--r--dists/msvc8/touche.vcproj10
-rw-r--r--dists/msvc8_to_msvc7_71.bat8
-rw-r--r--dists/msvc9/agi.vcproj10
-rw-r--r--dists/msvc9/agos.vcproj14
-rw-r--r--dists/msvc9/cine.vcproj14
-rw-r--r--dists/msvc9/cruise.vcproj18
-rw-r--r--dists/msvc9/drascula.vcproj10
-rw-r--r--dists/msvc9/gob.vcproj28
-rw-r--r--dists/msvc9/igor.vcproj10
-rw-r--r--dists/msvc9/kyra.vcproj22
-rw-r--r--dists/msvc9/lure.vcproj14
-rw-r--r--dists/msvc9/m4.vcproj10
-rw-r--r--dists/msvc9/made.vcproj10
-rw-r--r--dists/msvc9/parallaction.vcproj14
-rw-r--r--dists/msvc9/queen.vcproj14
-rw-r--r--dists/msvc9/saga.vcproj16
-rw-r--r--dists/msvc9/scumm.vcproj25
-rw-r--r--dists/msvc9/scummvm.vcproj85
-rw-r--r--dists/msvc9/sky.vcproj13
-rw-r--r--dists/msvc9/sword1.vcproj14
-rw-r--r--dists/msvc9/sword2.vcproj14
-rw-r--r--dists/msvc9/tinsel.vcproj12
-rw-r--r--dists/msvc9/touche.vcproj10
-rw-r--r--dists/redhat/scummvm-tools.spec10
-rw-r--r--dists/scummvm.621
-rw-r--r--dists/scummvm.rc2
-rw-r--r--dists/scummvm.rc.in2
-rw-r--r--engines/agi/agi.cpp16
-rw-r--r--engines/agi/agi.h5
-rw-r--r--engines/agi/cycle.cpp16
-rw-r--r--engines/agi/detection.cpp67
-rw-r--r--engines/agi/loader_v3.cpp12
-rw-r--r--engines/agi/op_cmd.cpp8
-rw-r--r--engines/agi/op_test.cpp3
-rw-r--r--engines/agi/preagi.cpp1
-rw-r--r--engines/agi/preagi.h2
-rw-r--r--engines/agi/preagi_common.cpp7
-rw-r--r--engines/agi/preagi_mickey.cpp29
-rw-r--r--engines/agi/preagi_mickey.h6
-rw-r--r--engines/agi/preagi_troll.cpp11
-rw-r--r--engines/agi/preagi_winnie.cpp9
-rw-r--r--engines/agi/saveload.cpp25
-rw-r--r--engines/agi/sound.cpp18
-rw-r--r--engines/agi/wagparser.h4
-rw-r--r--engines/agos/agos.cpp43
-rw-r--r--engines/agos/agos.h3
-rw-r--r--engines/agos/animation.cpp6
-rw-r--r--engines/agos/detection.cpp41
-rw-r--r--engines/agos/event.cpp6
-rw-r--r--engines/agos/gfx.cpp2
-rw-r--r--engines/agos/input.cpp18
-rw-r--r--engines/agos/midi.cpp56
-rw-r--r--engines/agos/midi.h7
-rw-r--r--engines/agos/oracle.cpp2
-rw-r--r--engines/agos/res.cpp3
-rw-r--r--engines/agos/saveload.cpp26
-rw-r--r--engines/agos/script.cpp10
-rw-r--r--engines/agos/script_e1.cpp13
-rw-r--r--engines/agos/script_e2.cpp4
-rw-r--r--engines/agos/script_s1.cpp5
-rw-r--r--engines/agos/script_ww.cpp4
-rw-r--r--engines/agos/sound.cpp13
-rw-r--r--engines/agos/subroutine.cpp2
-rw-r--r--engines/agos/verb.cpp2
-rw-r--r--engines/agos/window.cpp4
-rw-r--r--engines/cine/anim.cpp11
-rw-r--r--engines/cine/bg.cpp10
-rw-r--r--engines/cine/cine.cpp2
-rw-r--r--engines/cine/detection.cpp53
-rw-r--r--engines/cine/gfx.cpp29
-rw-r--r--engines/cine/main_loop.cpp12
-rw-r--r--engines/cine/part.cpp31
-rw-r--r--engines/cine/prc.cpp5
-rw-r--r--engines/cine/script_fw.cpp13
-rw-r--r--engines/cine/sound.cpp14
-rw-r--r--engines/cine/texte.cpp40
-rw-r--r--engines/cine/texte.h9
-rw-r--r--engines/cine/unpack.cpp8
-rw-r--r--engines/cine/unpack.h6
-rw-r--r--engines/cine/various.cpp8
-rw-r--r--engines/cine/various.h2
-rw-r--r--engines/cruise/object.cpp4
-rw-r--r--engines/cruise/vars.h4
-rw-r--r--engines/cruise/volume.cpp4
-rw-r--r--engines/dialogs.cpp264
-rw-r--r--engines/dialogs.h77
-rw-r--r--engines/drascula/actors.cpp87
-rw-r--r--engines/drascula/animation.cpp800
-rw-r--r--engines/drascula/converse.cpp359
-rw-r--r--engines/drascula/detection.cpp2
-rw-r--r--engines/drascula/drascula.cpp163
-rw-r--r--engines/drascula/drascula.h195
-rw-r--r--engines/drascula/graphics.cpp201
-rw-r--r--engines/drascula/interface.cpp63
-rw-r--r--engines/drascula/objects.cpp30
-rw-r--r--engines/drascula/palette.cpp69
-rw-r--r--engines/drascula/rooms.cpp563
-rw-r--r--engines/drascula/saveload.cpp17
-rw-r--r--engines/drascula/sound.cpp34
-rw-r--r--engines/drascula/talk.cpp314
-rw-r--r--engines/engine.cpp62
-rw-r--r--engines/engine.h36
-rw-r--r--engines/game.cpp (renamed from base/game.cpp)49
-rw-r--r--engines/game.h (renamed from base/game.h)58
-rw-r--r--engines/gob/dataio.cpp22
-rw-r--r--engines/gob/dataio.h6
-rw-r--r--engines/gob/detection.cpp154
-rw-r--r--engines/gob/draw.cpp35
-rw-r--r--engines/gob/draw.h7
-rw-r--r--engines/gob/game_v1.cpp4
-rw-r--r--engines/gob/game_v2.cpp10
-rw-r--r--engines/gob/gob.cpp46
-rw-r--r--engines/gob/gob.h7
-rw-r--r--engines/gob/goblin.cpp74
-rw-r--r--engines/gob/inter.cpp4
-rw-r--r--engines/gob/inter.h96
-rw-r--r--engines/gob/inter_bargon.cpp6
-rw-r--r--engines/gob/inter_v1.cpp114
-rw-r--r--engines/gob/inter_v2.cpp3
-rw-r--r--engines/gob/inter_v5.cpp1040
-rw-r--r--engines/gob/inter_v6.cpp866
-rw-r--r--engines/gob/map.cpp6
-rw-r--r--engines/gob/map.h20
-rw-r--r--engines/gob/module.mk3
-rw-r--r--engines/gob/mult.cpp2
-rw-r--r--engines/gob/palanim.cpp3
-rw-r--r--engines/gob/parse.h6
-rw-r--r--engines/gob/parse_v1.cpp2
-rw-r--r--engines/gob/parse_v2.cpp229
-rw-r--r--engines/gob/saveload.cpp2
-rw-r--r--engines/gob/sound/sound.cpp2
-rw-r--r--engines/gob/util.cpp10
-rw-r--r--engines/gob/video.h9
-rw-r--r--engines/gob/video_v6.cpp69
-rw-r--r--engines/gob/videoplayer.cpp3
-rw-r--r--engines/igor/parts/part_22.cpp6
-rw-r--r--engines/kyra/detection.cpp96
-rw-r--r--engines/kyra/gui.cpp5
-rw-r--r--engines/kyra/gui.h4
-rw-r--r--engines/kyra/gui_hof.cpp12
-rw-r--r--engines/kyra/gui_hof.h2
-rw-r--r--engines/kyra/gui_lok.cpp38
-rw-r--r--engines/kyra/gui_lok.h2
-rw-r--r--engines/kyra/gui_mr.cpp12
-rw-r--r--engines/kyra/gui_mr.h2
-rw-r--r--engines/kyra/gui_v2.cpp25
-rw-r--r--engines/kyra/gui_v2.h1
-rw-r--r--engines/kyra/kyra_hof.cpp26
-rw-r--r--engines/kyra/kyra_hof.h2
-rw-r--r--engines/kyra/kyra_lok.cpp31
-rw-r--r--engines/kyra/kyra_lok.h2
-rw-r--r--engines/kyra/kyra_mr.cpp15
-rw-r--r--engines/kyra/kyra_mr.h2
-rw-r--r--engines/kyra/kyra_v1.cpp24
-rw-r--r--engines/kyra/kyra_v1.h20
-rw-r--r--engines/kyra/kyra_v2.cpp10
-rw-r--r--engines/kyra/kyra_v2.h2
-rw-r--r--engines/kyra/lol.cpp74
-rw-r--r--engines/kyra/lol.h3
-rw-r--r--engines/kyra/module.mk1
-rw-r--r--engines/kyra/resource.cpp1406
-rw-r--r--engines/kyra/resource.h97
-rw-r--r--engines/kyra/resource_intern.cpp1072
-rw-r--r--engines/kyra/resource_intern.h132
-rw-r--r--engines/kyra/saveload.cpp49
-rw-r--r--engines/kyra/saveload_hof.cpp10
-rw-r--r--engines/kyra/saveload_lok.cpp12
-rw-r--r--engines/kyra/saveload_mr.cpp10
-rw-r--r--engines/kyra/scene_hof.cpp4
-rw-r--r--engines/kyra/scene_mr.cpp2
-rw-r--r--engines/kyra/screen.cpp48
-rw-r--r--engines/kyra/screen.h5
-rw-r--r--engines/kyra/screen_lok.cpp18
-rw-r--r--engines/kyra/screen_lok.h1
-rw-r--r--engines/kyra/script.cpp48
-rw-r--r--engines/kyra/script.h2
-rw-r--r--engines/kyra/script_lok.cpp3
-rw-r--r--engines/kyra/script_mr.cpp4
-rw-r--r--engines/kyra/sequences_hof.cpp25
-rw-r--r--engines/kyra/sequences_lok.cpp17
-rw-r--r--engines/kyra/sound.h5
-rw-r--r--engines/kyra/sound_towns.cpp2812
-rw-r--r--engines/kyra/sprites.cpp1
-rw-r--r--engines/kyra/staticres.cpp288
-rw-r--r--engines/kyra/text.cpp1
-rw-r--r--engines/kyra/text_hof.cpp12
-rw-r--r--engines/kyra/text_lok.cpp2
-rw-r--r--engines/kyra/text_mr.cpp10
-rw-r--r--engines/kyra/timer_mr.cpp2
-rw-r--r--engines/kyra/vqa.cpp143
-rw-r--r--engines/kyra/vqa.h4
-rw-r--r--engines/lure/animseq.cpp14
-rw-r--r--engines/lure/detection.cpp50
-rw-r--r--engines/lure/events.cpp16
-rw-r--r--engines/lure/events.h2
-rw-r--r--engines/lure/fights.cpp8
-rw-r--r--engines/lure/game.cpp29
-rw-r--r--engines/lure/game.h5
-rw-r--r--engines/lure/intro.cpp7
-rw-r--r--engines/lure/lure.cpp71
-rw-r--r--engines/lure/lure.h6
-rw-r--r--engines/lure/menu.cpp6
-rw-r--r--engines/lure/scripts.cpp6
-rw-r--r--engines/lure/sound.cpp32
-rw-r--r--engines/lure/sound.h4
-rw-r--r--engines/lure/surface.cpp14
-rw-r--r--engines/m4/converse.cpp45
-rw-r--r--engines/m4/globals.cpp14
-rw-r--r--engines/m4/m4.cpp6
-rw-r--r--engines/m4/mads_anim.cpp14
-rw-r--r--engines/m4/midi.cpp2
-rw-r--r--engines/m4/resource.cpp4
-rw-r--r--engines/made/detection.cpp4
-rw-r--r--engines/made/music.cpp2
-rw-r--r--engines/made/pmvplayer.cpp4
-rw-r--r--engines/made/redreader.cpp4
-rw-r--r--engines/made/screenfx.cpp2
-rw-r--r--engines/metaengine.h103
-rw-r--r--engines/module.mk4
-rw-r--r--engines/parallaction/balloons.cpp107
-rw-r--r--engines/parallaction/callables_ns.cpp11
-rw-r--r--engines/parallaction/detection.cpp48
-rw-r--r--engines/parallaction/dialogue.cpp12
-rw-r--r--engines/parallaction/disk.h50
-rw-r--r--engines/parallaction/disk_br.cpp48
-rw-r--r--engines/parallaction/disk_ns.cpp26
-rw-r--r--engines/parallaction/exec_br.cpp23
-rw-r--r--engines/parallaction/exec_ns.cpp324
-rw-r--r--engines/parallaction/gfxbase.cpp190
-rw-r--r--engines/parallaction/graphics.cpp88
-rw-r--r--engines/parallaction/graphics.h28
-rw-r--r--engines/parallaction/gui_br.cpp67
-rw-r--r--engines/parallaction/gui_ns.cpp91
-rw-r--r--engines/parallaction/input.cpp188
-rw-r--r--engines/parallaction/input.h45
-rw-r--r--engines/parallaction/objects.cpp2
-rw-r--r--engines/parallaction/objects.h17
-rw-r--r--engines/parallaction/parallaction.cpp440
-rw-r--r--engines/parallaction/parallaction.h488
-rw-r--r--engines/parallaction/parallaction_br.cpp221
-rw-r--r--engines/parallaction/parallaction_ns.cpp114
-rw-r--r--engines/parallaction/parser.cpp29
-rw-r--r--engines/parallaction/parser.h3
-rw-r--r--engines/parallaction/parser_br.cpp2
-rw-r--r--engines/parallaction/saveload.cpp171
-rw-r--r--engines/parallaction/saveload.h96
-rw-r--r--engines/parallaction/staticres.cpp15
-rw-r--r--engines/queen/input.cpp5
-rw-r--r--engines/queen/journal.cpp10
-rw-r--r--engines/queen/logic.cpp10
-rw-r--r--engines/queen/midiadlib.cpp2
-rw-r--r--engines/queen/queen.cpp69
-rw-r--r--engines/queen/queen.h5
-rw-r--r--engines/queen/resource.cpp2
-rw-r--r--engines/queen/sound.cpp24
-rw-r--r--engines/queen/talk.cpp2
-rw-r--r--engines/saga/animation.cpp2
-rw-r--r--engines/saga/detection.cpp51
-rw-r--r--engines/saga/input.cpp3
-rw-r--r--engines/saga/interface.cpp29
-rw-r--r--engines/saga/introproc_ihnm.cpp10
-rw-r--r--engines/saga/music.cpp22
-rw-r--r--engines/saga/music.h3
-rw-r--r--engines/saga/rscfile.cpp157
-rw-r--r--engines/saga/saga.cpp62
-rw-r--r--engines/saga/saga.h6
-rw-r--r--engines/saga/scene.cpp2
-rw-r--r--engines/saga/sfuncs.cpp43
-rw-r--r--engines/saga/sndres.cpp61
-rw-r--r--engines/saga/sndres.h1
-rw-r--r--engines/saga/sound.cpp47
-rw-r--r--engines/saga/sound.h7
-rw-r--r--engines/saga/sprite.cpp4
-rw-r--r--engines/scumm/detection.cpp97
-rw-r--r--engines/scumm/detection_tables.h2
-rw-r--r--engines/scumm/dialogs.cpp17
-rw-r--r--engines/scumm/dialogs.h6
-rw-r--r--engines/scumm/file.cpp22
-rw-r--r--engines/scumm/file.h39
-rw-r--r--engines/scumm/file_nes.cpp6
-rw-r--r--engines/scumm/file_nes.h8
-rw-r--r--engines/scumm/gfx.cpp57
-rw-r--r--engines/scumm/gfx.h3
-rw-r--r--engines/scumm/gfxARM.s79
-rw-r--r--engines/scumm/he/cup_player_he.cpp6
-rw-r--r--engines/scumm/he/intern_he.h6
-rw-r--r--engines/scumm/he/script_v100he.cpp84
-rw-r--r--engines/scumm/he/script_v70he.cpp5
-rw-r--r--engines/scumm/he/script_v72he.cpp18
-rw-r--r--engines/scumm/he/script_v90he.cpp298
-rw-r--r--engines/scumm/input.cpp10
-rw-r--r--engines/scumm/insane/insane.cpp25
-rw-r--r--engines/scumm/insane/insane.h17
-rw-r--r--engines/scumm/insane/insane_iact.cpp15
-rw-r--r--engines/scumm/module.mk2
-rw-r--r--engines/scumm/resource.cpp8
-rw-r--r--engines/scumm/resource_v4.cpp2
-rw-r--r--engines/scumm/saveload.cpp117
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script.cpp4
-rw-r--r--engines/scumm/script_v5.cpp2
-rw-r--r--engines/scumm/script_v6.cpp4
-rw-r--r--engines/scumm/script_v8.cpp8
-rw-r--r--engines/scumm/scumm-md5.h25
-rw-r--r--engines/scumm/scumm.cpp88
-rw-r--r--engines/scumm/scumm.h36
-rw-r--r--engines/scumm/smush/channel.h15
-rw-r--r--engines/scumm/smush/chunk.cpp168
-rw-r--r--engines/scumm/smush/imuse_channel.cpp48
-rw-r--r--engines/scumm/smush/saud_channel.cpp24
-rw-r--r--engines/scumm/smush/smush_player.cpp228
-rw-r--r--engines/scumm/smush/smush_player.h35
-rw-r--r--engines/scumm/thumbnail.cpp130
-rw-r--r--engines/sky/control.cpp23
-rw-r--r--engines/sky/intro.cpp7
-rw-r--r--engines/sky/intro.h1
-rw-r--r--engines/sky/logic.cpp2
-rw-r--r--engines/sky/mouse.cpp1
-rw-r--r--engines/sky/sky.cpp41
-rw-r--r--engines/sky/sky.h1
-rw-r--r--engines/sky/skydefs.h16
-rw-r--r--engines/sword1/animation.cpp5
-rw-r--r--engines/sword1/control.cpp12
-rw-r--r--engines/sword1/control.h1
-rw-r--r--engines/sword1/credits.cpp17
-rw-r--r--engines/sword1/logic.cpp2
-rw-r--r--engines/sword1/music.cpp2
-rw-r--r--engines/sword1/sword1.cpp203
-rw-r--r--engines/sword1/sword1.h2
-rw-r--r--engines/sword2/animation.cpp4
-rw-r--r--engines/sword2/controls.cpp8
-rw-r--r--engines/sword2/function.cpp2
-rw-r--r--engines/sword2/palette.cpp2
-rw-r--r--engines/sword2/resman.cpp4
-rw-r--r--engines/sword2/screen.cpp10
-rw-r--r--engines/sword2/sound.h2
-rw-r--r--engines/sword2/startup.cpp18
-rw-r--r--engines/sword2/sword2.cpp91
-rw-r--r--engines/sword2/sword2.h3
-rw-r--r--engines/tinsel/config.cpp111
-rw-r--r--engines/tinsel/config.h22
-rw-r--r--engines/tinsel/cursor.cpp7
-rw-r--r--engines/tinsel/detection.cpp180
-rw-r--r--engines/tinsel/dw.h7
-rw-r--r--engines/tinsel/inventory.cpp273
-rw-r--r--engines/tinsel/music.cpp8
-rw-r--r--engines/tinsel/music.h2
-rw-r--r--engines/tinsel/saveload.cpp22
-rw-r--r--engines/tinsel/sound.cpp4
-rw-r--r--engines/tinsel/sound.h3
-rw-r--r--engines/tinsel/tinlib.cpp12
-rw-r--r--engines/tinsel/tinsel.cpp49
-rw-r--r--engines/tinsel/tinsel.h18
-rw-r--r--engines/touche/detection.cpp73
-rw-r--r--engines/touche/menu.cpp10
-rw-r--r--engines/touche/opcodes.cpp4
-rw-r--r--engines/touche/saveload.cpp7
-rw-r--r--engines/touche/touche.cpp50
-rw-r--r--engines/touche/touche.h5
-rw-r--r--graphics/dxa_player.cpp1
-rw-r--r--graphics/dxa_player.h6
-rw-r--r--graphics/font.cpp1
-rw-r--r--graphics/iff.cpp9
-rw-r--r--graphics/module.mk2
-rw-r--r--graphics/scaler.h16
-rw-r--r--graphics/scaler/thumbnail_intern.cpp (renamed from graphics/scaler/thumbnail.cpp)91
-rw-r--r--graphics/surface.cpp5
-rw-r--r--graphics/surface.h19
-rw-r--r--graphics/thumbnail.cpp174
-rw-r--r--graphics/thumbnail.h69
-rw-r--r--gui/ThemeEngine.cpp10
-rw-r--r--gui/about.cpp2
-rw-r--r--gui/browser.cpp13
-rw-r--r--gui/browser.h10
-rw-r--r--gui/credits.h4
-rw-r--r--gui/launcher.cpp354
-rw-r--r--gui/launcher.h10
-rw-r--r--gui/massadd.cpp10
-rw-r--r--gui/massadd.h4
-rw-r--r--gui/newgui.cpp10
-rw-r--r--gui/options.cpp10
-rw-r--r--gui/theme.cpp82
-rw-r--r--gui/theme.h7
-rw-r--r--gui/themebrowser.cpp38
-rw-r--r--gui/themebrowser.h2
-rw-r--r--gui/themes/default.inc14
-rw-r--r--gui/themes/scummclassic.zipbin40156 -> 42002 bytes
-rw-r--r--gui/themes/scummclassic/classic_layout.stx7
-rw-r--r--gui/themes/scummclassic/classic_layout_320.stx7
-rw-r--r--gui/themes/scummodern.zipbin123105 -> 125107 bytes
-rw-r--r--gui/themes/scummodern/scummodern_layout.stx7
-rw-r--r--gui/themes/scummodern/scummodern_layout_320.stx7
-rw-r--r--gui/widget.cpp3
-rw-r--r--ports.mk2
-rw-r--r--sound/adpcm.cpp2
-rw-r--r--sound/audiocd.cpp1
-rw-r--r--sound/flac.cpp9
-rw-r--r--sound/flac.h1
-rw-r--r--sound/mididrv.cpp11
-rw-r--r--sound/mididrv.h4
-rw-r--r--sound/mixer.cpp1
-rw-r--r--sound/mods/infogrames.cpp25
-rw-r--r--sound/mods/infogrames.h17
-rw-r--r--sound/mp3.cpp2
-rw-r--r--sound/mp3.h1
-rw-r--r--sound/softsynth/mt32.cpp7
-rw-r--r--sound/softsynth/mt32/mt32_file.cpp4
-rw-r--r--sound/softsynth/mt32/mt32_file.h2
-rw-r--r--sound/softsynth/mt32/partial.cpp2
-rw-r--r--sound/softsynth/mt32/synth.cpp2
-rw-r--r--sound/softsynth/mt32/tables.cpp2
-rw-r--r--sound/vorbis.cpp2
-rw-r--r--sound/vorbis.h1
-rw-r--r--sound/wave.cpp4
-rw-r--r--test/common/bufferedreadstream.h11
-rw-r--r--test/common/bufferedseekablereadstream.h23
-rw-r--r--test/common/hashmap.h51
-rw-r--r--test/common/queue.h80
-rw-r--r--test/common/seekablesubreadstream.h21
-rw-r--r--test/common/str.h77
-rw-r--r--test/common/stream.h46
-rw-r--r--test/common/subreadstream.h2
-rw-r--r--tools/create_drascula/create_drascula.cpp12
-rw-r--r--tools/create_drascula/create_drascula.h34
-rw-r--r--tools/create_drascula/staticdata.h1626
-rw-r--r--tools/create_kyradat/create_kyradat.cpp2
-rw-r--r--tools/create_kyradat/hof_floppy.h22
-rw-r--r--tools/create_kyradat/pak.h2
-rwxr-xr-xtools/credits.pl3
-rw-r--r--tools/md5table.c1
-rw-r--r--tools/scumm-md5.txt23
662 files changed, 24479 insertions, 13577 deletions
diff --git a/AUTHORS b/AUTHORS
index 2272c20781..45cebf57c6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -168,9 +168,12 @@ ScummVM Team
Johannes Schickel
Miscellaneous:
- David Corrales-Lopez - Filesystem access improvements
+ David Corrales-Lopez - Filesystem access improvements (GSoC 2007
+ task)
Jerome Fisher - MT-32 emulator
Jochen Hoenicke - Speaker & PCjr sound support, Adlib work
+ Chris Page - Return to launcher, savestate improvements,
+ leak fixes, ... (GSoC 2008 task)
Robin Watts - ARM assembly routines for nice speedups on
several ports; improvements to the sound mixer
diff --git a/NEWS b/NEWS
index eba57b9b43..113ee4670a 100644
--- a/NEWS
+++ b/NEWS
@@ -2,10 +2,22 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
http://scummvm.sourceforge.net/daily/ChangeLog
0.13.0 (????-??-??)
+ General:
+ - Added MIDI driver for Atari ST / FreeMint.
+ - Added a 'Load' button to the Launcher (not supported by all engines).
+ - Added a new global main menu (GMM) dialog usable from all engines.
+ - Added the ability to return to the launcher from running games (via the GMM).
+
New Games:
- Added support for Discworld.
-0.12.0 (????-??-??)
+ KYRA:
+ - Added support for Auto-save feature.
+
+ SCUMM:
+ - Fixed a long-time bug which caused talkspeed and talkdelay to be mixed up.
+
+0.12.0 (2008-08-31)
New Games:
- Added support for The Legend of Kyrandia: Book Two: Hand of Fate.
- Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge.
diff --git a/README b/README
index 6f59e172bc..cd19d97bbd 100644
--- a/README
+++ b/README
@@ -39,10 +39,12 @@ Table of Contents:
* 5.1 Command Line Options
* 5.2 Language Options
* 5.3 Graphics Filters
- * 5.4 Hotkeys
+ * 5.4 Global Menu
+ * 5.5 Hotkeys
6.0) Savegames
* 6.1 Autosaves
* 6.2 Converting savegames
+ * 6.3 Viewing/Loading savegames from the command line
7.0) Music and Sound
* 7.1 Adlib emulation
* 7.2 FluidSynth MIDI emulation
@@ -182,17 +184,23 @@ GOB Games by Coktel Vision:
Gobliiins [gob1]
Gobliins 2 [gob2]
Goblins 3 [gob3]
+ Lost in Time [lostintime]
+ The Bizarre Adventures of Woodruff
+ and the Schnibble [woodruff]
Ween: The Prophecy [ween]
Other Games:
Beneath a Steel Sky [sky]
Broken Sword 1: The Shadow of the Templars [sword1]
Broken Sword 2: The Smoking Mirror [sword2]
+ Drascula: The Vampire Strikes Back [drascula]
Flight of the Amazon Queen [queen]
Future Wars [fw]
Inherit the Earth: Quest for the Orb [ite]
Nippon Safes Inc. [nippon]
The Legend of Kyrandia [kyra1]
+ The Legend of Kyrandia: The Hand of Fate [kyra2]
+ The Legend of Kyrandia: Malcolm's Revenge [kyra3]
Touche: The Adventures of the Fifth
Musketeer [touche]
@@ -781,6 +789,7 @@ arguments -- see the next section.
-h, --help Display a brief help text and exit
-z, --list-games Display list of supported games and exit
-t, --list-targets Display list of configured targets and exit
+ --list-saves=TARGET Display a list of savegames for the game (TARGET) specified
-c, --config=CONFIG Use alternate configuration file
-p, --path=PATH Path to where the game is installed
@@ -968,7 +977,38 @@ Likewise, games that originally were using 640x480 (such as COMI or Broken Sword
will be scaled to 1280x960 and 1920x1440.
-5.4) Hot Keys:
+5.4) Global Menu:
+---- ------------
+
+The Global Menu is a general menu which is available to all of the game engines
+by pressing F6. From this menu there are the following buttons: Resume,
+Options, About, Return to Launcher, and Quit. Selecting 'Options' will display
+a dialog where basic audio settings, such as volume levels, can be adjusted.
+Selecting 'Return to Launcher' will close the current game and return the user
+back to the ScummVM Launcher, where another game may be selected to play.
+
+Note: Returning to the Launcher is not supported by all of the engines,
+ and the button will be disabled in the Global Menu if it is not supported.
+
+Engines which currently support Returning to the Launcher are:
+
+ AGI
+ AGOS
+ CINE
+ GOB
+ KYRA
+ LURE
+ PARALLACTION
+ QUEEN
+ SAGA
+ SCUMM
+ SKY
+ SWORD1
+ SWORD2
+ TOUCHE
+
+
+5.5) Hot Keys:
---- ---------
TODO
TODO: Rework this section to clearly state which hotkeys are implemented in *all*
@@ -982,6 +1022,7 @@ ScummVM supports various in-game hotkeys. They differ between SCUMM games and
other games.
Common:
+ F6 - Displays the Global Menu
Cmd-q - Quit (Mac OS X)
Ctrl-q - Quit (other unices including Linux)
Ctrl-z OR Alt-x - Quit (other platforms)
@@ -1138,45 +1179,93 @@ The platforms that currently have a different default directory are:
6.1) Autosaves:
---- ----------
-For some games (namely "Beneath a Steel Sky", "Flight of the Amazon
-Queen" and all SCUMM games), ScummVM will by default automatically
-save the current state every five minutes (adjustable via the
-"autosave_period" config setting). For the SCUMM engine, it will save
-in Slot 0. This savestate can then be loaded again via Ctrl-0, or the
-F5 menu.
+For some games, (namely "Beneath a Steel Sky", "Flight of the Amazon Queen",
+all AGI games, and all SCUMM games), ScummVM will by default automatically
+save the current state every five minutes (adjustable via the "autosave_period"
+config setting). For the AGI and SCUMM engines, it will save in Slot 0. For the
+SCUMM engine, this savestate can then be loaded again via Ctrl-0, or the F5
+menu.
6.2) Converting Savegames:
----- ----------
-Using savegames from original versions, isn't supported by all game engines. Only
-the following games, can use savedgames from their original versions.
+---- ---------------------
+Using savegames from original versions, isn't supported by all game engines.
+Only the following games, can use savegames from their original versions.
Elvira 1
- - Add 8 bytes (savedgame name) to the start of the savegame file
- - Rename the savedgame to 'elvira1.xxx'
+ - Add 8 bytes (savegame name) to the start of the savegame file
+ - Rename the savegame to 'elvira1.xxx'
Elvira 2
- - Add 8 bytes (savedgame name) to the start of the savegame file
- - Rename the savedgame to 'elvira2-pc.xxx' (DOS version) or
+ - Add 8 bytes (savegame name) to the start of the savegame file
+ - Rename the savegame to 'elvira2-pc.xxx' (DOS version) or
'elvira2.xxx' (Other versions)
Waxworks
- - Add 8 bytes (savedgame name) to the start of the savegame file
- - Rename the savedgame to 'waxworks-pc.xxx' (DOS version) or
+ - Add 8 bytes (savegame name) to the start of the savegame file
+ - Rename the savegame to 'waxworks-pc.xxx' (DOS version) or
'waxworks.xxx' (Other versions)
Simon the Sorcerer 1
- - Rename the savedgame to 'simon1.xxx'
+ - Rename the savegame to 'simon1.xxx'
Simon the Sorcerer 1
- - Rename the savedgame to 'simon2.xxx'
+ - Rename the savegame to 'simon2.xxx'
The Feeble Files
- - Rename the savedgame to 'feeble.xxx'
+ - Rename the savegame to 'feeble.xxx'
Where 'xxx' is exact the saved game slot (ie 001) under ScummVM
+6.3) Viewing/Loading savegames from the command line:
+---- ------------------------------------------------
+
+--list-saves:
+
+ This switch may be used to display a list of the current savegames
+ of the specified target game and their corresponding save slots.
+
+ Usage: --list-saves=[TARGET], where [TARGET] is the target game.
+
+ Engines which currently support --list-saves are:
+
+ AGI
+ AGOS
+ CINE
+ KYRA
+ LURE
+ PARALLACTION
+ QUEEN
+ SAGA
+ SCUMM
+ SKY
+ SWORD1
+ SWORD2
+ TOUCHE
+
+--save-slot/-x:
+
+ This switch may be used to load a savegame directly from the command line.
+
+ Usage: --save-slot[SLOT] or -x[SLOT], where [SLOT] is the save slot number.
+
+ Engines which currently support --save-slot/-x are:
+
+ AGI
+ CINE
+ KYRA
+ LURE
+ PARALLACTION
+ QUEEN
+ SAGA
+ SCUMM
+ SKY
+ SWORD1
+ SWORD2
+ TOUCHE
+
+
7.0) Music and Sound:
---- ----------------
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 0caba25792..c503e6a536 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -93,7 +93,8 @@ DefaultEventManager::DefaultEventManager(OSystem *boss) :
_boss(boss),
_buttonState(0),
_modifierState(0),
- _shouldQuit(false) {
+ _shouldQuit(false),
+ _shouldRTL(false) {
assert(_boss);
@@ -200,6 +201,9 @@ DefaultEventManager::~DefaultEventManager() {
_boss->unlockMutex(_timeMutex);
_boss->unlockMutex(_recorderMutex);
+ if (!artificialEventQueue.empty())
+ artificialEventQueue.clear();
+
if (_playbackFile != NULL) {
delete _playbackFile;
}
@@ -349,7 +353,11 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
uint32 time = _boss->getMillis();
bool result;
- result = _boss->pollEvent(event);
+ if (!artificialEventQueue.empty()) {
+ event = artificialEventQueue.pop();
+ result = true;
+ } else
+ result = _boss->pollEvent(event);
if (_recordMode != kPassthrough) {
@@ -375,7 +383,6 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
_modifierState = event.kbd.flags;
-
// init continuous event stream
// not done on PalmOS because keyboard is emulated and keyup is not generated
#if !defined(PALMOS_MODE)
@@ -384,7 +391,41 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_currentKeyDown.flags = event.kbd.flags;
_keyRepeatTime = time + kKeyRepeatInitialDelay;
#endif
+ // Global Main Menu
+ // FIXME: F6 is not the best trigger, it conflicts with some games!!!
+ if (event.kbd.keycode == Common::KEYCODE_F6) {
+ if (g_engine && !g_engine->isPaused()) {
+ Common::Event menuEvent;
+ menuEvent.type = Common::EVENT_MAINMENU;
+
+ // FIXME: GSoC RTL branch passes the F6 key event to the
+ // engine, and also enqueues a EVENT_MAINMENU. For now,
+ // we just drop the key event and return an EVENT_MAINMENU
+ // instead. This way, we don't have to add special cases
+ // to engines (like it was the case for LURE in the RTL branch).
+ //
+ // However, this has other consequences, possibly negative ones.
+ // Like, what happens with key repeat for the trigger key?
+
+ //pushEvent(menuEvent);
+ event = menuEvent;
+
+ // FIXME: Since now we do not push another MAINMENU event onto
+ // our event stack, the GMM would never open, so we have to do
+ // that here. Of course when the engine would handle MAINMENU
+ // as an event now and open up the GMM itself it would open the
+ // menu twice.
+ if (g_engine && !g_engine->isPaused())
+ g_engine->mainMenuDialog();
+
+ if (_shouldQuit)
+ event.type = Common::EVENT_QUIT;
+ else if (_shouldRTL)
+ event.type = Common::EVENT_RTL;
+ }
+ }
break;
+
case Common::EVENT_KEYUP:
_modifierState = event.kbd.flags;
if (event.kbd.keycode == _currentKeyDown.keycode) {
@@ -401,6 +442,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_mousePos = event.mouse;
_buttonState |= LBUTTON;
break;
+
case Common::EVENT_LBUTTONUP:
_mousePos = event.mouse;
_buttonState &= ~LBUTTON;
@@ -410,11 +452,26 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_mousePos = event.mouse;
_buttonState |= RBUTTON;
break;
+
case Common::EVENT_RBUTTONUP:
_mousePos = event.mouse;
_buttonState &= ~RBUTTON;
break;
+ case Common::EVENT_MAINMENU:
+ if (g_engine && !g_engine->isPaused())
+ g_engine->mainMenuDialog();
+
+ if (_shouldQuit)
+ event.type = Common::EVENT_QUIT;
+ else if (_shouldRTL)
+ event.type = Common::EVENT_RTL;
+ break;
+
+ case Common::EVENT_RTL:
+ _shouldRTL = true;
+ break;
+
case Common::EVENT_QUIT:
if (ConfMan.getBool("confirm_exit")) {
if (g_engine)
@@ -425,6 +482,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
g_engine->pauseEngine(false);
} else
_shouldQuit = true;
+
break;
default:
@@ -447,4 +505,14 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
return result;
}
+void DefaultEventManager::pushEvent(Common::Event event) {
+
+ // If already received an EVENT_QUIT, don't add another one
+ if (event.type == Common::EVENT_QUIT) {
+ if (!_shouldQuit)
+ artificialEventQueue.push(event);
+ } else
+ artificialEventQueue.push(event);
+}
+
#endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h
index 98dcd4b3de..b2cd1354cc 100644
--- a/backends/events/default/default-events.h
+++ b/backends/events/default/default-events.h
@@ -48,6 +48,7 @@ class DefaultEventManager : public Common::EventManager {
int _buttonState;
int _modifierState;
bool _shouldQuit;
+ bool _shouldRTL;
class RandomSourceRecord {
public:
@@ -107,6 +108,7 @@ public:
~DefaultEventManager();
virtual bool pollEvent(Common::Event &event);
+ virtual void pushEvent(Common::Event event);
virtual void registerRandomSource(Common::RandomSource &rnd, const char *name);
virtual void processMillis(uint32 &millis);
@@ -114,6 +116,8 @@ public:
virtual int getButtonState() const { return _buttonState; }
virtual int getModifierState() const { return _modifierState; }
virtual int shouldQuit() const { return _shouldQuit; }
+ virtual int shouldRTL() const { return _shouldRTL; }
+ virtual void resetRTL() { _shouldRTL = false; }
};
#endif
diff --git a/backends/fs/abstract-fs.cpp b/backends/fs/abstract-fs.cpp
new file mode 100644
index 0000000000..6daad7152a
--- /dev/null
+++ b/backends/fs/abstract-fs.cpp
@@ -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$
+ */
+
+#include "backends/fs/abstract-fs.h"
+
+const char *AbstractFilesystemNode::lastPathComponent(const Common::String &str, const char sep) {
+ // TODO: Get rid of this eventually! Use Common::lastPathComponent instead
+ if(str.empty())
+ return "";
+
+ const char *start = str.c_str();
+ const char *cur = start + str.size() - 2;
+
+ while (cur >= start && *cur != sep) {
+ --cur;
+ }
+
+ return cur + 1;
+}
diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h
index 97de40a2fc..b3a652f2ae 100644
--- a/backends/fs/abstract-fs.h
+++ b/backends/fs/abstract-fs.h
@@ -43,22 +43,21 @@ typedef Common::Array<AbstractFilesystemNode *> AbstractFSList;
*/
class AbstractFilesystemNode {
protected:
- friend class FilesystemNode;
- typedef Common::String String;
- typedef FilesystemNode::ListMode ListMode;
+ friend class Common::FilesystemNode;
+ typedef Common::FilesystemNode::ListMode ListMode;
/**
- * Returns the child node with the given name. If no child with this name
- * exists, returns 0. When called on a non-directory node, it should
- * handle this gracefully by returning 0.
+ * Returns the child node with the given name. When called on a non-directory
+ * node, it should handle this gracefully by returning 0.
+ * When called with a name not matching any of the files/dirs contained in this
+ * directory, a valid node shold be returned, which returns 'false' upon calling
+ * the exists() method. The idea is that this node can then still can be used to
+ * create a new file via the openForWriting() method.
*
* Example:
* Calling getChild() for a node with path "/foo/bar" using name="file.txt",
* would produce a new node with "/foo/bar/file.txt" as path.
*
- * @note This function will append a separator char (\ or /) to the end of the
- * path if needed.
- *
* @note Handling calls on non-dir nodes gracefully makes it possible to
* switch to a lazy type detection scheme in the future.
*
@@ -72,6 +71,19 @@ protected:
*/
virtual AbstractFilesystemNode *getParent() const = 0;
+ /**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @param sep character used to separate path components
+ * @return Pointer to the first char of the last component inside str.
+ */
+ static const char *lastPathComponent(const Common::String &str, const char sep);
+
public:
/**
* Destructor.
@@ -149,9 +161,26 @@ public:
*/
virtual bool isWritable() const = 0;
- /* TODO:
- bool isFile();
- */
+
+ /**
+ * Creates a SeekableReadStream instance corresponding to the file
+ * referred by this node. This assumes that the node actually refers
+ * to a readable file. If this is not the case, 0 is returned.
+ *
+ * @return pointer to the stream object, 0 in case of a failure
+ */
+ virtual Common::SeekableReadStream *openForReading() = 0;
+
+ /**
+ * Creates a WriteStream instance corresponding to the file
+ * referred by this node. This assumes that the node actually refers
+ * to a readable file. If this is not the case, 0 is returned.
+ *
+ * @return pointer to the stream object, 0 in case of a failure
+ */
+ virtual Common::WriteStream *openForWriting() = 0;
};
+
+
#endif //BACKENDS_ABSTRACT_FS_H
diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.cpp b/backends/fs/amigaos4/amigaos4-fs-factory.cpp
index af843b7c78..2b0b2f1908 100644
--- a/backends/fs/amigaos4/amigaos4-fs-factory.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs-factory.cpp
@@ -26,8 +26,6 @@
#include "backends/fs/amigaos4/amigaos4-fs-factory.h"
#include "backends/fs/amigaos4/amigaos4-fs.cpp"
-DECLARE_SINGLETON(AmigaOSFilesystemFactory);
-
AbstractFilesystemNode *AmigaOSFilesystemFactory::makeRootFileNode() const {
return new AmigaOSFilesystemNode();
}
@@ -36,7 +34,7 @@ AbstractFilesystemNode *AmigaOSFilesystemFactory::makeCurrentDirectoryFileNode()
return new AmigaOSFilesystemNode();
}
-AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new AmigaOSFilesystemNode(path);
}
#endif
diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.h b/backends/fs/amigaos4/amigaos4-fs-factory.h
index 58a7dcd372..03af6e95b9 100644
--- a/backends/fs/amigaos4/amigaos4-fs-factory.h
+++ b/backends/fs/amigaos4/amigaos4-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef AMIGAOS_FILESYSTEM_FACTORY_H
#define AMIGAOS_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class AmigaOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<AmigaOSFilesystemFactory> {
+class AmigaOSFilesystemFactory : public FilesystemFactory {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- AmigaOSFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*AMIGAOS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
index 5bf57ddf34..d517121dc0 100644
--- a/backends/fs/amigaos4/amigaos4-fs.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -36,8 +36,8 @@
#endif
#include "common/util.h"
-#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#define ENTER() /* debug(6, "Enter") */
#define LEAVE() /* debug(6, "Leave") */
@@ -52,8 +52,8 @@ const uint32 kExAllBufferSize = 40960; // TODO: is this okay for sure?
class AmigaOSFilesystemNode : public AbstractFilesystemNode {
protected:
BPTR _pFileLock;
- String _sDisplayName;
- String _sPath;
+ Common::String _sDisplayName;
+ Common::String _sPath;
bool _bIsDirectory;
bool _bIsValid;
@@ -74,9 +74,9 @@ public:
/**
* Creates a AmigaOSFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- AmigaOSFilesystemNode(const String &p);
+ AmigaOSFilesystemNode(const Common::String &p);
/**
* FIXME: document this constructor.
@@ -96,17 +96,20 @@ public:
virtual ~AmigaOSFilesystemNode();
virtual bool exists() const;
- virtual String getDisplayName() const { return _sDisplayName; };
- virtual String getName() const { return _sDisplayName; };
- virtual String getPath() const { return _sPath; };
+ virtual Common::String getDisplayName() const { return _sDisplayName; };
+ virtual Common::String getName() const { return _sDisplayName; };
+ virtual Common::String getPath() const { return _sPath; };
virtual bool isDirectory() const { return _bIsDirectory; };
virtual bool isReadable() const;
virtual bool isWritable() const;
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
/**
* Creates a list with all the volumes present in the root node.
*/
@@ -116,7 +119,7 @@ public:
/**
* Returns the last component of a given path.
*
- * @param str String containing the path.
+ * @param str Common::String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
@@ -148,10 +151,10 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
LEAVE();
}
-AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
+AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) {
ENTER();
- int len = 0, offset = p.size();
+ int offset = p.size();
//assert(offset > 0);
@@ -161,7 +164,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
}
_sPath = p;
- _sDisplayName = lastPathComponent(_sPath);
+ _sDisplayName = ::lastPathComponent(_sPath);
_pFileLock = 0;
_bIsDirectory = false;
@@ -299,14 +302,14 @@ bool AmigaOSFilesystemNode::exists() const {
return nodeExists;
}
-AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const Common::String &n) const {
ENTER();
if (!_bIsDirectory) {
debug(6, "Not a directory");
return 0;
}
- String newPath(_sPath);
+ Common::String newPath(_sPath);
if (_sPath.lastChar() != '/')
newPath += '/';
@@ -368,10 +371,10 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
struct ExAllData *ead = data;
do {
- if ((mode == FilesystemNode::kListAll) ||
- (EAD_IS_DRAWER(ead) && (mode == FilesystemNode::kListDirectoriesOnly)) ||
- (EAD_IS_FILE(ead) && (mode == FilesystemNode::kListFilesOnly))) {
- String full_path = _sPath;
+ if ((mode == Common::FilesystemNode::kListAll) ||
+ (EAD_IS_DRAWER(ead) && (mode == Common::FilesystemNode::kListDirectoriesOnly)) ||
+ (EAD_IS_FILE(ead) && (mode == Common::FilesystemNode::kListFilesOnly))) {
+ Common::String full_path = _sPath;
full_path += (char*)ead->ed_Name;
BPTR lock = IDOS->Lock((STRPTR)full_path.c_str(), SHARED_LOCK);
@@ -566,4 +569,12 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
return myList;
}
+Common::SeekableReadStream *AmigaOSFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *AmigaOSFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
#endif //defined(__amigaos4__)
diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp
index 2eae2f2403..5c8c3f45f8 100644
--- a/backends/fs/ds/ds-fs-factory.cpp
+++ b/backends/fs/ds/ds-fs-factory.cpp
@@ -45,7 +45,7 @@ AbstractFilesystemNode *DSFilesystemFactory::makeCurrentDirectoryFileNode() cons
}
}
-AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
if (DS::isGBAMPAvailable()) {
return new DS::GBAMPFileSystemNode(path);
} else {
diff --git a/backends/fs/ds/ds-fs-factory.h b/backends/fs/ds/ds-fs-factory.h
index bff21a309d..67e0076b78 100644
--- a/backends/fs/ds/ds-fs-factory.h
+++ b/backends/fs/ds/ds-fs-factory.h
@@ -35,11 +35,9 @@
*/
class DSFilesystemFactory : public FilesystemFactory, public Common::Singleton<DSFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
DSFilesystemFactory() {};
diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp
index cffe4c118d..911702316d 100644
--- a/backends/fs/ds/ds-fs.cpp
+++ b/backends/fs/ds/ds-fs.cpp
@@ -24,6 +24,7 @@
#include "common/util.h"
//#include <NDS/ARM9/console.h> //basic print funcionality
#include "backends/fs/ds/ds-fs.h"
+#include "backends/fs/stdiostream.h"
#include "dsmain.h"
#include "fat/gba_nds_fat.h"
@@ -55,7 +56,7 @@ DSFileSystemNode::DSFileSystemNode() {
}
}
-DSFileSystemNode::DSFileSystemNode(const String& path) {
+DSFileSystemNode::DSFileSystemNode(const Common::String& path) {
// consolePrintf("--%s ",path.c_str());
char disp[128];
@@ -70,7 +71,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
strcpy(disp, pathStr + lastSlash + 1);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
// _isValid = true;
// _isDirectory = false;
@@ -98,7 +99,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
// consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory);
}
-DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
+DSFileSystemNode::DSFileSystemNode(const Common::String& path, bool isDir) {
// consolePrintf("--%s ",path.c_str());
char disp[128];
@@ -112,7 +113,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
strcpy(disp, pathStr + lastSlash + 1);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
_isValid = true;
_isDirectory = isDir;
@@ -167,10 +168,10 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool
_zipFile->getFileName(n);
// consolePrintf("file: %s\n", n);
- if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) )
- || (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) )
+ if ( (_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)) )
+ || (!_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll)) ) )
{
- DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(n), _zipFile->isDirectory());
+ DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory());
dsfsn->_isDirectory = _zipFile->isDirectory();
dirList.push_back((dsfsn));
}
@@ -195,7 +196,7 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const {
}
}
- p = new DSFileSystemNode(String(path, lastSlash));
+ p = new DSFileSystemNode(Common::String(path, lastSlash));
((DSFileSystemNode *) (p))->_isDirectory = true;
} else {
p = new DSFileSystemNode();
@@ -204,6 +205,14 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const {
return p;
}
+Common::SeekableReadStream *DSFileSystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *DSFileSystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
//////////////////////////////////////////////////////////////////////////
// GBAMPFileSystemNode - File system using GBA Movie Player and CF card //
//////////////////////////////////////////////////////////////////////////
@@ -216,7 +225,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode() {
_path = "mp:/";
}
-GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
+GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path) {
// consolePrintf("'%s'",path.c_str());
char disp[128];
@@ -245,13 +254,13 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
}
// consolePrintf("Path: %s (%d)\n", check, success);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
_isValid = success == FT_FILE;
_isDirectory = success == FT_DIR;
}
-GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
+GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDirectory) {
// consolePrintf("'%s'",path.c_str());
char disp[128];
@@ -265,7 +274,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
strcpy(disp, pathStr + lastSlash + 1);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
_isValid = true;
_isDirectory = isDirectory;
@@ -313,8 +322,8 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
while (entryType != TYPE_NO_MORE) {
- if ( ((entryType == TYPE_DIR) && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)))
- || ((entryType == TYPE_FILE) && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll))) ) {
+ if ( ((entryType == TYPE_DIR) && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)))
+ || ((entryType == TYPE_FILE) && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll))) ) {
GBAMPFileSystemNode* dsfsn;
consolePrintf("Fname: %s\n", fname);
@@ -322,9 +331,9 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
if (strcmp(fname, ".") && strcmp(fname, "..")) {
if (!strcmp(path, "/")) {
- dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String(fname), entryType == TYPE_DIR);
+ dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String(fname), entryType == TYPE_DIR);
} else {
- dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String("/") + String(fname), entryType == TYPE_DIR);
+ dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String("/") + Common::String(fname), entryType == TYPE_DIR);
}
// dsfsn->_isDirectory = entryType == DIR;
@@ -358,7 +367,7 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
}
}
- p = new GBAMPFileSystemNode(String(path, lastSlash));
+ p = new GBAMPFileSystemNode(Common::String(path, lastSlash));
p->_isDirectory = true;
} else {
p = new GBAMPFileSystemNode();
@@ -367,6 +376,14 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
return p;
}
+Common::SeekableReadStream *GBAMPFileSystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *GBAMPFileSystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
// Stdio replacements
#define MAX_FILE_HANDLES 32
@@ -399,6 +416,7 @@ FILE* std_fopen(const char* name, const char* mode) {
if (DS::isGBAMPAvailable()) {
FAT_chdir("/");
+ // Turn all back slashes into forward slashes for gba_nds_fat
char* p = realName;
while (*p) {
if (*p == '\\') *p = '/';
@@ -422,8 +440,12 @@ FILE* std_fopen(const char* name, const char* mode) {
// Allocate a file handle
int r = 0;
- while (handle[r].used) r++;
+ while (handle[r].used) {
+ r++;
+ assert(r < MAX_FILE_HANDLES);
+ }
+#ifdef GBA_SRAM_SAVE
if (strchr(mode, 'w')) {
// consolePrintf("Writing %s\n", realName);
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
@@ -431,6 +453,7 @@ FILE* std_fopen(const char* name, const char* mode) {
// consolePrintf("Reading %s\n", realName);
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
}
+#endif
if (handle[r].sramFile) {
handle[r].used = true;
@@ -512,69 +535,6 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return bytes / size;
}
return numItems;
-
-/* int item = 0;
- u8* data = (u8 *) ptr;
- while ((item < numItems) && (!FAT_feof((FAT_FILE *) handle))) {
-
-
- int bytes = 0;
- while ((bytes < size) && (!FAT_feof((FAT_FILE *) handle))) {
- *data++ = FAT_fgetc((FAT_FILE *) handle);
- bytes++;
- }
-
- item++;
-
- }
-
- return item;
-*/
- int items = 0;
-
- //for (int r = 0; r < numItems; r++) {
- if (!std_feof(handle)) {
-/* for (int t = 0; t < size; t++) {
- if (feof(handle)) eof = true;
- *(((char *) (ptr)) + r * size + t) = getc(handle);
- }*/
- int left = size * numItems;
- int bytesRead = -1;
-
- while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) {
- int amount = left > 8192? 8192: left;
-// do {
- bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle);
-/* if (bytesRead == 0) {
- consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead);
- left++;
-
- int pos = ftell(handle);
-
- fseek(handle, 0, SEEK_SET);
- int c = getc(handle);
- fseek(handle, pos - 1024, SEEK_SET);
- fread(ptr, 1024, 1, handle);
- swiWaitForVBlank();
- //while (true);
- }
-
- } while (bytesRead == 0);
-*/
- left -= bytesRead;
- ptr = ((char *) (ptr)) + bytesRead;
- }
-
- items = numItems - (left / size);
-
-// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1);
-// ptr = ((char *) (ptr)) + size;
- }
-// }
-
-// consolePrintf("...done %d \n", items)
-
- return items;
}
if (handle->sramFile) {
@@ -641,10 +601,6 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
}
}
-void std_fprintf(FILE* handle, const char* fmt, ...) {
- consolePrintf(fmt);
-}
-
bool std_feof(FILE* handle) {
// consolePrintf("feof ");
@@ -660,42 +616,10 @@ bool std_feof(FILE* handle) {
return handle->pos >= handle->size;
}
-void std_fflush(FILE* handle) {
+int std_fflush(FILE* handle) {
//FIXME: not implemented?
// consolePrintf("fflush ");
-}
-
-char* std_fgets(char* str, int size, FILE* file) {
-// consolePrintf("fgets file=%d ", file);
-
- if (DS::isGBAMPAvailable()) {
- char* s = str;
- while ((*s++ = std_getc(file)) >= 32) {
-// consolePrintf("%d ", *s);
- }
- *s = 0;
-
-// consolePrintf("Read:%s\n", str);
-
- return str;
- }
-
- if (file->sramFile) {
- file->pos--;
- int p = -1;
- do {
- file->pos++;
- p++;
- file->sramFile->read((char *) &str[p], 1);
-// consolePrintf("%d,", str[p]);
- } while ((str[p] >= 32) && (!std_feof(file)) && (p < size));
- str[p + 1] = 0;
- file->pos++;
-// consolePrintf("Read:%s\n", str);
- return str;
- }
-
- return NULL;
+ return 0;
}
long int std_ftell(FILE* handle) {
@@ -731,92 +655,20 @@ int std_fseek(FILE* handle, long int offset, int whence) {
return 0;
}
-void std_clearerr(FILE* handle) {
+int std_ferror(FILE* handle) {
//FIXME: not implemented?
-// consolePrintf("clearerr ");
-}
-
-int std_getc(FILE* handle) {
- if (DS::isGBAMPAvailable()) {
- char c;
- FAT_fread(&c, 1, 1, (FAT_FILE *) handle);
-
- return c;
- }
-
-// consolePrintf("fgetc ");
- return 0; // Not supported yet
+// consolePrintf("ferror ");
+ return 0;
}
-char* std_getcwd(char* dir, int dunno) {
-// consolePrintf("getcwd ");
- dir[0] = '\0';
- return dir; // Not supported yet
+void std_clearerr(FILE* handle) {
+ //FIXME: not implemented?
+// consolePrintf("clearerr ");
}
-void std_cwd(char* dir) {
- char buffer[128];
- strcpy(buffer, dir);
- char* realName = buffer;
-
- if (DS::isGBAMPAvailable()) {
- if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
- realName += 4;
- }
-
- // consolePrintf("Real cwd:%d\n", realName);
-
- char* p = realName;
- while (*p) {
- if (*p == '\\') *p = '/';
- p++;
- }
-
- // consolePrintf("Real cwd:%d\n", realName);
- FAT_chdir(realName);
- } else {
- if ((strlen(dir) >= 4) && (dir[0] == 'd') && (dir[1] == 's') && (dir[2] == ':') && (dir[3] == '/')) {
- realName += 4;
- }
-
- char* p = realName;
- while (*p) {
- if (*p == '\\') *p = '/';
- p++;
- }
-
- strcpy(currentDir, realName);
- if (*(currentDir + strlen(currentDir) - 1) == '/') {
- *(currentDir + strlen(currentDir) - 1) = '\0';
- }
-// consolePrintf("CWD: %s\n", currentDir);
- }
+void std_fprintf(FILE* handle, const char* fmt, ...) {
+ consolePrintf(fmt);
}
-int std_ferror(FILE* handle) {
- return 0;
-}
} // namespace DS
-
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/' && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
-
diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h
index 9ac453aca9..36e7bc9824 100644
--- a/backends/fs/ds/ds-fs.h
+++ b/backends/fs/ds/ds-fs.h
@@ -41,12 +41,10 @@ namespace DS {
*/
class DSFileSystemNode : public AbstractFilesystemNode {
protected:
- typedef class Common::String String;
-
static ZipFile* _zipFile;
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
@@ -61,7 +59,7 @@ public:
*
* @param path String with the path the new node should point to.
*/
- DSFileSystemNode(const String &path);
+ DSFileSystemNode(const Common::String &path);
/**
* Creates a DSFilesystemNode for a given path.
@@ -69,7 +67,7 @@ public:
* @param path String with the path the new node should point to.
* @param path true if path is a directory, false otherwise.
*/
- DSFileSystemNode(const String& path, bool isDir);
+ DSFileSystemNode(const Common::String& path, bool isDir);
/**
* Copy constructor.
@@ -77,9 +75,9 @@ public:
DSFileSystemNode(const DSFileSystemNode *node);
virtual bool exists() const { return true; } //FIXME: this is just a stub
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
@@ -89,9 +87,12 @@ public:
*/
virtual AbstractFilesystemNode *clone() const { return new DSFileSystemNode(this); }
virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
/**
* Returns the zip file this node points to.
* TODO: check this documentation.
@@ -107,10 +108,8 @@ public:
*/
class GBAMPFileSystemNode : public AbstractFilesystemNode {
protected:
- typedef class Common::String String;
-
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
@@ -125,7 +124,7 @@ public:
*
* @param path String with the path the new node should point to.
*/
- GBAMPFileSystemNode(const String &path);
+ GBAMPFileSystemNode(const Common::String &path);
/**
* Creates a DSFilesystemNode for a given path.
@@ -133,7 +132,7 @@ public:
* @param path String with the path the new node should point to.
* @param path true if path is a directory, false otherwise.
*/
- GBAMPFileSystemNode(const String &path, bool isDirectory);
+ GBAMPFileSystemNode(const Common::String &path, bool isDirectory);
/**
* Copy constructor.
@@ -141,9 +140,9 @@ public:
GBAMPFileSystemNode(const GBAMPFileSystemNode *node);
virtual bool exists() const { return _isValid || _isDirectory; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
@@ -153,8 +152,11 @@ public:
*/
virtual AbstractFilesystemNode *clone() const { return new GBAMPFileSystemNode(this); }
virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
};
struct fileHandle {
@@ -179,15 +181,14 @@ struct fileHandle {
// Please do not remove any of these prototypes that appear not to be required.
FILE* std_fopen(const char* name, const char* mode);
void std_fclose(FILE* handle);
-int std_getc(FILE* handle);
size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
bool std_feof(FILE* handle);
long int std_ftell(FILE* handle);
int std_fseek(FILE* handle, long int offset, int whence);
void std_clearerr(FILE* handle);
-void std_cwd(char* dir);
-void std_fflush(FILE* handle);
+int std_fflush(FILE* handle);
+int std_ferror(FILE* handle);
} //namespace DS
diff --git a/backends/fs/palmos/palmos-fs-factory.cpp b/backends/fs/palmos/palmos-fs-factory.cpp
index 8699a9788b..bbc1639897 100644
--- a/backends/fs/palmos/palmos-fs-factory.cpp
+++ b/backends/fs/palmos/palmos-fs-factory.cpp
@@ -36,7 +36,7 @@ AbstractFilesystemNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode()
return new PalmOSFilesystemNode();
}
-AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new PalmOSFilesystemNode(path);
}
#endif
diff --git a/backends/fs/palmos/palmos-fs-factory.h b/backends/fs/palmos/palmos-fs-factory.h
index 3ea8b5fe47..f778aa89ef 100644
--- a/backends/fs/palmos/palmos-fs-factory.h
+++ b/backends/fs/palmos/palmos-fs-factory.h
@@ -35,11 +35,9 @@
*/
class PalmOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<PalmOSFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
PalmOSFilesystemFactory() {};
diff --git a/backends/fs/palmos/palmos-fs.cpp b/backends/fs/palmos/palmos-fs.cpp
index 5edb6c2d26..7c415aa320 100644
--- a/backends/fs/palmos/palmos-fs.cpp
+++ b/backends/fs/palmos/palmos-fs.cpp
@@ -28,6 +28,7 @@
#include "globals.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
/**
* Implementation of the ScummVM file system API based on PalmOS VFS API.
@@ -36,8 +37,8 @@
*/
class PalmOSFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
bool _isPseudoRoot;
@@ -51,22 +52,25 @@ public:
/**
* Creates a POSIXFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- PalmOSFilesystemNode(const String &p);
+ PalmOSFilesystemNode(const Common::String &p);
virtual bool exists() const { return _isValid; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
private:
/**
* Adds a single WindowsFilesystemNode to a given list.
@@ -74,44 +78,20 @@ private:
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
- * @param base String with the directory being listed.
+ * @param base Common::String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList &list, ListMode mode, const Char *base, FileInfoType* find_data);
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
void PalmOSFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, FileInfoType* find_data) {
PalmOSFilesystemNode entry;
bool isDir;
isDir = (find_data->attributes & vfsFileAttrDirectory);
- if ((!isDir && mode == FilesystemNode::kListDirectoriesOnly) ||
- (isDir && mode == FilesystemNode::kListFilesOnly))
+ if ((!isDir && mode == Common::FilesystemNode::kListDirectoriesOnly) ||
+ (isDir && mode == Common::FilesystemNode::kListFilesOnly))
return;
entry._isDirectory = isDir;
@@ -136,9 +116,9 @@ PalmOSFilesystemNode::PalmOSFilesystemNode() {
_isPseudoRoot = false;
}
-PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
+PalmOSFilesystemNode::PalmOSFilesystemNode(const Common::String &p) {
_path = p;
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '/');
UInt32 attr;
FileRef handle;
@@ -159,10 +139,10 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
_isPseudoRoot = false;
}
-AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -215,17 +195,25 @@ AbstractFilesystemNode *PalmOSFilesystemNode::getParent() const {
if (!_isPseudoRoot) {
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
p = new PalmOSFilesystemNode();
- p->_path = String(start, end - start);
+ p->_path = Common::String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path);
+ p->_displayName = lastPathComponent(p->_path, '/');
p->_isPseudoRoot =(p->_path == "/");
}
return p;
}
+Common::SeekableReadStream *PalmOSFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *PalmOSFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
#endif // PALMOS_MODE
diff --git a/backends/fs/posix/posix-fs-factory.cpp b/backends/fs/posix/posix-fs-factory.cpp
index 0a1160ff8f..cbfb69b76a 100644
--- a/backends/fs/posix/posix-fs-factory.cpp
+++ b/backends/fs/posix/posix-fs-factory.cpp
@@ -26,19 +26,18 @@
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.cpp"
-DECLARE_SINGLETON(POSIXFilesystemFactory);
-
AbstractFilesystemNode *POSIXFilesystemFactory::makeRootFileNode() const {
- return new POSIXFilesystemNode();
+ return new POSIXFilesystemNode("/");
}
AbstractFilesystemNode *POSIXFilesystemFactory::makeCurrentDirectoryFileNode() const {
char buf[MAXPATHLEN];
getcwd(buf, MAXPATHLEN);
- return new POSIXFilesystemNode(buf, true);
+ return new POSIXFilesystemNode(buf);
}
-AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const String &path) const {
- return new POSIXFilesystemNode(path, true);
+AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const Common::String &path) const {
+ assert(!path.empty());
+ return new POSIXFilesystemNode(path);
}
#endif
diff --git a/backends/fs/posix/posix-fs-factory.h b/backends/fs/posix/posix-fs-factory.h
index d8eecda6ef..c697679814 100644
--- a/backends/fs/posix/posix-fs-factory.h
+++ b/backends/fs/posix/posix-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef POSIX_FILESYSTEM_FACTORY_H
#define POSIX_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,10 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class POSIXFilesystemFactory : public FilesystemFactory, public Common::Singleton<POSIXFilesystemFactory> {
-public:
- typedef Common::String String;
-
+class POSIXFilesystemFactory : public FilesystemFactory {
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- POSIXFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*POSIX_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 10782a9057..8dca78d82a 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -24,85 +24,20 @@
#if defined(UNIX)
-#include "backends/fs/abstract-fs.h"
+#include "backends/fs/posix/posix-fs.h"
+#include "backends/fs/stdiostream.h"
+#include "common/algorithm.h"
-#ifdef MACOSX
-#include <sys/types.h>
-#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
-#include <unistd.h>
-/**
- * Implementation of the ScummVM file system API based on POSIX.
- *
- * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
- */
-class POSIXFilesystemNode : public AbstractFilesystemNode {
-protected:
- Common::String _displayName;
- Common::String _path;
- bool _isDirectory;
- bool _isValid;
-
-public:
- /**
- * Creates a POSIXFilesystemNode with the root node as path.
- */
- POSIXFilesystemNode();
-
- /**
- * Creates a POSIXFilesystemNode for a given path.
- *
- * @param path String with the path the new node should point to.
- * @param verify true if the isValid and isDirectory flags should be verified during the construction.
- */
- POSIXFilesystemNode(const Common::String &path, bool verify);
-
- virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
- virtual Common::String getDisplayName() const { return _displayName; }
- virtual Common::String getName() const { return _displayName; }
- virtual Common::String getPath() const { return _path; }
- virtual bool isDirectory() const { return _isDirectory; }
- virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
- virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
-
- virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
- virtual AbstractFilesystemNode *getParent() const;
-
-private:
- /**
- * Tests and sets the _isValid and _isDirectory flags, using the stat() function.
- */
- virtual void setFlags();
-};
-
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
+#ifdef __OS2__
+#define INCL_DOS
+#include <os2.h>
+#endif
- return cur + 1;
-}
void POSIXFilesystemNode::setFlags() {
struct stat st;
@@ -111,15 +46,7 @@ void POSIXFilesystemNode::setFlags() {
_isDirectory = _isValid ? S_ISDIR(st.st_mode) : false;
}
-POSIXFilesystemNode::POSIXFilesystemNode() {
- // The root dir.
- _path = "/";
- _displayName = _path;
- _isValid = true;
- _isDirectory = true;
-}
-
-POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p, bool verify) {
+POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p) {
assert(p.size() > 0);
// Expand "~/" to the value of the HOME env variable
@@ -134,30 +61,85 @@ POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p, bool verify) {
} else {
_path = p;
}
-
- _displayName = lastPathComponent(_path);
-
- if (verify) {
- setFlags();
+
+#ifdef __OS2__
+ // On OS/2, 'X:/' is a root of drive X, so we should not remove that last
+ // slash.
+ if (!(_path.size() == 3 && _path.hasSuffix(":/")))
+#endif
+ // Normalize the path (that is, remove unneeded slashes etc.)
+ _path = Common::normalizePath(_path, '/');
+ _displayName = Common::lastPathComponent(_path, '/');
+
+ // TODO: should we turn relative paths into absolute ones?
+ // Pro: Ensures the "getParent" works correctly even for relative dirs.
+ // Contra: The user may wish to use (and keep!) relative paths in his
+ // config file, and converting relative to absolute paths may hurt him...
+ //
+ // An alternative approach would be to change getParent() to work correctly
+ // if "_path" is the empty string.
+#if 0
+ if (!_path.hasPrefix("/")) {
+ char buf[MAXPATHLEN+1];
+ getcwd(buf, MAXPATHLEN);
+ strcat(buf, "/");
+ _path = buf + _path;
}
+#endif
+ // TODO: Should we enforce that the path is absolute at this point?
+ //assert(_path.hasPrefix("/"));
+
+ setFlags();
}
AbstractFilesystemNode *POSIXFilesystemNode::getChild(const Common::String &n) const {
- // FIXME: Pretty lame implementation! We do no error checking to speak
- // of, do not check if this is a special node, etc.
+ assert(!_path.empty());
assert(_isDirectory);
+
+ // Make sure the string contains no slashes
+ assert(!n.contains('/'));
+ // We assume here that _path is already normalized (hence don't bother to call
+ // Common::normalizePath on the final path).
Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
- return new POSIXFilesystemNode(newPath, true);
+ return makeNode(newPath);
}
bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
assert(_isDirectory);
+#ifdef __OS2__
+ if (_path == "/") {
+ // Special case for the root dir: List all DOS drives
+ ULONG ulDrvNum;
+ ULONG ulDrvMap;
+
+ DosQueryCurrentDisk(&ulDrvNum, &ulDrvMap);
+
+ for (int i = 0; i < 26; i++) {
+ if (ulDrvMap & 1) {
+ char drive_root[] = "A:/";
+ drive_root[0] += i;
+
+ POSIXFilesystemNode *entry = new POSIXFilesystemNode();
+ entry->_isDirectory = true;
+ entry->_isValid = true;
+ entry->_path = drive_root;
+ entry->_displayName = "[" + Common::String(drive_root, 2) + "]";
+ myList.push_back(entry);
+ }
+
+ ulDrvMap >>= 1;
+ }
+
+ return true;
+ }
+#endif
+
DIR *dirp = opendir(_path.c_str());
struct dirent *dp;
@@ -175,12 +157,12 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
continue;
}
- Common::String newPath(_path);
- if (newPath.lastChar() != '/')
- newPath += '/';
- newPath += dp->d_name;
-
- POSIXFilesystemNode entry(newPath, false);
+ // Start with a clone of this node, with the correct path set
+ POSIXFilesystemNode entry(*this);
+ entry._displayName = dp->d_name;
+ if (_path.lastChar() != '/')
+ entry._path += '/';
+ entry._path += entry._displayName;
#if defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
/* TODO: d_type is not part of POSIX, so it might not be supported
@@ -215,13 +197,10 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
continue;
// Honor the chosen mode
- if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
- if (entry._isDirectory)
- entry._path += "/";
-
myList.push_back(new POSIXFilesystemNode(entry));
}
closedir(dirp);
@@ -231,12 +210,39 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
AbstractFilesystemNode *POSIXFilesystemNode::getParent() const {
if (_path == "/")
- return 0;
+ return 0; // The filesystem root has no parent
+
+#ifdef __OS2__
+ if (_path.size() == 3 && _path.hasSuffix(":/"))
+ // This is a root directory of a drive
+ return makeNode("/"); // return a virtual root for a list of drives
+#endif
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = start + _path.size();
+
+ // Strip of the last component. We make use of the fact that at this
+ // point, _path is guaranteed to be normalized
+ while (end > start && *(end-1) != '/')
+ end--;
+
+ if (end == start) {
+ // This only happens if we were called with a relative path, for which
+ // there simply is no parent.
+ // TODO: We could also resolve this by assuming that the parent is the
+ // current working directory, and returning a node referring to that.
+ return 0;
+ }
+
+ return makeNode(Common::String(start, end));
+}
+
+Common::SeekableReadStream *POSIXFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new POSIXFilesystemNode(Common::String(start, end - start), true);
+Common::WriteStream *POSIXFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined(UNIX)
diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h
new file mode 100644
index 0000000000..e09e433e05
--- /dev/null
+++ b/backends/fs/posix/posix-fs.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 POSIX_FILESYSTEM_H
+#define POSIX_FILESYSTEM_H
+
+#include "backends/fs/abstract-fs.h"
+
+#ifdef MACOSX
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+
+/**
+ * Implementation of the ScummVM file system API based on POSIX.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
+ */
+class POSIXFilesystemNode : public AbstractFilesystemNode {
+protected:
+ Common::String _displayName;
+ Common::String _path;
+ bool _isDirectory;
+ bool _isValid;
+
+ virtual AbstractFilesystemNode *makeNode(const Common::String &path) const {
+ return new POSIXFilesystemNode(path);
+ }
+
+ /**
+ * Plain constructor, for internal use only (hence protected).
+ */
+ POSIXFilesystemNode() : _isDirectory(false), _isValid(false) {}
+
+public:
+ /**
+ * Creates a POSIXFilesystemNode for a given path.
+ *
+ * @param path the path the new node should point to.
+ */
+ POSIXFilesystemNode(const Common::String &path);
+
+ virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
+ virtual bool isDirectory() const { return _isDirectory; }
+ virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
+ virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
+
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
+private:
+ /**
+ * Tests and sets the _isValid and _isDirectory flags, using the stat() function.
+ */
+ virtual void setFlags();
+};
+
+#endif /*POSIX_FILESYSTEM_H*/
diff --git a/backends/fs/ps2/ps2-fs-factory.cpp b/backends/fs/ps2/ps2-fs-factory.cpp
index ce3b4a5eaf..e96671ee0a 100644
--- a/backends/fs/ps2/ps2-fs-factory.cpp
+++ b/backends/fs/ps2/ps2-fs-factory.cpp
@@ -36,7 +36,7 @@ AbstractFilesystemNode *Ps2FilesystemFactory::makeCurrentDirectoryFileNode() con
return new Ps2FilesystemNode();
}
-AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const Common::String &path) const {
// return new Ps2FilesystemNode(path);
Ps2FilesystemNode *nf = new Ps2FilesystemNode(path, true);
diff --git a/backends/fs/ps2/ps2-fs-factory.h b/backends/fs/ps2/ps2-fs-factory.h
index 416024c905..432cf467c3 100644
--- a/backends/fs/ps2/ps2-fs-factory.h
+++ b/backends/fs/ps2/ps2-fs-factory.h
@@ -35,11 +35,9 @@
*/
class Ps2FilesystemFactory : public FilesystemFactory, public Common::Singleton<Ps2FilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
Ps2FilesystemFactory() {};
diff --git a/backends/fs/ps2/ps2-fs.cpp b/backends/fs/ps2/ps2-fs.cpp
index 782e97b959..3d7656e9f0 100644
--- a/backends/fs/ps2/ps2-fs.cpp
+++ b/backends/fs/ps2/ps2-fs.cpp
@@ -23,6 +23,7 @@
*/
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
@@ -47,8 +48,8 @@ class Ps2FilesystemNode : public AbstractFilesystemNode {
friend class Ps2FilesystemFactory;
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isRoot;
@@ -65,10 +66,10 @@ public:
/**
* Creates a PS2FilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- Ps2FilesystemNode(const String &path);
- Ps2FilesystemNode(const String &path, bool verify);
+ Ps2FilesystemNode(const Common::String &path);
+ Ps2FilesystemNode(const Common::String &path, bool verify);
/**
* Copy constructor.
@@ -77,9 +78,9 @@ public:
virtual bool exists(void) const;
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const {
return _isDirectory;
@@ -95,32 +96,13 @@ public:
}
virtual AbstractFilesystemNode *clone() const { return new Ps2FilesystemNode(this); }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
-};
-
-/**
- * Returns the last component of a given path.
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if (str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/' && *cur != ':') {
- --cur;
- }
-
- printf("romeo : lastPathComponent = %s\n", cur + 1);
- return cur + 1;
-}
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+};
Ps2FilesystemNode::Ps2FilesystemNode() {
_isDirectory = true;
@@ -129,12 +111,12 @@ Ps2FilesystemNode::Ps2FilesystemNode() {
_path = "";
}
-Ps2FilesystemNode::Ps2FilesystemNode(const String &path) {
+Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path) {
_path = path;
_isDirectory = true;
if (strcmp(path.c_str(), "") == 0) {
_isRoot = true;
- _displayName = String("PlayStation 2");
+ _displayName = Common::String("PlayStation 2");
} else {
_isRoot = false;
const char *dsplName = NULL, *pos = path.c_str();
@@ -142,18 +124,18 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path) {
if (*pos++ == '/')
dsplName = pos;
if (dsplName)
- _displayName = String(dsplName);
+ _displayName = Common::String(dsplName);
else
_displayName = getDeviceDescription(path.c_str());
}
}
-Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) {
+Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path, bool verify) {
_path = path;
if (strcmp(path.c_str(), "") == 0) {
_isRoot = true; /* root is always a dir*/
- _displayName = String("PlayStation 2");
+ _displayName = Common::String("PlayStation 2");
_isDirectory = true;
} else {
_isRoot = false;
@@ -163,7 +145,7 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) {
dsplName = pos;
if (dsplName) {
- _displayName = String(dsplName);
+ _displayName = Common::String(dsplName);
if (verify)
_isDirectory = getDirectoryFlag(path.c_str());
else
@@ -228,7 +210,7 @@ bool Ps2FilesystemNode::getDirectoryFlag(const char *path) {
return false;
}
-AbstractFilesystemNode *Ps2FilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *Ps2FilesystemNode::getChild(const Common::String &n) const {
if (!_isDirectory)
return NULL;
@@ -306,9 +288,9 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi
while ((dreadRes = fio.dread(fd, &dirent)) > 0) {
if (dirent.name[0] == '.')
continue; // ignore '.' and '..'
- if (((mode == FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) ||
- ((mode == FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) ||
- (mode == FilesystemNode::kListAll)) {
+ if (((mode == Common::FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) ||
+ ((mode == Common::FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) ||
+ (mode == Common::FilesystemNode::kListAll)) {
dirEntry._isDirectory = (bool)(dirent.stat.mode & FIO_S_IFDIR);
dirEntry._isRoot = false;
@@ -344,7 +326,7 @@ AbstractFilesystemNode *Ps2FilesystemNode::getParent() const {
}
if (slash)
- return new Ps2FilesystemNode(String(_path.c_str(), slash - _path.c_str()));
+ return new Ps2FilesystemNode(Common::String(_path.c_str(), slash - _path.c_str()));
else
return new Ps2FilesystemNode();
}
@@ -359,3 +341,10 @@ char *Ps2FilesystemNode::getDeviceDescription(const char *path) const {
return "Harddisk";
}
+Common::SeekableReadStream *Ps2FilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *Ps2FilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp
index 87f0e0f587..a38462f02a 100644
--- a/backends/fs/psp/psp-fs-factory.cpp
+++ b/backends/fs/psp/psp-fs-factory.cpp
@@ -36,7 +36,7 @@ AbstractFilesystemNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() con
return new PSPFilesystemNode();
}
-AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new PSPFilesystemNode(path, true);
}
#endif
diff --git a/backends/fs/psp/psp-fs-factory.h b/backends/fs/psp/psp-fs-factory.h
index ffa934755f..abf03d288e 100644
--- a/backends/fs/psp/psp-fs-factory.h
+++ b/backends/fs/psp/psp-fs-factory.h
@@ -35,11 +35,9 @@
*/
class PSPFilesystemFactory : public FilesystemFactory, public Common::Singleton<PSPFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
PSPFilesystemFactory() {};
diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp
index 3fe6060928..13cd63903b 100644
--- a/backends/fs/psp/psp-fs.cpp
+++ b/backends/fs/psp/psp-fs.cpp
@@ -26,6 +26,7 @@
#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <sys/stat.h>
#include <unistd.h>
@@ -39,8 +40,8 @@
*/
class PSPFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
@@ -53,47 +54,26 @@ public:
/**
* Creates a PSPFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
*/
PSPFilesystemNode(const Common::String &p, bool verify);
virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
-};
-
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+};
PSPFilesystemNode::PSPFilesystemNode() {
_isDirectory = true;
@@ -106,7 +86,7 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
assert(p.size() > 0);
_path = p;
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '/');
_isValid = true;
_isDirectory = true;
@@ -117,12 +97,12 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
}
}
-AbstractFilesystemNode *PSPFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *PSPFilesystemNode::getChild(const Common::String &n) const {
// FIXME: Pretty lame implementation! We do no error checking to speak
// of, do not check if this is a special node, etc.
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -157,8 +137,8 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
entry._path += "/";
// Honor the chosen mode
- if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
myList.push_back(new PSPFilesystemNode(entry));
@@ -176,9 +156,17 @@ AbstractFilesystemNode *PSPFilesystemNode::getParent() const {
return 0;
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
+
+ return new PSPFilesystemNode(Common::String(start, end - start), false);
+}
+
+Common::SeekableReadStream *PSPFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new PSPFilesystemNode(String(start, end - start), false);
+Common::WriteStream *PSPFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#ifdef __PSP__
diff --git a/backends/fs/stdiostream.cpp b/backends/fs/stdiostream.cpp
new file mode 100644
index 0000000000..3b0de253ab
--- /dev/null
+++ b/backends/fs/stdiostream.cpp
@@ -0,0 +1,161 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/fs/stdiostream.h"
+
+#include <errno.h>
+
+#if defined(MACOSX) || defined(IPHONE)
+#include "CoreFoundation/CoreFoundation.h"
+#endif
+
+
+#ifdef __PLAYSTATION2__
+ // for those replaced fopen/fread/etc functions
+ typedef unsigned long uint64;
+ typedef signed long int64;
+ #include "backends/platform/ps2/fileio.h"
+
+ #define fopen(a, b) ps2_fopen(a, b)
+ #define fclose(a) ps2_fclose(a)
+ #define fseek(a, b, c) ps2_fseek(a, b, c)
+ #define ftell(a) ps2_ftell(a)
+ #define feof(a) ps2_feof(a)
+ #define fread(a, b, c, d) ps2_fread(a, b, c, d)
+ #define fwrite(a, b, c, d) ps2_fwrite(a, b, c, d)
+
+ //#define fprintf ps2_fprintf // used in common/util.cpp
+ //#define fflush(a) ps2_fflush(a) // used in common/util.cpp
+
+ //#define fgetc(a) ps2_fgetc(a) // not used
+ //#define fgets(a, b, c) ps2_fgets(a, b, c) // not used
+ //#define fputc(a, b) ps2_fputc(a, b) // not used
+ //#define fputs(a, b) ps2_fputs(a, b) // not used
+
+ //#define fsize(a) ps2_fsize(a) // not used -- and it is not a standard function either
+#endif
+
+#ifdef __DS__
+
+ // These functions replace the standard library functions of the same name.
+ // As this header is included after the standard one, I have the chance to #define
+ // all of these to my own code.
+ //
+ // A #define is the only way, as redefinig the functions would cause linker errors.
+
+ // These functions need to be #undef'ed, as their original definition
+ // in devkitarm is done with #includes (ugh!)
+ #undef feof
+ #undef clearerr
+ //#undef getc
+ //#undef ferror
+
+ #include "backends/fs/ds/ds-fs.h"
+
+
+ // Only functions used in the ScummVM source have been defined here!
+ #define fopen(name, mode) DS::std_fopen(name, mode)
+ #define fclose(handle) DS::std_fclose(handle)
+ #define fread(ptr, size, items, file) DS::std_fread(ptr, size, items, file)
+ #define fwrite(ptr, size, items, file) DS::std_fwrite(ptr, size, items, file)
+ #define feof(handle) DS::std_feof(handle)
+ #define ftell(handle) DS::std_ftell(handle)
+ #define fseek(handle, offset, whence) DS::std_fseek(handle, offset, whence)
+ #define clearerr(handle) DS::std_clearerr(handle)
+ #define fflush(file) DS::std_fflush(file)
+ #define ferror(handle) DS::std_ferror(handle)
+
+#endif
+
+StdioStream::StdioStream(void *handle) : _handle(handle) {
+ assert(handle);
+}
+
+StdioStream::~StdioStream() {
+ fclose((FILE *)_handle);
+}
+
+bool StdioStream::err() const {
+ return ferror((FILE *)_handle) != 0;
+}
+
+void StdioStream::clearErr() {
+ clearerr((FILE *)_handle);
+}
+
+bool StdioStream::eos() const {
+ return feof((FILE *)_handle) != 0;
+}
+
+int32 StdioStream::pos() const {
+ return ftell((FILE *)_handle);
+}
+
+int32 StdioStream::size() const {
+ int32 oldPos = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, 0, SEEK_END);
+ int32 length = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, oldPos, SEEK_SET);
+
+ return length;
+}
+
+bool StdioStream::seek(int32 offs, int whence) {
+ return fseek((FILE *)_handle, offs, whence) == 0;
+}
+
+uint32 StdioStream::read(void *ptr, uint32 len) {
+ return fread((byte *)ptr, 1, len, (FILE *)_handle);
+}
+
+uint32 StdioStream::write(const void *ptr, uint32 len) {
+ return fwrite(ptr, 1, len, (FILE *)_handle);
+}
+
+bool StdioStream::flush() {
+ return fflush((FILE *)_handle) == 0;
+}
+
+StdioStream *StdioStream::makeFromPath(const Common::String &path, bool writeMode) {
+ FILE *handle = fopen(path.c_str(), writeMode ? "wb" : "rb");
+
+#ifdef __amigaos4__
+ //
+ // Work around for possibility that someone uses AmigaOS "newlib" build
+ // with SmartFileSystem (blocksize 512 bytes), leading to buffer size
+ // being only 512 bytes. "Clib2" sets the buffer size to 8KB, resulting
+ // smooth movie playback. This forces the buffer to be enough also when
+ // using "newlib" compile on SFS.
+ //
+ if (handle && !writeMode) {
+ setvbuf(handle, NULL, _IOFBF, 8192);
+ }
+#endif
+
+
+ if (handle)
+ return new StdioStream(handle);
+ return 0;
+}
diff --git a/engines/scumm/smush/chunk.h b/backends/fs/stdiostream.h
index ca4a3cdd99..3d44062d7f 100644
--- a/engines/scumm/smush/chunk.h
+++ b/backends/fs/stdiostream.h
@@ -23,70 +23,40 @@
*
*/
-#ifndef SCUMM_SMUSH_CHUNK_H
-#define SCUMM_SMUSH_CHUNK_H
+#ifndef BACKENDS_FS_STDIOSTREAM_H
+#define BACKENDS_FS_STDIOSTREAM_H
#include "common/scummsys.h"
-#include "common/str.h"
+#include "common/noncopyable.h"
#include "common/stream.h"
+#include "common/str.h"
-namespace Scumm {
-
-class BaseScummFile;
-
-class Chunk : public Common::SeekableReadStream {
-public:
- typedef uint32 type;
-
- virtual type getType() const = 0;
- virtual Chunk *subBlock() = 0;
- virtual void reseek() = 0;
-};
-
-// Common functionality for concrete chunks (FileChunk, MemoryChunk)
-class BaseChunk : public Chunk {
+class StdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
protected:
- Chunk::type _type;
- uint32 _size;
- uint32 _curPos;
- Common::String _name;
-
- BaseChunk();
+ /** File handle to the actual file. */
+ void *_handle;
public:
- Chunk::type getType() const;
- uint32 size() const;
- bool eos() const;
- uint32 pos() const;
- void seek(int32 delta, int dir);
-};
+ /**
+ * Given a path, invokes fopen on that path and wrap the result in a
+ * StdioStream instance.
+ */
+ static StdioStream *makeFromPath(const Common::String &path, bool writeMode);
-class FileChunk : public BaseChunk {
-private:
- BaseScummFile *_data;
- bool _deleteData;
- uint32 _offset;
+ StdioStream(void *handle);
+ virtual ~StdioStream();
- FileChunk(BaseScummFile *data, int offset);
-public:
- FileChunk(const Common::String &name, int offset = 0);
- virtual ~FileChunk();
- Chunk *subBlock();
- void reseek();
- uint32 read(void *buffer, uint32 size);
-};
+ bool err() const;
+ void clearErr();
+ bool eos() const;
-class MemoryChunk : public BaseChunk {
-private:
- byte *_data;
+ virtual uint32 write(const void *dataPtr, uint32 dataSize);
+ virtual bool flush();
-public:
- MemoryChunk(byte *data);
- Chunk *subBlock();
- void reseek();
- uint32 read(void *buffer, uint32 size);
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ bool seek(int32 offs, int whence = SEEK_SET);
+ uint32 read(void *dataPtr, uint32 dataSize);
};
-} // End of namespace Scumm
-
#endif
diff --git a/backends/fs/symbian/symbian-fs-factory.cpp b/backends/fs/symbian/symbian-fs-factory.cpp
index 0a1bd62134..c31dfb594a 100644
--- a/backends/fs/symbian/symbian-fs-factory.cpp
+++ b/backends/fs/symbian/symbian-fs-factory.cpp
@@ -26,8 +26,6 @@
#include "backends/fs/symbian/symbian-fs-factory.h"
#include "backends/fs/symbian/symbian-fs.cpp"
-DECLARE_SINGLETON(SymbianFilesystemFactory);
-
AbstractFilesystemNode *SymbianFilesystemFactory::makeRootFileNode() const {
return new SymbianFilesystemNode(true);
}
@@ -38,7 +36,7 @@ AbstractFilesystemNode *SymbianFilesystemFactory::makeCurrentDirectoryFileNode()
return new SymbianFilesystemNode(path);
}
-AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new SymbianFilesystemNode(path);
}
#endif
diff --git a/backends/fs/symbian/symbian-fs-factory.h b/backends/fs/symbian/symbian-fs-factory.h
index 502fba2930..ef5a231e72 100644
--- a/backends/fs/symbian/symbian-fs-factory.h
+++ b/backends/fs/symbian/symbian-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef SYMBIAN_FILESYSTEM_FACTORY_H
#define SYMBIAN_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class SymbianFilesystemFactory : public FilesystemFactory, public Common::Singleton<SymbianFilesystemFactory> {
+class SymbianFilesystemFactory : public FilesystemFactory {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- SymbianFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*SYMBIAN_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/symbian/symbian-fs.cpp b/backends/fs/symbian/symbian-fs.cpp
index 85fc58179a..1c6d8435a9 100644
--- a/backends/fs/symbian/symbian-fs.cpp
+++ b/backends/fs/symbian/symbian-fs.cpp
@@ -24,12 +24,16 @@
#if defined (__SYMBIAN32__)
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/symbian/symbianstream.h"
+#include "backends/platform/symbian/src/symbianos.h"
#include <dirent.h>
#include <eikenv.h>
#include <f32file.h>
#include <bautils.h>
+#define KDriveLabelSize 30
+
/**
* Implementation of the ScummVM file system API based on POSIX.
*
@@ -37,12 +41,11 @@
*/
class SymbianFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
- bool _isDirectory;
- bool _isValid;
- bool _isPseudoRoot;
-
+ Common::String _displayName;
+ Common::String _path;
+ TBool _isDirectory;
+ TBool _isValid;
+ TBool _isPseudoRoot;
public:
/**
* Creates a SymbianFilesystemNode with the root node as path.
@@ -54,57 +57,36 @@ public:
/**
* Creates a SymbianFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- SymbianFilesystemNode(const String &path);
+ SymbianFilesystemNode(const Common::String &path);
virtual bool exists() const {
TFileName fname;
- TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
+ TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size());
fname.Copy(ptr);
- TBool fileExists = BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), fname);
+ TBool fileExists = BaflUtils::FileExists(static_cast<OSystem_SDL_Symbian*> (g_system)->FsSession(), fname);
return fileExists;
}
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } //FIXME: this is just a stub
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } //FIXME: this is just a stub
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
-};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * c:\foo\bar.txt would return "\bar.txt"
- * c:\foo\bar\ would return "\bar\"
- *
- * @param str Path to obtain the last component from.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+};
/**
* Fixes the path by changing all slashes to backslashes.
*
- * @param path String with the path to be fixed.
+ * @param path Common::String with the path to be fixed.
*/
static void fixFilePath(Common::String& aPath){
TInt len = aPath.size();
@@ -118,54 +100,47 @@ static void fixFilePath(Common::String& aPath){
SymbianFilesystemNode::SymbianFilesystemNode(bool aIsRoot) {
_path = "";
- _isValid = true;
- _isDirectory = true;
+ _isValid = ETrue;
+ _isDirectory = ETrue;
_isPseudoRoot = aIsRoot;
_displayName = "Root";
}
-SymbianFilesystemNode::SymbianFilesystemNode(const String &path) {
+SymbianFilesystemNode::SymbianFilesystemNode(const Common::String &path) {
if (path.size() == 0)
- _isPseudoRoot = true;
+ _isPseudoRoot = ETrue;
else
- _isPseudoRoot = false;
+ _isPseudoRoot = EFalse;
_path = path;
fixFilePath(_path);
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '\\');
TEntry fileAttribs;
TFileName fname;
TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
fname.Copy(ptr);
- if (CEikonEnv::Static()->FsSession().Entry(fname, fileAttribs) == KErrNone) {
- _isValid = true;
+ if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().Entry(fname, fileAttribs) == KErrNone) {
+ _isValid = ETrue;
_isDirectory = fileAttribs.IsDir();
} else {
- _isValid = false;
- _isDirectory = false;
+ _isValid = ETrue;
+ _isDirectory = EFalse;
}
}
-AbstractFilesystemNode *SymbianFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *SymbianFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '\\')
newPath += '\\';
- newPath += n;
- TPtrC8 ptr((const unsigned char*) newPath.c_str(), newPath.size());
- TFileName fname;
- fname.Copy(ptr);
- TBool isFolder = EFalse;
- BaflUtils::IsFolder(CEikonEnv::Static()->FsSession(), fname, isFolder);
- if (!isFolder)
- return 0;
+ newPath += n;
return new SymbianFilesystemNode(newPath);
}
@@ -177,19 +152,19 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
if (_isPseudoRoot) {
// Drives enumeration
- RFs fs = CEikonEnv::Static()->FsSession();
+ RFs& fs = static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession();
TInt driveNumber;
TChar driveLetter;
TUint driveLetterValue;
TVolumeInfo volumeInfo;
- TBuf8<30> driveLabel8;
- TBuf8<30> driveString8;
+ TBuf8<KDriveLabelSize> driveLabel8;
+ TBuf8<KDriveLabelSize> driveString8;
for (driveNumber=EDriveA; driveNumber<=EDriveZ; driveNumber++) {
TInt err = fs.Volume(volumeInfo, driveNumber);
if (err != KErrNone)
continue;
- if (fs.DriveToChar(driveNumber,driveLetter) != KErrNone)
+ if (fs.DriveToChar(driveNumber, driveLetter) != KErrNone)
continue;
driveLetterValue = driveLetter;
@@ -205,40 +180,46 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
sprintf(path,"%c:\\", driveNumber+'A');
SymbianFilesystemNode entry(false);
- entry._displayName = (char*)driveString8.PtrZ(); // drive_name
- entry._isDirectory = true;
- entry._isValid = true;
- entry._isPseudoRoot = false;
+ entry._displayName = (char*) driveString8.PtrZ(); // drive_name
+ entry._isDirectory = ETrue;
+ entry._isValid = ETrue;
+ entry._isPseudoRoot = EFalse;
entry._path = path;
myList.push_back(new SymbianFilesystemNode(entry));
}
} else {
- TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
+ TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size());
TFileName fname;
- fname.Copy(ptr);
TBuf8<256>nameBuf;
CDir* dirPtr;
- if (CEikonEnv::Static()->FsSession().GetDir(fname,KEntryAttNormal|KEntryAttDir,0,dirPtr)==KErrNone) {
+ fname.Copy(ptr);
+
+ if (_path.lastChar() != '\\')
+ fname.Append('\\');
+
+ if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().GetDir(fname, KEntryAttNormal|KEntryAttDir, 0, dirPtr) == KErrNone) {
CleanupStack::PushL(dirPtr);
TInt cnt=dirPtr->Count();
for (TInt loop=0;loop<cnt;loop++) {
TEntry fileentry=(*dirPtr)[loop];
nameBuf.Copy(fileentry.iName);
- SymbianFilesystemNode entry(false);
- entry._isPseudoRoot = false;
+ SymbianFilesystemNode entry(EFalse);
+ entry._isPseudoRoot = EFalse;
- entry._displayName =(char*)nameBuf.PtrZ();
+ entry._displayName =(char*) nameBuf.PtrZ();
entry._path = _path;
- entry._path +=(char*)nameBuf.PtrZ();
+
+ if (entry._path.lastChar() != '\\')
+ entry._path+= '\\';
+
+ entry._path +=(char*) nameBuf.PtrZ();
entry._isDirectory = fileentry.IsDir();
// Honor the chosen mode
- if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
-
- if (entry._isDirectory)
- entry._path += "\\";
+
myList.push_back(new SymbianFilesystemNode(entry));
}
CleanupStack::PopAndDestroy(dirPtr);
@@ -254,21 +235,30 @@ AbstractFilesystemNode *SymbianFilesystemNode::getParent() const {
// Root node is its own parent. Still we can't just return this
// as the GUI code will call delete on the old node.
if (!_isPseudoRoot && _path.size() > 3) {
- p = new SymbianFilesystemNode(false);
+ p = new SymbianFilesystemNode(EFalse);
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '\\');
- p->_path = String(start, end - start);
- p->_isValid = true;
- p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path);
+ p->_path = Common::String(start, end - start);
+ p->_isValid = ETrue;
+ p->_isDirectory = ETrue;
+ p->_displayName = lastPathComponent(p->_path, '\\');
}
else
{
- p = new SymbianFilesystemNode(true);
+ p = new SymbianFilesystemNode(ETrue);
}
return p;
}
+Common::SeekableReadStream *SymbianFilesystemNode::openForReading() {
+ return SymbianStdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *SymbianFilesystemNode::openForWriting() {
+ return SymbianStdioStream::makeFromPath(getPath().c_str(), true);
+}
#endif //#if defined (__SYMBIAN32__)
+
+
diff --git a/backends/fs/symbian/symbianstream.cpp b/backends/fs/symbian/symbianstream.cpp
new file mode 100644
index 0000000000..5944cab892
--- /dev/null
+++ b/backends/fs/symbian/symbianstream.cpp
@@ -0,0 +1,274 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+#include "backends/fs/symbian/symbianstream.h"
+#include "common/system.h"
+#include "backends/platform/symbian/src/symbianos.h"
+
+#include <f32file.h>
+
+#define KInputBufferLength 128
+
+// Symbian libc file functionality in order to provide shared file handles
+class TSymbianFileEntry {
+public:
+ RFile _fileHandle;
+ char _inputBuffer[KInputBufferLength];
+ TInt _inputBufferLen;
+ TInt _inputPos;
+ TInt _lastError;
+ TBool _eofReached;
+};
+
+TSymbianFileEntry* CreateSymbianFileEntry(const char* name, const char* mode) {
+ TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
+ fileEntry->_inputPos = KErrNotFound;
+ fileEntry->_lastError = 0;
+ fileEntry->_eofReached = EFalse;
+
+ if (fileEntry != NULL) {
+ TInt modeLen = strlen(mode);
+
+ TPtrC8 namePtr((unsigned char*) name, strlen(name));
+ TFileName tempFileName;
+ tempFileName.Copy(namePtr);
+
+ TInt fileMode = EFileRead;
+
+ if (mode[0] == 'a')
+ fileMode = EFileWrite;
+
+ if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) {
+ fileMode |= EFileStreamText;
+ }
+
+ if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) {
+ fileMode = fileMode| EFileWrite;
+ }
+
+ fileMode = fileMode| EFileShareAny;
+
+ switch(mode[0]) {
+ case 'a':
+ if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ if (fileEntry->_fileHandle.Create(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ delete fileEntry;
+ fileEntry = NULL;
+ }
+ }
+ break;
+ case 'r':
+ if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ delete fileEntry;
+ fileEntry = NULL;
+ }
+ break;
+
+ case 'w':
+ if (fileEntry->_fileHandle.Replace(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ delete fileEntry;
+ fileEntry = NULL;
+ }
+ break;
+ }
+ }
+ return fileEntry;
+}
+
+size_t ReadData(const void* ptr, size_t size, size_t numItems, TSymbianFileEntry* handle) {
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
+ TUint32 totsize = size*numItems;
+ TPtr8 pointer ( (unsigned char*) ptr, totsize);
+
+ // Nothing cached and we want to load at least KInputBufferLength bytes
+ if (totsize >= KInputBufferLength) {
+ TUint32 totLength = 0;
+ if (entry->_inputPos != KErrNotFound) {
+ TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer+entry->_inputPos, entry->_inputBufferLen - entry->_inputPos, KInputBufferLength);
+ pointer.Append(cacheBuffer);
+ entry->_inputPos = KErrNotFound;
+ totLength+=pointer.Length();
+ pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
+ }
+
+ entry->_lastError = entry->_fileHandle.Read(pointer);
+
+ totLength+=pointer.Length();
+
+ pointer.Set((unsigned char*) ptr, totLength, totsize);
+
+ } else {
+ // Nothing in buffer
+ if (entry->_inputPos == KErrNotFound) {
+ TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, KInputBufferLength);
+ entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
+
+ if (cacheBuffer.Length() >= totsize) {
+ pointer.Copy(cacheBuffer.Left(totsize));
+ entry->_inputPos = totsize;
+ entry->_inputBufferLen = cacheBuffer.Length();
+ } else {
+ pointer.Copy(cacheBuffer);
+ entry->_inputPos = KErrNotFound;
+ }
+
+ } else {
+ TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, entry->_inputBufferLen, KInputBufferLength);
+
+ if (entry->_inputPos+totsize < entry->_inputBufferLen) {
+ pointer.Copy(cacheBuffer.Mid(entry->_inputPos, totsize));
+ entry->_inputPos+=totsize;
+ } else {
+
+ pointer.Copy(cacheBuffer.Mid(entry->_inputPos, entry->_inputBufferLen-entry->_inputPos));
+ cacheBuffer.SetLength(0);
+ entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
+
+ if (cacheBuffer.Length() >= totsize-pointer.Length()) {
+ TUint32 restSize = totsize-pointer.Length();
+ pointer.Append(cacheBuffer.Left(restSize));
+ entry->_inputPos = restSize;
+ entry->_inputBufferLen = cacheBuffer.Length();
+ } else {
+ pointer.Append(cacheBuffer);
+ entry->_inputPos = KErrNotFound;
+ }
+ }
+ }
+ }
+
+ if((numItems * size) != pointer.Length() && entry->_lastError == KErrNone) {
+ entry->_eofReached = ETrue;
+ }
+
+ return pointer.Length() / size;
+}
+
+SymbianStdioStream::SymbianStdioStream(void *handle) : _handle(handle) {
+ assert(handle);
+}
+
+SymbianStdioStream::~SymbianStdioStream() {
+ ((TSymbianFileEntry*)(_handle))->_fileHandle.Close();
+
+ delete (TSymbianFileEntry*)(_handle);
+}
+
+bool SymbianStdioStream::err() const {
+ return ((TSymbianFileEntry*)(_handle))->_lastError != 0;
+}
+
+void SymbianStdioStream::clearErr() {
+ ((TSymbianFileEntry*)(_handle))->_lastError = 0;
+ ((TSymbianFileEntry*)(_handle))->_eofReached = 0;
+}
+
+bool SymbianStdioStream::eos() const {
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
+
+ return entry->_eofReached != 0;
+}
+
+int32 SymbianStdioStream::pos() const {
+ TInt pos = 0;
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
+
+ entry->_lastError = entry->_fileHandle.Seek(ESeekCurrent, pos);
+ if (entry->_lastError == KErrNone && entry->_inputPos != KErrNotFound) {
+ pos += (entry->_inputPos - entry->_inputBufferLen);
+ }
+
+ return pos;
+}
+
+int32 SymbianStdioStream::size() const {
+
+ TInt length = 0;
+ ((TSymbianFileEntry*)(_handle))->_fileHandle.Size(length);
+
+ return length;
+}
+
+bool SymbianStdioStream::seek(int32 offs, int whence) {
+ assert(_handle);
+
+ TSeek seekMode = ESeekStart;
+ TInt pos = offs;
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
+
+ switch (whence) {
+ case SEEK_SET:
+ seekMode = ESeekStart;
+ break;
+ case SEEK_CUR:
+ seekMode = ESeekCurrent;
+ if (entry->_inputPos != KErrNotFound) {
+ pos += (entry->_inputPos - entry->_inputBufferLen);
+ }
+ break;
+ case SEEK_END:
+ seekMode = ESeekEnd;
+ break;
+
+ }
+
+ entry->_inputPos = KErrNotFound;
+ entry->_eofReached = EFalse;
+ entry->_fileHandle.Seek(seekMode, pos);
+
+ return true; // FIXME: Probably should return a value based on what _fileHandle.Seek returns
+}
+
+uint32 SymbianStdioStream::read(void *ptr, uint32 len) {
+ return (uint32)ReadData((byte *)ptr, 1, len, (TSymbianFileEntry *)_handle);
+}
+
+uint32 SymbianStdioStream::write(const void *ptr, uint32 len) {
+ TPtrC8 pointer( (unsigned char*) ptr, len);
+
+ ((TSymbianFileEntry*)(_handle))->_inputPos = KErrNotFound;
+ ((TSymbianFileEntry*)(_handle))->_lastError = ((TSymbianFileEntry*)(_handle))->_fileHandle.Write(pointer);
+ ((TSymbianFileEntry*)(_handle))->_eofReached = EFalse;
+
+ if (((TSymbianFileEntry*)(_handle))->_lastError == KErrNone) {
+ return len;
+ }
+
+ return 0;
+}
+
+bool SymbianStdioStream::flush() {
+ ((TSymbianFileEntry*)(_handle))->_fileHandle.Flush();
+ return true;
+}
+
+SymbianStdioStream *SymbianStdioStream::makeFromPath(const Common::String &path, bool writeMode) {
+ void *handle = CreateSymbianFileEntry(path.c_str(), writeMode ? "wb" : "rb");
+ if (handle)
+ return new SymbianStdioStream(handle);
+ return 0;
+}
+
diff --git a/backends/fs/symbian/symbianstream.h b/backends/fs/symbian/symbianstream.h
new file mode 100644
index 0000000000..d783856687
--- /dev/null
+++ b/backends/fs/symbian/symbianstream.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.
+ *
+ * $URL: $
+ * $Id: $
+ *
+ */
+
+#ifndef BACKENDS_FS_SYMBIANSTDIOSTREAM_H
+#define BACKENDS_FS_SYMBIANSTDIOSTREAM_H
+
+#include "common/scummsys.h"
+#include "common/noncopyable.h"
+#include "common/stream.h"
+#include "common/str.h"
+
+class SymbianStdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
+protected:
+ /** File handle to the actual file. */
+ void *_handle;
+
+public:
+ /**
+ * Given a path, invokes fopen on that path and wrap the result in a
+ * StdioStream instance.
+ */
+ static SymbianStdioStream *makeFromPath(const Common::String &path, bool writeMode);
+
+ SymbianStdioStream(void *handle);
+ virtual ~SymbianStdioStream();
+
+ bool err() const;
+ void clearErr();
+ bool eos() const;
+
+ virtual uint32 write(const void *dataPtr, uint32 dataSize);
+ virtual bool flush();
+
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ bool seek(int32 offs, int whence = SEEK_SET);
+ uint32 read(void *dataPtr, uint32 dataSize);
+};
+
+#endif
diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp
index 9839858dd5..69086a95f1 100644
--- a/backends/fs/wii/wii-fs-factory.cpp
+++ b/backends/fs/wii/wii-fs-factory.cpp
@@ -42,7 +42,7 @@ AbstractFilesystemNode *WiiFilesystemFactory::makeCurrentDirectoryFileNode() con
return new WiiFilesystemNode();
}
-AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new WiiFilesystemNode(path, true);
}
#endif
diff --git a/backends/fs/wii/wii-fs-factory.h b/backends/fs/wii/wii-fs-factory.h
index 24badee330..36867a392c 100644
--- a/backends/fs/wii/wii-fs-factory.h
+++ b/backends/fs/wii/wii-fs-factory.h
@@ -33,11 +33,9 @@
*/
class WiiFilesystemFactory : public FilesystemFactory, public Common::Singleton<WiiFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
WiiFilesystemFactory() {};
diff --git a/backends/fs/wii/wii-fs.cpp b/backends/fs/wii/wii-fs.cpp
index e6d0cf4c7e..a620df5471 100644
--- a/backends/fs/wii/wii-fs.cpp
+++ b/backends/fs/wii/wii-fs.cpp
@@ -23,6 +23,7 @@
#if defined(__WII__)
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <sys/dir.h>
@@ -37,8 +38,8 @@
*/
class WiiFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory, _isReadable, _isWritable;
public:
@@ -50,51 +51,30 @@ public:
/**
* Creates a WiiFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
*/
- WiiFilesystemNode(const String &path, bool verify);
+ WiiFilesystemNode(const Common::String &path, bool verify);
virtual bool exists() const;
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return _isReadable; }
virtual bool isWritable() const { return _isWritable; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
private:
virtual void setFlags();
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
void WiiFilesystemNode::setFlags() {
struct stat st;
@@ -118,12 +98,12 @@ WiiFilesystemNode::WiiFilesystemNode() {
setFlags();
}
-WiiFilesystemNode::WiiFilesystemNode(const String &p, bool verify) {
+WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, bool verify) {
assert(p.size() > 0);
_path = p;
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '/');
if (verify)
setFlags();
@@ -134,10 +114,10 @@ bool WiiFilesystemNode::exists() const {
return stat(_path.c_str (), &st) == 0;
}
-AbstractFilesystemNode *WiiFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *WiiFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -160,15 +140,15 @@ bool WiiFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
continue;
- String newPath(_path);
+ Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += filename;
bool isDir = S_ISDIR(st.st_mode);
- if ((mode == FilesystemNode::kListFilesOnly && isDir) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !isDir))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && isDir) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !isDir))
continue;
if (isDir)
@@ -187,9 +167,17 @@ AbstractFilesystemNode *WiiFilesystemNode::getParent() const {
return 0;
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
+
+ return new WiiFilesystemNode(Common::String(start, end - start), true);
+}
+
+Common::SeekableReadStream *WiiFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new WiiFilesystemNode(String(start, end - start), true);
+Common::WriteStream *WiiFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined(__WII__)
diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp
index 7fbf4f7fff..ed273bb746 100644
--- a/backends/fs/windows/windows-fs-factory.cpp
+++ b/backends/fs/windows/windows-fs-factory.cpp
@@ -26,8 +26,6 @@
#include "backends/fs/windows/windows-fs-factory.h"
#include "backends/fs/windows/windows-fs.cpp"
-DECLARE_SINGLETON(WindowsFilesystemFactory);
-
AbstractFilesystemNode *WindowsFilesystemFactory::makeRootFileNode() const {
return new WindowsFilesystemNode();
}
@@ -36,7 +34,7 @@ AbstractFilesystemNode *WindowsFilesystemFactory::makeCurrentDirectoryFileNode()
return new WindowsFilesystemNode("", true);
}
-AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new WindowsFilesystemNode(path, false);
}
#endif
diff --git a/backends/fs/windows/windows-fs-factory.h b/backends/fs/windows/windows-fs-factory.h
index 0745b286a8..3c7b80942d 100644
--- a/backends/fs/windows/windows-fs-factory.h
+++ b/backends/fs/windows/windows-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef WINDOWS_FILESYSTEM_FACTORY_H
#define WINDOWS_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class WindowsFilesystemFactory : public FilesystemFactory, public Common::Singleton<WindowsFilesystemFactory> {
+class WindowsFilesystemFactory : public FilesystemFactory {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- WindowsFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*WINDOWS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp
index 2105317a96..c59c7dbe71 100644
--- a/backends/fs/windows/windows-fs.cpp
+++ b/backends/fs/windows/windows-fs.cpp
@@ -24,24 +24,17 @@
#ifdef WIN32
-#ifdef ARRAYSIZE
-#undef ARRAYSIZE
-#endif
-#ifdef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
+#ifdef _WIN32_WCE
#undef GetCurrentDirectory
#endif
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef _WIN32_WCE
-#include <windows.h>
-// winnt.h defines ARRAYSIZE, but we want our own one...
-#undef ARRAYSIZE
-#endif
#include <tchar.h>
// F_OK, R_OK and W_OK are not defined under MSVC, so we define them here
@@ -66,8 +59,8 @@
*/
class WindowsFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isPseudoRoot;
bool _isValid;
@@ -89,23 +82,26 @@ public:
* path=c:\foo\bar.txt, currentDir=true -> current directory
* path=NULL, currentDir=true -> current directory
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
* @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory.
*/
- WindowsFilesystemNode(const String &path, const bool currentDir);
+ WindowsFilesystemNode(const Common::String &path, const bool currentDir);
virtual bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
private:
/**
* Adds a single WindowsFilesystemNode to a given list.
@@ -113,7 +109,7 @@ private:
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
- * @param base String with the directory being listed.
+ * @param base Common::String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data);
@@ -121,7 +117,7 @@ private:
/**
* Converts a Unicode string to Ascii format.
*
- * @param str String to convert from Unicode to Ascii.
+ * @param str Common::String to convert from Unicode to Ascii.
* @return str in Ascii format.
*/
static char *toAscii(TCHAR *str);
@@ -129,36 +125,12 @@ private:
/**
* Converts an Ascii string to Unicode format.
*
- * @param str String to convert from Ascii to Unicode.
+ * @param str Common::String to convert from Ascii to Unicode.
* @return str in Unicode format.
*/
static const TCHAR* toUnicode(const char *str);
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * c:\foo\bar.txt would return "\bar.txt"
- * c:\foo\bar\ would return "\bar\"
- *
- * @param str Path to obtain the last component from.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
-
void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) {
WindowsFilesystemNode entry;
char *asciiName = toAscii(find_data->cFileName);
@@ -170,8 +142,8 @@ void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const c
isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false);
- if ((!isDirectory && mode == FilesystemNode::kListDirectoriesOnly) ||
- (isDirectory && mode == FilesystemNode::kListFilesOnly))
+ if ((!isDirectory && mode == Common::FilesystemNode::kListDirectoriesOnly) ||
+ (isDirectory && mode == Common::FilesystemNode::kListFilesOnly))
return;
entry._isDirectory = isDirectory;
@@ -222,7 +194,7 @@ WindowsFilesystemNode::WindowsFilesystemNode() {
#endif
}
-WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool currentDir) {
+WindowsFilesystemNode::WindowsFilesystemNode(const Common::String &p, const bool currentDir) {
if (currentDir) {
char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
@@ -232,7 +204,7 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current
_path = p;
}
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '\\');
// Check whether it is a directory, and whether the file actually exists
DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str()));
@@ -251,10 +223,10 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current
_isPseudoRoot = false;
}
-AbstractFilesystemNode *WindowsFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *WindowsFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '\\')
newPath += '\\';
newPath += n;
@@ -322,17 +294,25 @@ AbstractFilesystemNode *WindowsFilesystemNode::getParent() const {
WindowsFilesystemNode *p = new WindowsFilesystemNode();
if (_path.size() > 3) {
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '\\');
p = new WindowsFilesystemNode();
- p->_path = String(start, end - start);
+ p->_path = Common::String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path);
+ p->_displayName = lastPathComponent(p->_path, '\\');
p->_isPseudoRoot = false;
}
return p;
}
+Common::SeekableReadStream *WindowsFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *WindowsFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
#endif //#ifdef WIN32
diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 57a5a1ea32..9e86181674 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -28,7 +28,7 @@
* both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html)
*/
-#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__)
+#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
#include "common/util.h"
#include "sound/musicplugin.h"
diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp
new file mode 100644
index 0000000000..addb23c6bd
--- /dev/null
+++ b/backends/midi/stmidi.cpp
@@ -0,0 +1,155 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Raw MIDI output for the Atari ST line of computers.
+ * Based on the ScummVM SEQ & CoreMIDI drivers.
+ * Atari code by Keith Scroggins
+ * We, unfortunately, could not use the SEQ driver because the /dev/midi under
+ * FreeMiNT (and hence in libc) is considered to be a serial port for machine
+ * access. So, we just use OS calls then to send the data to the MIDI ports
+ * directly. The current implementation is sending 1 byte at a time because
+ * in most cases we are only sending up to 3 bytes, I believe this saves a few
+ * cycles. I might change so sysex messages are sent the other way later.
+ */
+
+#if defined __MINT__
+
+#include <osbind.h>
+#include "sound/mpu401.h"
+#include "common/util.h"
+#include "sound/musicplugin.h"
+
+class MidiDriver_STMIDI : public MidiDriver_MPU401 {
+public:
+ MidiDriver_STMIDI() : _isOpen (false) { }
+ int open();
+ void close();
+ void send(uint32 b);
+ void sysEx(const byte *msg, uint16 length);
+
+private:
+ bool _isOpen;
+};
+
+int MidiDriver_STMIDI::open() {
+ if ((_isOpen) && (!Bcostat(4)))
+ return MERR_ALREADY_OPEN;
+ warning("ST Midi Port Open");
+ _isOpen = true;
+ return 0;
+}
+
+void MidiDriver_STMIDI::close() {
+ MidiDriver_MPU401::close();
+ _isOpen = false;
+}
+
+void MidiDriver_STMIDI::send(uint32 b) {
+
+ byte status_byte = (b & 0x000000FF);
+ byte first_byte = (b & 0x0000FF00) >> 8;
+ byte second_byte = (b & 0x00FF0000) >> 16;
+
+// warning("ST MIDI Packet sent");
+
+ switch (b & 0xF0) {
+ case 0x80: // Note Off
+ case 0x90: // Note On
+ case 0xA0: // Polyphonic Key Pressure
+ case 0xB0: // Controller
+ case 0xE0: // Pitch Bend
+ Bconout(3, status_byte);
+ Bconout(3, first_byte);
+ Bconout(3, second_byte);
+ break;
+ case 0xC0: // Program Change
+ case 0xD0: // Aftertouch
+ Bconout(3, status_byte);
+ Bconout(3, first_byte);
+ break;
+ default:
+ fprintf(stderr, "Unknown : %08x\n", (int)b);
+ break;
+ }
+}
+
+void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
+ if (length > 254) {
+ warning ("Cannot send SysEx block - data too large");
+ return;
+ }
+
+ const byte *chr = msg;
+ warning("Sending SysEx Message");
+
+ Bconout(3, '0xF0');
+ for (; length; --length, ++chr) {
+ Bconout(3,((unsigned char) *chr & 0x7F));
+ }
+ Bconout(3, '0xF7');
+}
+
+// Plugin interface
+
+class StMidiMusicPlugin : public MusicPluginObject {
+public:
+ const char *getName() const {
+ return "STMIDI";
+ }
+
+ const char *getId() const {
+ return "stmidi";
+ }
+
+ MusicDevices getDevices() const;
+ PluginError createInstance(Audio::Mixer *mixer, MidiDriver **mididriver)
+ 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;
+}
+
+PluginError StMidiMusicPlugin::createInstance(Audio::Mixer *mixer, MidiDriver **mididriver) const {
+ *mididriver = new MidiDriver_STMIDI();
+
+ return kNoError;
+}
+
+MidiDriver *MidiDriver_STMIDI_create(Audio::Mixer *mixer) {
+ MidiDriver *mididriver;
+
+ StMidiMusicPlugin p;
+ p.createInstance(mixer, &mididriver);
+
+ return mididriver;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
+ //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+//#endif
+
+#endif
diff --git a/backends/module.mk b/backends/module.mk
index 6642a3a281..8944e9a3db 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -1,6 +1,8 @@
MODULE := backends
MODULE_OBJS := \
+ fs/abstract-fs.o \
+ fs/stdiostream.o \
fs/amigaos4/amigaos4-fs-factory.o \
fs/ds/ds-fs-factory.o \
fs/palmos/palmos-fs-factory.o \
@@ -17,6 +19,7 @@ MODULE_OBJS := \
midi/coremidi.o \
midi/quicktime.o \
midi/seq.o \
+ midi/stmidi.o \
midi/timidity.o \
midi/dmedia.o \
midi/windows.o \
diff --git a/backends/platform/dc/dc-fs.cpp b/backends/platform/dc/dc-fs.cpp
index f4dc4037df..c4f1d76f10 100644
--- a/backends/platform/dc/dc-fs.cpp
+++ b/backends/platform/dc/dc-fs.cpp
@@ -24,6 +24,7 @@
#include "dc.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <ronin/cdfs.h>
#include <stdio.h>
@@ -34,75 +35,50 @@
*
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
-/* A file */
class RoninCDFileNode : public AbstractFilesystemNode {
protected:
- String _path;
- static const char *lastPathComponent(const Common::String &str);
+ Common::String _path;
public:
- RoninCDFileNode(const String &path) : _path(path) {};
+ RoninCDFileNode(const Common::String &path) : _path(path) {};
virtual bool exists() const { return true; }
- virtual String getName() const { return lastPathComponent(_path); }
- virtual String getPath() const { return _path; }
+ virtual Common::String getName() const { return lastPathComponent(_path, '/'); }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return false; }
virtual bool isReadable() const { return true; }
virtual bool isWritable() const { return false; }
- virtual AbstractFilesystemNode *getChild(const String &n) const { return NULL; }
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const { return NULL; }
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const { return false; }
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
static AbstractFilesystemNode *makeFileNodePath(const Common::String &path);
};
/* A directory */
class RoninCDDirectoryNode : public RoninCDFileNode {
public:
- RoninCDDirectoryNode(const String &path) : RoninCDFileNode(path) {};
+ RoninCDDirectoryNode(const Common::String &path) : RoninCDFileNode(path) {};
virtual bool isDirectory() const { return true; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
};
/* A file/directory which does not exist */
class RoninCDNonexistingNode : public RoninCDFileNode {
public:
- RoninCDNonexistingNode(const String &path) : RoninCDFileNode(path) {};
+ RoninCDNonexistingNode(const Common::String &path) : RoninCDFileNode(path) {};
virtual bool exists() const { return false; }
virtual bool isReadable() const { return false; }
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *RoninCDFileNode::lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
-AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &path)
-{
+AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &path) {
assert(path.size() > 0);
int fd;
@@ -110,18 +86,16 @@ AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &
if ((fd = open(path.c_str(), O_RDONLY)) >= 0) {
close(fd);
return new RoninCDFileNode(path);
- }
- else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
+ } else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
close(fd);
return new RoninCDDirectoryNode(path);
- }
- else {
+ } else {
return NULL;
}
}
-AbstractFilesystemNode *RoninCDDirectoryNode::getChild(const String &n) const {
- String newPath(_path);
+AbstractFilesystemNode *RoninCDDirectoryNode::getChild(const Common::String &n) const {
+ Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -139,20 +113,20 @@ bool RoninCDDirectoryNode::getChildren(AbstractFSList &myList, ListMode mode, bo
// ... loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL) {
- String newPath(_path);
+ Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += dp->d_name;
if (dp->d_size < 0) {
// Honor the chosen mode
- if (mode == FilesystemNode::kListFilesOnly)
+ if (mode == Common::FilesystemNode::kListFilesOnly)
continue;
myList.push_back(new RoninCDDirectoryNode(newPath+"/"));
} else {
// Honor the chosen mode
- if (mode == FilesystemNode::kListDirectoriesOnly)
+ if (mode == Common::FilesystemNode::kListDirectoriesOnly)
continue;
myList.push_back(new RoninCDFileNode(newPath));
@@ -168,9 +142,18 @@ AbstractFilesystemNode *RoninCDFileNode::getParent() const {
return 0;
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
+
+ return new RoninCDDirectoryNode(Common::String(start, end - start));
+}
+
+
+Common::SeekableReadStream *RoninCDFileNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new RoninCDDirectoryNode(String(start, end - start));
+Common::WriteStream *RoninCDFileNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
AbstractFilesystemNode *OSystem_Dreamcast::makeRootFileNode() const {
diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 91c851506f..a4a53e0f65 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -146,12 +146,12 @@ struct Dir
{
char name[252];
char deficon[256];
- FilesystemNode node;
+ Common::FilesystemNode node;
};
static Game the_game;
-static bool isIcon(const FilesystemNode &entry)
+static bool isIcon(const Common::FilesystemNode &entry)
{
int l = entry.getDisplayName().size();
if (l>4 && !strcasecmp(entry.getDisplayName().c_str()+l-4, ".ICO"))
@@ -198,14 +198,14 @@ static int findGames(Game *games, int max)
{
Dir *dirs = new Dir[MAX_DIR];
int curr_game = 0, curr_dir = 0, num_dirs = 1;
- dirs[0].node = FilesystemNode("");
+ dirs[0].node = Common::FilesystemNode("");
while (curr_game < max && curr_dir < num_dirs) {
strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().c_str(), 252);
dirs[curr_dir].name[251] = '\0';
dirs[curr_dir].deficon[0] = '\0';
- FSList files, fslist;
- dirs[curr_dir++].node.getChildren(fslist, FilesystemNode::kListAll);
- for (FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
+ Common::FSList files, fslist;
+ dirs[curr_dir++].node.getChildren(fslist, Common::FilesystemNode::kListAll);
+ for (Common::FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
++entry) {
if (entry->isDirectory()) {
if (num_dirs < MAX_DIR && strcasecmp(entry->getDisplayName().c_str(),
diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp
index 6ab8fc4558..d17e1f6213 100644
--- a/backends/platform/dc/vmsave.cpp
+++ b/backends/platform/dc/vmsave.cpp
@@ -269,14 +269,15 @@ class InVMSave : public Common::InSaveFile {
private:
char *buffer;
int _pos, _size;
+ bool _eos;
uint32 read(void *buf, uint32 cnt);
- void skip(uint32 offset);
- void seek(int32 offs, int whence);
+ bool skip(uint32 offset);
+ bool seek(int32 offs, int whence);
public:
InVMSave()
- : _pos(0), buffer(NULL)
+ : _pos(0), buffer(NULL), _eos(false)
{ }
~InVMSave()
@@ -285,9 +286,10 @@ public:
delete[] buffer;
}
- bool eos() const { return _pos >= _size; }
- uint32 pos() const { return _pos; }
- uint32 size() const { return _size; }
+ bool eos() const { return _eos; }
+ void clearErr() { _eos = false; }
+ int32 pos() const { return _pos; }
+ int32 size() const { return _size; }
bool readSaveGame(const char *filename)
{ return ::readSaveGame(buffer, _size, filename); }
@@ -312,8 +314,8 @@ public:
~OutVMSave();
- bool ioFailed() const { return iofailed; }
- void clearIOFailed() { iofailed = false; }
+ bool err() const { return iofailed; }
+ void clearErr() { iofailed = false; }
void finalize();
};
@@ -370,6 +372,7 @@ uint32 InVMSave::read(void *buf, uint32 cnt)
int nbyt = cnt;
if (_pos + nbyt > _size) {
cnt = (_size - _pos);
+ _eos = true;
nbyt = cnt;
}
if (nbyt)
@@ -378,15 +381,16 @@ uint32 InVMSave::read(void *buf, uint32 cnt)
return cnt;
}
-void InVMSave::skip(uint32 offset)
+bool InVMSave::skip(uint32 offset)
{
int nbyt = offset;
if (_pos + nbyt > _size)
nbyt = (_size - _pos);
_pos += nbyt;
+ return true;
}
-void InVMSave::seek(int32 offs, int whence)
+bool InVMSave::seek(int32 offs, int whence)
{
switch(whence) {
case SEEK_SET:
@@ -403,6 +407,8 @@ void InVMSave::seek(int32 offs, int whence)
_pos = 0;
else if (_pos > _size)
_pos = _size;
+ _eos = false;
+ return true;
}
uint32 OutVMSave::write(const void *buf, uint32 cnt)
diff --git a/backends/platform/ds/arm7/Makefile b/backends/platform/ds/arm7/Makefile
index 55db7f8cad..82637845db 100644
--- a/backends/platform/ds/arm7/Makefile
+++ b/backends/platform/ds/arm7/Makefile
@@ -107,7 +107,7 @@ MAPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.map)))
export OFILES := $(MAPFILES:.map=.o) $(RAWFILES:.raw=.o) $(PALFILES:.pal=.o) $(BINFILES:.bin=.o) $(PCXFILES:.pcx=.o)\
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
-export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) -I- -I$(CURDIR)/../commoninclude\
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) -Iquote -I$(CURDIR)/../commoninclude\
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include/nds)\
-I$(CURDIR)/$(BUILD) -I$(CURDIR)/source/libcartreset
diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp
index bee39f1efe..d252ed44de 100644
--- a/backends/platform/ds/arm7/source/main.cpp
+++ b/backends/platform/ds/arm7/source/main.cpp
@@ -233,7 +233,7 @@ void DummyHandler() {
REG_IF = REG_IF;
}
-uint16 powerManagerWrite(uint32 command, u32 data, bool enable) {
+void powerManagerWrite(uint32 command, u32 data, bool enable) {
uint16 result;
SerialWaitBusy();
@@ -261,9 +261,6 @@ uint16 powerManagerWrite(uint32 command, u32 data, bool enable) {
REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
REG_SPIDATA = enable? (result | data): (result & ~data);
SerialWaitBusy();
-
- // FIXME: This function should either return something, or have a comment
- // explaining why it is valid for it to not return something. :-)
}
/*
diff --git a/backends/platform/ds/arm9/dist/readme_ds.txt b/backends/platform/ds/arm9/dist/readme_ds.txt
new file mode 100644
index 0000000000..f77da418c9
--- /dev/null
+++ b/backends/platform/ds/arm9/dist/readme_ds.txt
@@ -0,0 +1,840 @@
+
+
+
+ The official port of ScummVM
+ to the Nintendo DS handheld console
+ by Neil Millstone (agentq)
+ http://scummvm.drunkencoders.com
+------------------------------------------------------------------------
+Visit the main ScummVM website <http://www.scummvm.org>
+
+
+
+
+ Contents
+ ------------------------------------------------------------------------
+
+
+
+ * What's New?
+ * What is ScummVM DS?
+ * Features
+ * Screenshots
+ * How to Get ScummVM DS Onto Your DS - Simple Explanation
+ o Using a CF/SD/Mini SD/Micro SD card reader and a DLDI driver
+ o Instructions for specific card readers
+ * What to do if saving doesn't work or your card gets corruped -
+ force SRAM saves
+ * How to use ScummVM DS
+ * Game Specific Controls
+ * DS Options Screen
+ * Which games are compatible with ScummVM DS
+ * Predictive dictionary for Sierra AGI games
+ * Converting your CD audio
+ * Converting speech to MP3 format
+ * Frequently Asked Questions
+ * Downloads
+ * Contributors
+ * Donations and Getting Help
+ * Building from Sources
+
+
+
+ What's New?
+ ------------------------------------------------------------------------
+
+ScummVM DS 0.12.0
+
+ * New games supported: Lure of the Temptress, Nippon Safes, Lost in Time.
+ * New laptop-style trackpad input method. Uses relative movement when you
+ drag on the touch screen.
+ * New option which allows you to drag to hover, tap the touch screen to
+ click, and double tap the screen to right click.
+ * Reorganised DS Options screen into three tabs for clearer navigation
+ * New top screen scaling options let you choose the scaling factor used
+ on startup.
+ * The usual round of bug fixes.
+
+
+ScummVM DS 0.11.1
+
+ * Bugfix release - No new DS port features
+
+
+ScummVM DS 0.11.0
+
+ * New games supported: Elvira 1 and 2, Waxworks (Amiga version)
+ * Software scaler for improved image quality. Turn it on using the DS options
+ screen (press select during the game). Thanks to Tramboi and Robin Watts for
+ this feature!
+ * Function keys added to virtual keyboard (used in AGI games)
+ * Plenty of bug fixes
+
+ What is ScummVM DS?
+ ------------------------------------------------------------------------
+
+ScummVM DS is a part of the ScummVM project. The ScummVM project is an
+attempt to re-engineer many classic point and click adventure games of the
+80s and 90s to run on modern computer hardware. Technology has changed a
+lot since these games were written, and so ScummVM attempts to replicate the
+gameplay of the original games in exacting details, without any of the original
+code that the game ran on. ScummVM needs a copy of the original game, in order
+to take the graphics, sound, and scripts that made the game work.
+
+ScummVM is written in such a way that it can be 'ported' from one type of
+machine to another, and ScummVM DS is a port of ScummVM to the Nintendo DS
+handheld games console.
+
+
+ Features
+ ------------------------------------------------------------------------
+
+ * Runs nearly all of Lucasarts' SCUMM games up to and including Sam
+ & Max Hit the Road
+ * Runs many non-Lucasarts point-and-click adventures too
+ * Supports sound
+ * Provides a GUI to change settings and choose games
+ * Supports using the DS touch screen for controls
+ * Suports saving games to compatible flash cards
+ * All games run at pretty much full speed
+
+
+
+
+
+ How to Get ScummVM DS Onto Your DS - Simple Explanation
+ ------------------------------------------------------------------------
+
+Nintendo don't want you to run ScummVM on your DS. They control
+which companies can make games on the DS, and there is an expensive
+process to go through in order to be licenced. Having to pay for
+this would prevent me from giving away ScummVM for free.
+
+So, the result is that to run ScummVM on your DS you'll need an
+unofficial card reader. There are many of these, and all are different.
+Popular models at the time of writing are the R4DS and the M3DS Real,
+but many different models work. You need to buy one of these, and at
+MicroSD card to go with it.
+
+There are also slot-2 card readers which fit into the bottom slot on
+your DS, usually used for Game Boy Advance games. These are less common
+these days, and although they have certain advantages, the details of
+these are beyond the scope of this website. Information on these is
+quite easy to find by searching.
+
+Once you have your card reader and a MicroSD card, you will also need
+a copy of the game you want to run. ScummVM can run a large variety
+of games, but you must own a real boxed copy of the game. These games
+are still under copyright, and it is illegal to copy them from a friend
+or download them from the Internet without paying. The exception to
+this are the three Revolution Software games. These are 'Beneath a
+Steel Sky', 'Lure of the Temptress' and 'Flight of the Amazon Queen'.
+Revolution have kindly allowed us to give these games away for free.
+You can download them from the main ScummVM site at
+<http://www.scummvm.org/downloads.php>
+
+NOTE: Previous version of ScummVM DS supported a method which used a
+zip file to run games on unsupported flash card readers. This method
+is no longer supported.
+
+
+ How to Get ScummVM DS Onto Your DS - Using a CF/SD/Mini SD/Micro
+ SD card reader and a DLDI driver
+ ------------------------------------------------------------------------
+
+ScummVM DS needs something called a DLDI driver to run on each make
+and model of card reader. Many modern card readers (R4DS, M3 DS Real)
+handle this autmatically and for those, you don't have to do anything.
+Just running ScummVM on the card will handle this step for you.
+For others, you will need to follow the steps in this section before
+ScummVM DS will work.
+
+All DS card readers are different in the way that they work. In order to
+support many different card readers, ScummVM DS uses a DLDI driver installed
+into the ScummVM DS code. This is done using a program called DLDITool
+which you can download and run on your computer. Each DLDI driver is
+designed to tell ScummVM DS how to use a specific type of card reader.
+These drivers can be used with any homebrew program which supports the
+DLDI interface.
+
+While each card reader should work with these instructions, there are
+some exceptions. Please read the card reader notes
+section to see if there is any specific information about your card reader.
+
+Here is what you need to do:
+
+ * Visit the DLDI page <http://dldi.drunkencoders.com/> and
+ download the executable for DLDITool for your operating system
+ (versions are available for Windows, Linux, and MacOS)
+ * Download the DLDI for your card reader. This is the big table at
+ the top of the page. The first column marked DLDI is the one you
+ want. You should get a single file with a .dldi extension.
+ * Extract DLDITool into a folder, and put the DLDI of your choice in
+ the same folder.
+ * If you're using the command line version of DLDITool enter the
+ following at a command prompt:
+
+ dlditool <dldiname> <scummvm nds name>
+
+
+ If you're using the Windows GUI version, double click on
+ dlditool32.exe, select your card reader from the box, drag your
+ ScummVM binaries (either the .nds, or the .ds.gba version
+ depending on your card reader. I think only Supercards use the
+ .ds.gba files) into the lower box, then click patch.
+
+ Either way, you should see 'Patched Successfully'. If you don't,
+ you're doing something wrong.
+
+ You need to patch one of the builds labeled A - F depending on
+ which game you want to run. See the table on the ScummVM DS
+ website to see which games are supported by which build.
+
+ * Put the patched .nds or .ds.gba files on your flash card. If
+ you're using the Supercard, you will need to use the .ds.gba
+ files, but rename them to .nds.
+ * Put your game data in any folder on the card. Do NOT use a zip file.
+ * Boot up your DS and run ScummVM.
+ * Click 'Add Game', browse to the folder with your game data, click
+ 'Choose', then 'OK'. Click 'Start' to run the game.
+
+If your copy of ScummVM DS has been successfully patched, you will get a
+message on the top screen that looks like this:
+
+ DLDI Device:
+ GBA Movie Player (Compact Flash)
+
+The message should show the name of your card reader. If it is wrong,
+you have used the wrong DLDI file.
+
+If you haven't patched your .nds file, you will get the following message
+
+ DLDI Driver not patched!
+ DLDI Initialise failed.
+
+In this case, you've made a mistake following the above instructions, or
+have patched the wrong file.
+
+You may also see the following message:
+
+ DLDI Device:
+ GBA Movie Player (Compact Flash)
+ DLDI Initialise failed.
+
+In this case, the driver did not start up correctly. The driver is
+probably broken, or you've used the wrong one for your card reader.
+
+In the case of the Supercard, M3 Lite and DS Link, there are several
+drivers available. You might want to try one of the others.
+
+This version of ScummVM DS will run on any card reader that has a DLDI
+driver available. If yours doesn't, you need to pressure your card
+reader manufacturer to release one.
+
+DO NOT EMAIL ME TO ASK ME TO CREATE A DRIVER FOR YOUR CARD READER, I
+CANNOT DO THIS.
+
+
+ How to Get ScummVM DS Onto Your DS - Instructions for specific
+ card readers
+ ------------------------------------------------------------------------
+
+ * *GBAMP CF:* You need to upload replacement firmware to your card
+ reader before it will work. You can download the firmware program
+ here <http://chishm.drunkencoders.com/NDSMP/index.html>. Name your
+ .nds file _BOOT_MP.nds.
+ * *M3 CF/SD:* Copy the .nds file to your card with the M3 Game
+ Manager in order to avoid an annoying message when you boot your
+ M3. Use the default options to copy the file. Be sure to press 'A'
+ in the M3 browser to start the .nds file, and not 'Start', or it
+ won't work.
+ * *M3 CF/SD:* Copy the .nds file to your card with the M3 Game
+ Manager in order to avoid an annoying message when you boot your
+ M3. Use the default options to copy the file. Be sure to press 'A'
+ in the M3 browser to start the .nds file, and not 'Start', or it
+ won't work.
+ * *Supercard CF/SD (slot-2):* Use the .ds.gba files to run ScummVM
+ on the Supercard. Other than that, just follow the instructions as
+ normal.
+ * *Supercard Lite (slot-2):* It has been reported that only the
+ standard Supercard driver and the Moonshell version work with
+ ScummVM DS.
+ * *Datel Max Media Dock: * If you haven't already, upgrade your
+ firmware to the latest version. The firmware that came with my Max
+ Media Dock was unable to run ScummVM DS at all. Click here to
+ visit Datel's support page and download the latest firmware
+ <http://us.codejunkies.com/mpds/support.htm>
+ * *NinjaDS*: There are firmware upgrades for this device, but for
+ me, ScummVM DS ran straight out of the box. Visit this page
+ <http://www.ninjads.com/news.html> to download the latest firmware
+ if you want. If you have installed FlashMe on your DS, it will
+ make your DS crash on boot when the NinjaDS is inserted. You can
+ hold the 'select' button during boot to disable FlashMe, which
+ will allow the NinjaDS to work. Due to this, it is not recommended
+ to install FlashMe if you use a NinjaDS.
+ * *EZ-Flash*: This card reader uses .ds.gba files from the ScummVM
+ archive. Rename them to .nds before patching them with the DLDI
+ patcher.
+ * *R4DS*: If you upgrade the firmware for your R4DS to version 1.10
+ or later, the card will autmatically DLDI patch the game, meaning
+ you don't have to use dlditool to patch the .NDS file. This makes
+ things a lot easier!
+ * *M3DS Real*: This card autmatically DLDI patches the game, meaning
+ that you do not need to do this yourself.
+
+
+
+ Which games are compatible with ScummVM DS?
+ ------------------------------------------------------------------------
+
+I'm glad you asked. Here is a list of the compatible games in version
+0.12.0. Demo versions of the games listed should work too.
+
+Flight of the Amazon Queen, Beneath a Steel Sky, and Lure of the
+Temptress have generously been released as freeware by the original
+authors, Revolution Software <http://www.revolution.co.uk/>. This is a
+great thing and we should support Revolution for being so kind to us.
+You can download the game data from the official ScummVM download page
+<http://www.scummvm.org/downloads.php>.
+
+The other games on this list are commercial, and still under copyright,
+which means downloading them without paying for it is illegal. You can
+probably find a second-hand copy on eBay. Please don't email me to ask
+for a copy, as I am unable to send it to you.
+
+Game Build Notes
+
+Manic Mansion A
+
+Zak McKracken and the Alien Mindbenders A
+
+Indiana Jones and the Last Crusade A
+
+Loom A
+
+Passport to Adventure A
+
+The Secret of Monkey Island A
+
+Monkey Island 2: LeChuck's Revenge A
+
+Indiana Jones and the Fate of Atlantis A
+
+Day of the Tentacle A
+
+Sam & Max Hit the Road A Some slowdown in a few scenes
+ when MP3 audio is enabled
+
+Bear Stormin' (DOS) A
+
+Fatty Bear's Birthday Surprise (DOS) A
+
+Fatty Bear's Fun Pack (DOS) A
+
+Putt-Putt's Fun Pack (DOS) A
+
+Putt-Putt Goes to the Moon (DOS) A
+
+Putt-Putt Joins the Parade (DOS) A Can sometimes crash due to low memory
+
+Beneath a Steel Sky B
+
+Flight of the Amazon Queen B
+
+Simon the Sorcerer 1 C Zoomed view does not follow the
+ speaking character
+Simon the Sorcerer 2 C Zoomed view does not follow the
+ speaking character
+Elvira 1 C
+
+Elvira 2 C
+
+Waxworks (Amiga version) C
+
+Gobliiins D
+
+Gobliins 2 D
+
+Goblins 3 D
+
+Ween: The Prophecy D
+
+Bargon Attack D
+
+Lost in Time D
+
+Future Wars D
+
+All Sierra AGI games.
+For a complete list, see this page
+<http://wiki.scummvm.org/index.php/AGI> D
+
+Inherit the Earth E
+
+The Legend of Kyrandia F Zoomed view does not follow the
+ speaking character
+
+Lure of the Temptress G
+
+Nippon Safes G
+
+There is no support for Full Throttle, The Dig, or The Curse of Monkey
+Island because of memory issues. There simply is not enough RAM on the
+DS to run these games. Sorry. Also there is no support for Windows Humongous
+Entertainment games. The extra code required to make this work uses up
+too much RAM.
+
+
+ What to do when saving doesn't work or your card gets corrupted -
+ forcing SRAM Saves
+ ------------------------------------------------------------------------
+
+This method only works for cards which use the Game Boy Advance slot on the
+bottom of your DS.
+
+If ScummVM DS cannot save games to your SD card, or it causes corruption
+when it does, you can force it to use GBA SRAM to save the game. This
+uses your flash cart reader's GBA features to save the game to a .sav or
+.dat file (depending on the reader). Only slot-2 devices can use SRAM saves,
+and only ones with support for GBA games.
+
+If you want to use SRAM save, just create a text file called scummvm.ini
+(or scummvmb.ini, scummvmc.ini for builds B or C) in the root of your
+card which contains the following:
+
+[ds]
+forcesramsave=true
+
+When you boot your game, ScummVM DS will not save games to your SD card
+directly, instead it will save to GBA SRAM. On most cards, you need to
+transfer the data to your SD card by rebooting and using your card
+reader's boot-up menu. Using this method, around four saves can me made.
+
+One disadvantage of forcing SRAM saves is that your settings won't be
+saved. You can add games manually to the ini file so that you don't have
+to select them on each boot. Just add a section like the following on
+for each game on your card.
+
+[monkey2]
+description=Monkey Island 2: LeChuck's Revenge (English/DOS)
+path=mp:/MONKEY2
+
+
+ How to Use ScummVM
+ ------------------------------------------------------------------------
+
+Once you've booted up ScummVM, you'll see the start up screen.
+
+ 1. Tap the 'Add' button with the pen, then browse to the folder
+ containing your game data. Once you have clicked on your folder, you will
+ not see any files inside. This is normal, as the folder selector only shows
+ folders!
+
+ 2. Click the 'Choose' button.
+
+ 3. You will get some options for the game. You can usually just click 'Ok' to
+ this.
+
+ 4. Now click on the name of the game you want to play from the list and
+ click 'Start'. Your game will start!
+
+You can use the B button to skip cutscenes, and the select button to
+show an options menu which will let you tweak the DS contols, including
+switch between scaled and unscaled video modes. The text is clearer in
+the unscaled mode, but the whole game doesn't fit on the screen. To
+scroll around, hold either shoulder button and use the D-pad or drag the
+screen around with the stylus. Even in scaled mode, a small amount is
+missing from the top and bottom of the screen. You can scroll around to
+see those areas. The top screen shows a zoomed-in view. This scrolls
+around to focus on the character who's speaking, and also follows where
+the pen touches the screen. You can change the zoom level by holding one
+of the shoulder buttons and pressing B to zoom in and A to zoom out.
+
+Press the start button for the in-game menu where you can load or save
+your game (this works in Lucasarts games, other games vary). Saves will
+write directly to your flash card. You can choose the folder where they
+are stored using the GUI that appears when you boot up. If you're using
+a GBA Flash Cartridge, or an unsupported flash card adaptor, you will be
+using GBA SRAM to save your game. Four or five save game will fit in
+save RAM. If you save more games than will fit, a warning will appear on
+the top screen. When you turn your DS off, the new save will be lost,
+and only the first ones you saved will be present.
+
+Many of the games use both mouse buttons. Usually the right button often
+performs the default action on any object you click on. To simulate this
+with the DS pen, you can switch the input into one of three modes. Press
+left on the D-pad to enable the left mouse button. Press right on the
+D-pad to enable the right mouse button. Press up on the D-pad to enable
+hover mode. In this mode, you won't click on anything, just hover the
+mouse cursor over it. This lets you pick out active objects in the scene.
+
+An icon on the top screen will show you which mode you're in.
+
+In hover mode, there are some additional controls. While holding the pen
+on the screen, tapping D-pad left or D-pad right (or A/Y in left handed
+mode) will click the left or right mouse button.
+
+There is an alternative method of control which doesn't require you to
+change modes with the D-pad. Press 'Select' to bring up the DS options,
+and choose 'Tap for left click, double tap for right click'. In this
+mode, you can quickly tap the screen to left click the mouse, and tap twice
+to right click the mouse.
+
+
+Here is a complete list of controls in right-handed mode (the default
+setting):
+Key Usage
+Pad Left Left mouse button
+Pad Right Right mouse button
+Pad Up Hover mouse (no mouse button)
+Pad Down Skip dialogue line (for some Lucasarts games), Show inventory
+ (for Beneath a Steel Sky), Show active objects (for Simon the Sorceror)
+Start Pause/game menu (works in some games)
+Select DS Options
+B Skip cutscenes
+A Swap main screen and zoomed screen
+Y Show/Hide debug console
+X Show/Hide on-screen keyboard
+L + D-pad or L + Pen Scroll touch screen view
+L + B Zoom in
+L + A Zoom out
+
+
+
+And here's left-handed mode:
+Key Usage
+Y Left mouse button
+A Right mouse button
+X Hover mouse (no mouse button)
+B Skip dialogue line (for some Lucasarts games), Show inventory (for
+ Beneath a Steel Sky), Show active objects (for Simon the Sorceror)
+Start Pause/game menu (works in some games)
+Select DS Options
+D-pad down Skip cutscenes
+D-pad up Swap main screen and zoomed screen
+D-pad left Show/Hide debug console
+D-pad right Show/Hide on-screen keyboard
+R + D-pad or R + Pen Scroll touch screen view
+R + D-pad down Zoom in
+R + d-pad right Zoom out
+
+
+
+ Game-specific controls
+ ------------------------------------------------------------------------
+
+ * Sam and Max Hit the Road: The current cursor mode is displayed on
+ the top screen. Use d-pad right to switch mode.
+ * Indiana Jones games: If you get into a fight, press Select, and
+ check the box marked 'Use Indy Fighting Controls'.
+ Return to the game, then use the following controls to fight:
+
+ D-pad left: move left
+ D-pad right: move right
+ D-pad up: guard up
+ D-pad down: guard down
+ Y: guard middle
+ X: Punch high
+ A: Punch middle
+ B: Punch low
+ Left shoulder: Fight towards the left
+ Right shoulder: Fight towards the right
+
+ The icon on the top screen shows which way you're currently
+ facing. Remember to turn the option off when the fight ends, or
+ the normal controls won't work!
+ * Beneath a Steel Sky: Press D-pad down to show your inventory.
+ * Simon the Sorcerer 1/2: Press D-pad down to show active objects.
+ * AGI games: Press Start to show the menu bar.
+ * Bargon Attack: Press Start to hit F1 when you need to start the
+ game. Use the on-screen keyboard (hit X) to press other function keys.
+
+
+ DS Options Screen
+ ------------------------------------------------------------------------
+
+Pressing the 'select' button during any game to show the DS options
+screen. This screen shows options specific to the Nintendo DS version
+of ScummVM.
+
+Controls tab
+
+Indy Fight Controls - Enable fighting controls for the Indiana Jones
+games. See 'Game Specific Controls' for more information.
+
+Left handed Mode - Switch the controls on the D-pad with the controls
+on the A/B/X/Y buttons.
+
+Show mouse cursor - Shows the game's mouse cursor on the bottom screen.
+
+Snap to edges - makes it easier for the mouse controls to reach the edges
+of the screen. Useful for Beneath a Steel Sky and Goblins 3.
+
+Touch X offset - if your screen doesn't perform properly, this setting
+allows you to adjust when the cursor appears left or right relative to
+the screen's measured touch position.
+
+Touch Y offset - if your screen doesn't perform properly, this setting
+allows you to adjust when the cursor appears higher or lower relative to
+the screen's measured touch position.
+
+Use Laptop Trackpad-style cursor control - In this mode, use the lower
+screen to drag the cursor around, a bit like using a trackpad on a laptop.
+When this option is enabled, the following option is also enabled.
+
+Tap for left click, double tap for right click - In this mode, you can
+quickly tap on the screen to left click the mouse, or quickly
+double tap on the screen to right click the mouse. If you find clicking
+or double-clicking difficult, try and make a firmer touch on the screen,
+and keep the pen down for longer.
+
+Sensitivity - this bar adjusts the speed of cursor movement when laptop
+trackpad-style cursor control is enabled (see above).
+
+Graphics Tab
+
+Scaling options:
+
+Three scaling options are available for the main screen.
+
+Harware Scale - Scales using the DS hardware scaler using a flicker method.
+Produces lower quality graphics but doesn't slow the game down.
+
+Software Scale - Scales using the CPU. A much higher quality image is
+produced, but at the expense of speed in some games.
+
+Unscaled - Allows you to see the graphics as originaly displayed. This
+doesn't fit on the DS screen, but you can scroll the screen around by holding
+the left shoulder button and using the D-pad or touch screen.
+
+Top screen zoom - These three options control the zoom level of the top
+screen when ScummVM is started up. Changing this option will set the zoom
+to the specified level immediately.
+
+Initial top screen scale:
+
+This option controls the scaling level of the zoomed screen. In ScummVM
+DS, one screen shows a zoomed-in view of the action, and this option controls
+how zoomed in it is. You can also adjust this in the game by holding L and
+pressing A/B.
+
+General Tab
+
+High Quality Audio - Enhance the sound quality, at the expense of some
+slowdown during some games.
+
+Disable power off - ScummVM DS turns the power off when the game quits.
+This option disables that feature.
+
+
+
+
+
+
+ Auto completion dictionary for Sierra AGI games
+ ------------------------------------------------------------------------
+
+If you are playing a Sierra AGI game, you will be using the on-screen
+keyboard quite a lot (press X to show it). To reduce the amount you have
+to type, the game can automatically complete long words for you. To use
+this feature, simply copy the PRED.DIC file from the ScummVM DS archive
+into your game folder on your card. Now, when you use the keyboard,
+possible words will be shown underneith it. To type one of those words,
+simply double click on it with your stylus.
+
+
+ Converting your CD audio
+ ------------------------------------------------------------------------
+
+ScummVM supports playing CD audio for specific games which came with
+music stored as standard music CD tracks. To use this music in ScummVM
+DS, they need to be ripped from the CD and stored in a specific format.
+This can only be done for the CD versions of certain games, such as
+Monkey Island 1, Loom, and Gobliiins. All the floppy games and CD games
+that didn't have CD audio tracks for music don't require any conversion,
+and will work unmodified on ScummVM DS. MP3 audio files for CD music are
+not supported.
+
+Cdex can do the conversion very well and I recommend using it to convert
+your audio files, although any CD ripping software can be used, so feel
+free to use your favourite program. The format you need to use is
+IMA-ADPCM 4-bit Mono. You may use any sample rate. All other formats
+will be rejected, including uncompressed WAV files.
+
+Now I will to describe how to rip your CD tracks with Cdex, which can be
+found here: Cdex Homepage <http://sourceforge.net/projects/cdexos/>.
+Other software can be used to create IMA ADPCM files under Linux or
+MacOS.
+
+To set this up in Cdex, select Settings from the Options menu. On the
+Encoder tab, select 'WAV Output Encoder'. Under 'Encoder Options',
+choose the following:
+
+ Format: WAV
+ Compression: IMA ADPCM
+ Samplerate: 22050 Hz
+ Channels: Mono
+ On the fly encoding: On
+
+Next, go to the 'Filenames' tab and select the folder you want to save
+your Wav files to. Under 'Filename format', enter 'track%3'. This should
+name your WAV files in the correct way. Click OK.
+
+Now select all the tracks on your CD, and click 'Extract CD tracks to a
+compressed audio file'. Cdex should rip all the audio off your CD.
+
+Now all you have to do is copy the newly created WAV files into the same
+directory that your other game data is stored on your CompactFlash card.
+Next time your run ScummVM DS, it should play with music!
+
+*Important Note:* Do not select 'Extract CD tracks to a WAV file'. This
+creates uncompressed WAVs only. You want 'Extract CD tracks to a
+compressed audio file'.
+
+
+ Converting Speech files to MP3 format
+ ------------------------------------------------------------------------
+
+ScummVM supports playing back speech for talkie games in MP3 format.
+Unfortunately, the DS CPU is not quite up to the task, and MP3 audio
+will sometimes cause slowdown in your game. However, if your flash card
+isn't big enough to fit the audio files on, you will have no choice!
+
+To convert your audio you will need a copy of the ScummVM Tools package
+<http://sourceforge.net/project/showfiles.php?group_id=37116&package_id=67433>.
+You will also need a copy of the LAME MP3 encoder
+<http://www.free-codecs.com/Lame_Encoder_download.htm>.
+
+Once this is all installed and set up, the process to encode your audio
+varies from game to game, but the Lucasarts games can all be compressed
+using the following command line:
+
+compress_scumm_sou --mp3 monster.sou
+
+This produces a monster.so3 file which you can copy to your flash card
+and replaces the original monster.sou. Ogg format (monster.sog) and flac
+format files are not currently supported by ScummVM DS, and it is
+unlikely they will ever be supported. There is no way to convert .sog or
+.so3 files back to .sou files. Just dig out your original CD and copy
+the file from that.
+
+
+ Frequently Asked Questions
+ ------------------------------------------------------------------------
+
+I get a lot of email about ScummVM DS. Nearly all of them are exactly
+the same. Here I'm going to try and answer the questions that everybody
+asks me in the hope that I will spend less time answering questions that
+are clearly in the documentation and more time helping people who have a
+real problem or have discovered a real bug.
+
+*Q:* I can't see the bottom line of inventory items in Day of the
+Tentacle, Monkey Island 2, or a few other games! What do I do?
+*A:* Hold down the left shoulder button and use D-pad (or the touch
+screen) to scroll the screen around.
+
+*Q:* I dont see a menu when I press Start in Flight of the Amazon Queen
+or Simon the Sorcerer. Is ScummVM broken?
+*A:* No. To save in Simon the Sorcerer, click 'use', then click on the
+postcard in your inventory. In Flight of the Amazon Queen, click 'use',
+then click on the journal in your inventory.
+
+*Q:* Why does ScummVM crash when I play Monkey Island 1?
+*A:* This happens when MP3 audio tracks are present from the PC version
+of ScummVM. Delete the MP3 tracks and reencode them to ADPCM WAV files
+as described in the CD audio section.
+
+*Q:* When will you support my Mini/Micro SD card reader? I want it!
+Pretty please?
+*A:* ScummVM uses DLDI drivers. If your card reader manufacturer doesn't
+provide a driver, there is nothing I can do about it. The people to ask
+are the card reader manufacturers themselves.
+
+*Q:* Can't you use the extra RAM in the M3/Supercard or the official
+Opera Expansion Pack to support more games like The Dig and Full
+Throttle? DS Linux has done it, so why can't you?
+*A:* Not at the moment. The extra RAM has certain differences to the
+build in RAM which makes it difficult to use for general programs. As
+ScummVM DS is an official port, the changes to the ScummVM code base
+must be minimal to avoid making the code difficult to read for other
+users. I do have plans to work on this some time in the future, but
+don't nag me about when it'll be done. If and when there's progress with
+this, I will post on the ScummVM forums about it.
+
+
+*Q:* ScummVM DS turns off my DS when I hit 'Quit' in the game or quit
+from the frontend. Why doesn't it return to the menu?
+*A:* Due to bugs in the ScummVM codebase, many of the ScummVM games
+cannot quit cleanly leaving the machine in the same state as when it
+started. You will notice that no other versions of ScummVM can quit back
+to the menu either. This will be fixed at some time in the future.
+
+
+
+
+ Contributors
+ ------------------------------------------------------------------------
+
+ScummVM DS uses chishm's GBA Movie Player FAT driver.
+The CPU scaler is by Tramboi and Robin Watts
+The ARM code was optimised by Robin Watts
+Thanks to highpass for the ScummVM DS icons.
+Thanks to zhevon for the Sam & Max cursor code.
+Thanks to theNinjaBunny for the M3 Adaptor guide on this site.
+Thanks also to everyone on the GBADev Forums.
+
+This program was brought to you by caffiene, sugar, and late nights.
+
+
+ Donations and Getting Help
+ ------------------------------------------------------------------------
+
+If you have problems getting ScummVM to work on your hardware, please
+read the FAQ first. /Please/ don't ask me questions which are
+answered in the FAQ, I get many emails about this program each day, and
+I can't help the people who really need help if I'm answering the same
+question all the time which is already answered on this page. Other than
+that, feel free to post on the ScummVM DS forum <http://forums.scummvm.org>
+for help. Please do your research first though. There is no way of
+running this on an out-of-the box DS without extra hardware. Most of
+these things are fairly inexpensive though.
+
+If you want to contact me, please email me on scummvm at millstone dot
+demon dot co dot uk.
+
+If you want to help with the development of ScummVM DS, great! Download
+the source code and get building. There are plenty of things left to do.
+
+You can also help by making a donation if you've particularly enjoyed
+ScummVM DS. This uses Paypal, and is completely secure. There's no
+pressure though, ScummVM DS is completely free. This is just for those
+who would like to make a contribution to further development.
+
+
+
+ Building from Sources
+ ------------------------------------------------------------------------
+
+ScummVM is an open source project. This means that anyone is free to
+take the source code to the project and make their own additions and fixes,
+contributing them back to the authors for consideration for the next version.
+
+To build ScummVM DS from source, it's probably better to checkout the
+latest version of the code from the ScummVM SVN repository. The ScummVM
+Sourceforge.net homepage <http://sourceforge.net/projects/scummvm> has
+all the information about how to do this.
+
+By default, ScummVM DS expects to find libmad, an MP3 compressor library
+targeted for the ARM platform. If you don't have this, you must disable
+libmad support by opening 'backends/platform/ds/arm9/makefile' and
+commenting out the line which says USE_MAD = 1.
+
+Then, enter the 'backends/platform/ds' folder and type:
+make SCUMM_BUILD=a
+
+The executable nds file will build inside 'backends/platform/ds/arm9/SCUMMVM-A'.
+
+For other builds, substitute the letters b - g in the above line.
+
+
+
diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile
index 7472a32218..e74bcf28da 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -8,25 +8,29 @@ libndsdir = $(DEVKITPRO)/libnds
# Select the build by setting SCUMM_BUILD to a,b,c,d,e,f or g.
# Anything else gets build a.
-ifeq ($(SCUMM_BUILD),g)
+ifeq ($(SCUMM_BUILD),h)
+ DS_BUILD_H = 1
+ else
+ ifeq ($(SCUMM_BUILD),g)
DS_BUILD_G = 1
-else
- ifeq ($(SCUMM_BUILD),f)
+ else
+ ifeq ($(SCUMM_BUILD),f)
DS_BUILD_F = 1
- else
- ifeq ($(SCUMM_BUILD),e)
- DS_BUILD_E = 1
else
- ifeq ($(SCUMM_BUILD),d)
- DS_BUILD_D = 1
+ ifeq ($(SCUMM_BUILD),e)
+ DS_BUILD_E = 1
else
- ifeq ($(SCUMM_BUILD),c)
- DS_BUILD_C = 1
+ ifeq ($(SCUMM_BUILD),d)
+ DS_BUILD_D = 1
else
- ifeq ($(SCUMM_BUILD),b)
- DS_BUILD_B = 1
+ ifeq ($(SCUMM_BUILD),c)
+ DS_BUILD_C = 1
else
+ ifeq ($(SCUMM_BUILD),b)
+ DS_BUILD_B = 1
+ else
DS_BUILD_A = 1
+ endif
endif
endif
endif
@@ -67,7 +71,12 @@ endif
# NOTE: The header and libs for the debugger is assumed to be in the libnds
# folder.
-VPATH = $(srcdir)
+vpath %.h $(srcdir)
+vpath %.cpp $(srcdir)
+vpath %.c $(srcdir)
+vpath %.m $(srcdir)
+vpath %.asm $(srcdir)
+vpath %.s $(srcdir)
# Command to build libmad is:
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork'
@@ -75,8 +84,8 @@ VPATH = $(srcdir)
# I actually had to use
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' LDFLAGS='C:/Progra~1/devkitpro/libnds/lib/libnds9.a' --disable-shared --disable-debugging
-USE_ARM_SOUND_ASM = 1
ARM = 1
+USE_ARM_SOUND_ASM = 1
USE_ARM_COSTUME_ASM = 1
ifdef DS_BUILD_A
@@ -135,6 +144,13 @@ ifdef DS_BUILD_G
BUILD=scummvm-G
endif
+ifdef DS_BUILD_H
+ DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_H
+ LOGO = logog.bmp
+ ENABLE_PARALLACTION = STATIC_PLUGIN
+ BUILD=scummvm-H
+endif
+
ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin
ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
@@ -147,6 +163,7 @@ CFLAGS = -Wno-multichar -Wall\
-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
-mthumb-interwork -DUSE_ARM_COSTUME_ASM=1
+
# -ffast-math
ifdef USE_DEBUGGER
@@ -160,7 +177,7 @@ ifdef USE_PROFILER
endif
CXXFLAGS= $(CFLAGS) -Wno-non-virtual-dtor -Wno-unknown-pragmas -Wno-reorder \
- -fno-exceptions -fno-rtti -mthumb-interwork
+ -fno-exceptions -fno-rtti -mthumb-interwork -ffunction-sections -fdata-sections
# -mthumb
@@ -180,12 +197,12 @@ ifdef USE_MAD
endif
-LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -Wl,--wrap,time -mno-fpu -Wl,-Map,map.txt
+LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -Wl,--wrap,time -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections
-INCLUDES= -I./ -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/common -I$(portdir)/source \
- -I$(portdir)/data -I$(libndsdir)/include -I$(portdir)/../commoninclude\
- -I$(libndsdir)/include -I$(libndsdir)/include/nds -I$(srcdir)/engines -I$(portdir)/source/mad\
- -I$(portdir)/source/libcartreset -include $(srcdir)/common/scummsys.h
+INCLUDES= -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/engines \
+ -I$(portdir)/data -I$(portdir)/../commoninclude \
+ -I$(portdir)/source -I$(portdir)/source/mad -I$(portdir)/source/libcartreset \
+ -I$(libndsdir)/include -include $(srcdir)/common/scummsys.h
LIBS = -lm -L$(libndsdir)/lib -L$(portdir)/lib -lnds9
@@ -232,7 +249,8 @@ endif
DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o
-COMPRESSOR_OBJS := $(portdir)/source/compressor/lz.o
+COMPRESSOR_OBJS :=
+#$(portdir)/source/compressor/lz.o
FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o\
$(portdir)/source/fat/io_fcsr.o $(portdir)/source/fat/io_m3cf.o\
@@ -252,14 +270,15 @@ FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o
# $(portdir)/source/fat/io_sd_common.o $(portdir)/source/fat/io_scsd_s.o \
# $(portdir)/source/fat/io_sc_common.o $(portdir)/source/fat/io_sd_common.o
-LIBCARTRESET_OBJS := $(portdir)/source/libcartreset/cartreset.o
+LIBCARTRESET_OBJS :=
+#$(portdir)/source/libcartreset/cartreset.o
# Files in this list will be optimisied for speed, otherwise they will be optimised for space
OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp mixer.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp
#OPTLIST :=
# Compiler options for files which should be optimised for speed
-OPT_SPEED := -O2
+OPT_SPEED := -O3
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os
@@ -281,7 +300,7 @@ ndsall:
include $(srcdir)/Makefile.common
semiclean:
- $(RM) $(portdir)/source/dsoptions.o $(portdir)/source/dsmain.o $(FAT_OBJS) $(DATA_OBJS) $(portdir)/source/wordcompletion.o
+ $(RM) $(portdir)/source/dsoptions.o $(portdir)/source/dsmain.o $(FAT_OBJS) $(DATA_OBJS) $(portdir)/source/wordcompletion.o $(portdir)/source/dsoptions.o
clean:
$(RM) $(OBJS) $(EXECUTABLE)
@@ -333,36 +352,17 @@ endef
##############
# Replacement rule for the one in makefile.common
##############
-ifndef HAVE_GCC3
-# If you use GCC, disable the above and enable this for intelligent
-# dependency tracking.
-#.cpp.o:
-%.o:%.cpp
- $(MKDIR) $(*D)/$(DEPDIR)
- $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-# $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
- $(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
- $(RM) "$(*D)/$(DEPDIR)/$(*F).d2"
-else
-# If you even have GCC 3.x, you can use this build rule, which is safer; the above
-# rule can get you into a bad state if you Ctrl-C at the wrong moment.
-# Also, with this GCC inserts additional dummy rules for the involved headers,
-# which ensures a smooth compilation even if said headers become obsolete.
-#.cpp.o:
-%.o:%.cpp
+%.o: %.cpp
# echo !!!!!!!!!!!! $(notdir $<)
# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) )
# OPTFLAG=-O3
# else
# OPTFLAG=-Os
# endif
-
# export OPTFLAG = ;
# echo !!!!!!!! $(OPTFLAG)
-
$(MKDIR) $(*D)/$(DEPDIR)
$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(if $(findstring $(notdir $<), $(OPTLIST)), $(OPT_SPEED), $(OPT_SIZE)) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-endif
#---------------------------------------------------------------------------------
@@ -412,6 +412,7 @@ endif
padbin 16 $(basename $@).ds.gba
#---------------------------------------------------------------------------------
+# FIXME: The following rule hardcodes the input & output filename -- shouldn't it use $< and $@ instead?
%.bin: %.elf
$(OBJCOPY) -S scummvm.elf scummvm-stripped.elf
$(OBJCOPY) -O binary scummvm-stripped.elf scummvm.bin
@@ -419,4 +420,3 @@ endif
#%.o: %.s
# $(MKDIR) $(*D)/$(DEPDIR)
# $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-
diff --git a/backends/platform/ds/arm9/source/blitters_arm.s b/backends/platform/ds/arm9/source/blitters_arm.s
index 5f7df298b4..48ec316675 100644
--- a/backends/platform/ds/arm9/source/blitters_arm.s
+++ b/backends/platform/ds/arm9/source/blitters_arm.s
@@ -20,149 +20,12 @@
@
@ @author Robin Watts (robin@wss.co.uk)
- .global asmDrawStripToScreen
- .global asmCopy8Col
.global Rescale_320x256xPAL8_To_256x256x1555
.global Rescale_320x256x1555_To_256x256x1555
.section .itcm,"ax", %progbits
.align 2
.code 32
- @ ARM implementation of asmDrawStripToScreen.
- @
- @ C prototype would be:
- @
- @ extern "C" void asmDrawStripToScreen(int height,
- @ int width,
- @ byte const *text,
- @ byte const *src,
- @ byte *dst,
- @ int vsPitch,
- @ int vsScreenWidth,
- @ int textSurfacePitch);
- @
- @ In addition, we assume that text, src and dst are all word (4 byte)
- @ aligned. This is the same assumption that the old 'inline' version
- @ made.
-asmDrawStripToScreen:
- @ r0 = height
- @ r1 = width
- @ r2 = text
- @ r3 = src
- MOV r12,r13
- STMFD r13!,{r4-r7,r9-r11,R14}
- LDMIA r12,{r4,r5,r6,r7}
- @ r4 = dst
- @ r5 = vsPitch
- @ r6 = vmScreenWidth
- @ r7 = textSurfacePitch
-
- CMP r0,#0 @ If height<=0
- MOVLE r0,#1 @ height=1
- CMP r1,#4 @ If width<4
- BLT end @ return
-
- @ Width &= ~4 ? What's that about then? Width &= ~3 I could have
- @ understood...
- BIC r1,r1,#4
-
- SUB r5,r5,r1 @ vsPitch -= width
- SUB r6,r6,r1 @ vmScreenWidth -= width
- SUB r7,r7,r1 @ textSurfacePitch -= width
- MOV r10,#253
- ORR r10,r10,r10,LSL #8
- ORR r10,r10,r10,LSL #16 @ r10 = mask
-yLoop:
- MOV r14,r1 @ r14 = width
-xLoop:
- LDR r12,[r2],#4 @ r12 = [text]
- LDR r11,[r3],#4 @ r11 = [src]
- CMP r12,r10
- BNE singleByteCompare
- SUBS r14,r14,#4
- STR r11,[r4], #4 @ r4 = [dst]
- BGT xLoop
-
- ADD r2,r2,r7 @ text += textSurfacePitch
- ADD r3,r3,r5 @ src += vsPitch
- ADD r4,r4,r6 @ dst += vmScreenWidth
- SUBS r0,r0,#1
- BGT yLoop
- LDMFD r13!,{r4-r7,r9-r11,PC}
-
-singleByteCompare:
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- STR r12,[r4],#4
- SUBS r14,r14,#4
- BGT xLoop
-
- ADD r2,r2,r7 @ text += textSurfacePitch
- ADD r3,r3,r5 @ src += vsPitch
- ADD r4,r4,r6 @ dst += vmScreenWidth
- SUBS r0,r0,#1
- BGT yLoop
-end:
- LDMFD r13!,{r4-r7,r9-r11,PC}
-
-
- @ ARM implementation of asmCopy8Col
- @
- @ C prototype would be:
- @
- @ extern "C" void asmCopy8Col(byte *dst,
- @ int dstPitch,
- @ const byte *src,
- @ int height);
- @
- @ In addition, we assume that src and dst are both word (4 byte)
- @ aligned. This is the same assumption that the old 'inline' version
- @ made.
-asmCopy8Col:
- @ r0 = dst
- @ r1 = dstPitch
- @ r2 = src
- @ r3 = height
- STMFD r13!,{r14}
- SUB r1,r1,#4
-
- TST r3,#1
- ADDNE r3,r3,#1
- BNE roll2
-yLoop2:
- LDR r12,[r2],#4
- LDR r14,[r2],r1
- STR r12,[r0],#4
- STR r14,[r0],r1
-roll2:
- LDR r12,[r2],#4
- LDR r14,[r2],r1
- SUBS r3,r3,#2
- STR r12,[r0],#4
- STR r14,[r0],r1
- BNE yLoop2
-
- LDMFD r13!,{PC}
-
-
@ ARM implementation of Rescale_320x256x1555_To_256x256x1555
@
@ C prototype would be:
diff --git a/backends/platform/ds/arm9/source/cdaudio.h b/backends/platform/ds/arm9/source/cdaudio.h
index d237569bb7..d1897d3e5d 100644
--- a/backends/platform/ds/arm9/source/cdaudio.h
+++ b/backends/platform/ds/arm9/source/cdaudio.h
@@ -20,7 +20,7 @@
*
*/
- #ifndef _CDAUDIO_H_
+#ifndef _CDAUDIO_H_
#define _CDAUDIO_H_
namespace DS {
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index f4706807f7..872a196e9b 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -65,6 +65,8 @@
//#define USE_LIBCARTRESET
#include <nds.h>
+#include <nds/registers_alt.h>
+#include <nds/arm9/exceptions.h>
//#include <ARM9/console.h> //basic print funcionality
@@ -75,13 +77,10 @@
#include "icons_raw.h"
#include "fat/gba_nds_fat.h"
#include "fat/disc_io.h"
-#include "common/config-manager.h"
-#include "engines/scumm/scumm.h"
#include "keyboard_raw.h"
#include "keyboard_pal_raw.h"
#define V16(a, b) ((a << 12) | b)
#include "touchkeyboard.h"
-#include "registers_alt.h"
//#include "compact_flash.h"
#include "dsoptions.h"
#ifdef USE_DEBUGGER
@@ -96,6 +95,26 @@
#endif
#include "backends/fs/ds/ds-fs.h"
+extern "C" u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState);
+extern const char __itcm_start[];
+static const char *registerNames[] =
+ { "r0","r1","r2","r3","r4","r5","r6","r7",
+ "r8 ","r9 ","r10","r11","r12","sp ","lr ","pc " };
+
+/*
+extern "C" void* __real_malloc(size_t size);
+
+extern "C" void* __wrap_malloc(size_t size) {
+ void* res = __real_malloc(size);
+ if (res) {
+ return res;
+ } else {
+ consolePrintf("Failed alloc %d\n", size);
+ return NULL;
+ }
+}
+*/
+
namespace DS {
// From console.c in NDSLib
@@ -168,7 +187,7 @@ bool displayModeIs8Bit = false;
u8 gameID;
bool snapToBorder = false;
-bool consoleEnable = true;
+bool consoleEnable = false;
bool gameScreenSwap = false;
bool isCpuScalerEnabled();
//#define HEAVY_LOGGING
@@ -197,6 +216,13 @@ int mouseHotspotX, mouseHotspotY;
bool cursorEnable = false;
bool mouseCursorVisible = true;
bool rightButtonDown = false;
+bool touchPadStyle = false;
+int touchPadSensitivity = 8;
+bool tapScreenClicks = true;
+
+int tapCount = 0;
+int tapTimeout = 0;
+int tapComplete = 0;
// Dragging
int dragStartX, dragStartY;
@@ -213,7 +239,14 @@ int gameHeight = 200;
// Scale
bool twoHundredPercentFixedScale = false;
bool cpuScalerEnable = false;
-#define NUM_SUPPORTED_GAMES 20
+
+ // 100 256
+ // 150 192
+ // 200 128
+
+ // (256 << 8) / scale
+
+
#ifdef USE_PROFILER
int hBlankCount = 0;
@@ -221,6 +254,7 @@ int hBlankCount = 0;
u8* scalerBackBuffer = NULL;
+#define NUM_SUPPORTED_GAMES 21
gameListType gameList[NUM_SUPPORTED_GAMES] = {
// Unknown game - use normal SCUMM controls
@@ -248,6 +282,7 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = {
{"elvira2", CONT_SIMON},
{"elvira1", CONT_SIMON},
{"waxworks", CONT_SIMON},
+ {"parallaction", CONT_NIPPON},
};
gameListType* currentGame = NULL;
@@ -260,6 +295,7 @@ bool penHeld;
bool penReleased;
bool penDownLastFrame;
s32 penX, penY;
+s32 penDownX, penDownY;
int keysDownSaved;
int keysReleasedSaved;
int keysChangedSaved;
@@ -299,9 +335,41 @@ void setCpuScalerEnable(bool enable) {
cpuScalerEnable = enable;
}
+void setTrackPadStyleEnable(bool enable) {
+ touchPadStyle = enable;
+}
+
+void setTapScreenClicksEnable(bool enable) {
+ tapScreenClicks = enable;
+}
+
+void setGameScreenSwap(bool enable) {
+ gameScreenSwap = enable;
+}
+
+void setSensitivity(int sensitivity) {
+ touchPadSensitivity = sensitivity;
+}
+
+void setTopScreenZoom(int percentage) {
+ // 100 256
+ // 150 192
+ // 200 128
+
+ // (256 << 8) / scale
+
+ s32 scale = (percentage << 8) / 100;
+ subScreenScale = (256 * 256) / scale;
+
+// consolePrintf("Scale is %d %%\n", percentage);
+}
// return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds"));
+controlType getControlType() {
+ return currentGame->control;
+}
+
//plays an 8 bit mono sample at 11025Hz
void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate)
@@ -429,14 +497,14 @@ void initGame() {
consolePrintf("initing game...");
#endif
- static bool firstTime = true;
+// static bool firstTime = true;
setOptions();
//strcpy(gameName, ConfMan.getActiveDomain().c_str());
strcpy(gameName, ConfMan.get("gameid").c_str());
- consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
+// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
currentGame = &gameList[0]; // Default game
@@ -447,16 +515,12 @@ void initGame() {
}
}
- if (firstTime) {
+/* if (firstTime) {
firstTime = false;
- if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) {
- startSound(22050, 8192);
- } else {
- startSound(11025, 4096);
- }
}
+*/
#ifdef HEAVY_LOGGING
consolePrintf("done\n");
#endif
@@ -631,7 +695,7 @@ void checkSleepMode() {
void setShowCursor(bool enable)
{
- if (currentGame->control == CONT_SCUMM_SAMNMAX)
+ if ((currentGame) && (currentGame->control == CONT_SCUMM_SAMNMAX))
{
if (cursorEnable) {
sprites[1].attribute[0] = ATTR0_BMP | 150;
@@ -654,23 +718,28 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX,
mouseHotspotX = hotspotX;
mouseHotspotY = hotspotY;
+ //consolePrintf("Set cursor icon %d, %d\n", w, h);
+
{
int off = 128*64;
memset(SPRITE_GFX + off, 0, 32 * 32 * 2);
memset(SPRITE_GFX_SUB + off, 0, 32 * 32 * 2);
+
for (uint y=0; y<h; y++) {
for (uint x=0; x<w; x++) {
int color = icon[y*w+x];
+
+ //consolePrintf("%d:%d ", color, OSystem_DS::instance()->getDSPaletteEntry(color));
if (color == keycolor) {
SPRITE_GFX[off+(y)*32+x] = 0x0000; // black background
SPRITE_GFX_SUB[off+(y)*32+x] = 0x0000; // black background
} else {
- SPRITE_GFX[off+(y)*32+x] = BG_PALETTE[color] | 0x8000;
- SPRITE_GFX_SUB[off+(y)*32+x] = BG_PALETTE[color] | 0x8000;
+ SPRITE_GFX[off+(y)*32+x] = OSystem_DS::instance()->getDSCursorPaletteEntry(color) | 0x8000;
+ SPRITE_GFX_SUB[off+(y)*32+x] = OSystem_DS::instance()->getDSCursorPaletteEntry(color) | 0x8000;
}
}
}
@@ -733,6 +802,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX,
sprites[1].attribute[1] = ATTR1_SIZE_64 | pos;
sprites[1].attribute[2] = ATTR2_ALPHA(1) | 176;
}
+
}
@@ -745,6 +815,7 @@ void displayMode16Bit() {
u16 buffer[32 * 32 * 2];
+ releaseAllKeys();
if (displayModeIs8Bit) {
// static int test = 0;
@@ -1109,7 +1180,7 @@ void setKeyboardEnable(bool en) {
} else {
-
+ DS::releaseAllKeys();
// Restore the palette that the keyboard has used
for (int r = 0; r < 256; r++) {
BG_PALETTE_SUB[r] = BG_PALETTE[r];
@@ -1157,6 +1228,194 @@ bool getIsDisplayMode8Bit() {
return displayModeIs8Bit;
}
+void doScreenTapMode(OSystem_DS* system)
+{
+ Common::Event event;
+ static bool left = false, right = false;
+
+ if (left) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ left = false;
+ }
+
+ if (right) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ right = false;
+ }
+
+
+ if (tapComplete == 1) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ tapComplete = 0;
+ left = true;
+ } else if (tapComplete == 2) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ tapComplete = 0;
+ right = true;
+ }
+
+
+ if (getKeysDown() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ if (getKeysReleased() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+
+ if (getKeysDown() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ if (getKeysReleased() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+}
+
+void doButtonSelectMode(OSystem_DS* system)
+{
+ Common::Event event;
+
+
+ if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ //consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
+ }
+
+ static bool leftButtonDown = false;
+ static bool rightButtonDown = false;
+
+ if (getPenReleased() && (leftButtonDown || rightButtonDown)) {
+ if (leftButtonDown) {
+ event.type = Common::EVENT_LBUTTONUP;
+ } else {
+ event.type = Common::EVENT_RBUTTONUP;
+ }
+
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+
+ if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) {
+ if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ if ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit)) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ leftButtonDown = true;
+ } else {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ rightButtonDown = true;
+ }
+
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ } else {
+ // In hover mode, D-pad left and right click the mouse when the pen is on the screen
+
+ if (getPenHeld()) {
+ if (getKeysDown() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+ if (getKeysReleased() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+
+ if (getKeysDown() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+ if (getKeysReleased() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+ }
+ }
+
+ if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) {
+
+ if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) {
+ if (getKeysDown() & KEY_LEFT) {
+ mouseMode = MOUSE_LEFT;
+ }
+
+ if (rightButtonDown)
+ {
+ Common::Event event;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ event.type = Common::EVENT_RBUTTONUP;
+ system->addEvent(event);
+ rightButtonDown = false;
+ }
+
+
+ if (getKeysDown() & KEY_RIGHT) {
+ if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) {
+ mouseMode = MOUSE_RIGHT;
+ } else {
+ // If we're playing sam and max, click and release the right mouse
+ // button to change verb
+ Common::Event event;
+
+ if (currentGame->control == CONT_FUTURE_WARS) {
+ event.mouse = Common::Point(320 - 128, 200 - 128);
+ event.type = Common::EVENT_MOUSEMOVE;
+ system->addEvent(event);
+ } else {
+ event.mouse = Common::Point(getPenX(), getPenY());
+ }
+
+ rightButtonDown = true;
+
+
+ event.type = Common::EVENT_RBUTTONDOWN;
+ system->addEvent(event);
+
+ //event.type = Common::EVENT_RBUTTONUP;
+ //system->addEvent(event);
+ }
+ }
+
+
+
+ if (getKeysDown() & KEY_UP) {
+ mouseMode = MOUSE_HOVER;
+ }
+ }
+ }
+}
+
void addEventsToQueue() {
#ifdef HEAVY_LOGGING
consolePrintf("addEventsToQueue\n");
@@ -1286,54 +1545,6 @@ void addEventsToQueue() {
}
- if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) {
- if (getKeysDown() & KEY_LEFT) {
- mouseMode = MOUSE_LEFT;
- }
-
- if (rightButtonDown)
- {
- Common::Event event;
- event.mouse = Common::Point(getPenX(), getPenY());
- event.type = Common::EVENT_RBUTTONUP;
- system->addEvent(event);
- rightButtonDown = false;
- }
-
-
- if (getKeysDown() & KEY_RIGHT) {
- if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) {
- mouseMode = MOUSE_RIGHT;
- } else {
- // If we're playing sam and max, click and release the right mouse
- // button to change verb
- Common::Event event;
-
- if (currentGame->control == CONT_FUTURE_WARS) {
- event.mouse = Common::Point(320 - 128, 200 - 128);
- event.type = Common::EVENT_MOUSEMOVE;
- system->addEvent(event);
- } else {
- event.mouse = Common::Point(getPenX(), getPenY());
- }
-
- rightButtonDown = true;
-
-
- event.type = Common::EVENT_RBUTTONDOWN;
- system->addEvent(event);
-
- //event.type = Common::EVENT_RBUTTONUP;
- //system->addEvent(event);
- }
- }
-
-
-
- if (getKeysDown() & KEY_UP) {
- mouseMode = MOUSE_HOVER;
- }
- }
@@ -1359,52 +1570,13 @@ void addEventsToQueue() {
if (!keyboardEnable) {
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- //consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
+ if ((tapScreenClicks) && (getIsDisplayMode8Bit()))
+ {
+ doScreenTapMode(system);
}
-
- if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) {
- if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
- event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? Common::EVENT_LBUTTONDOWN: Common::EVENT_RBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
-
- if (getPenReleased()) {
- event.type = mouseMode == MOUSE_LEFT? Common::EVENT_LBUTTONUP: Common::EVENT_RBUTTONUP;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- } else {
- // In hover mode, D-pad left and right click the mouse when the pen is on the screen
-
- if (getPenHeld()) {
- if (getKeysDown() & KEY_LEFT) {
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- if (getKeysReleased() & KEY_LEFT) {
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
-
-
- if (getKeysDown() & KEY_RIGHT) {
- event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- if (getKeysReleased() & KEY_RIGHT) {
- event.type = Common::EVENT_RBUTTONUP;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- }
+ else
+ {
+ doButtonSelectMode(system);
}
if (((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) || (indyFightState)) && (displayModeIs8Bit)) {
@@ -1537,8 +1709,8 @@ void triggerIcon(int imageNum) {
void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) {
- sprites[num].attribute[0] = ATTR0_BMP | (enable? y: 192) | (!enable? ATTR0_DISABLED: 0);
- sprites[num].attribute[1] = ATTR1_SIZE_32 | x | flags;
+ sprites[num].attribute[0] = ATTR0_BMP | (enable? (y & 0xFF): 192) | (!enable? ATTR0_DISABLED: 0);
+ sprites[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags;
sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16);
}
@@ -1552,28 +1724,30 @@ void updateStatus() {
int offs;
if (displayModeIs8Bit) {
- switch (mouseMode) {
- case MOUSE_LEFT: {
- offs = 1;
- break;
- }
- case MOUSE_RIGHT: {
- offs = 2;
- break;
- }
- case MOUSE_HOVER: {
- offs = 0;
- break;
- }
- default: {
- // Nothing!
- offs = 0;
- break;
+ if (!tapScreenClicks) {
+ switch (mouseMode) {
+ case MOUSE_LEFT: {
+ offs = 1;
+ break;
+ }
+ case MOUSE_RIGHT: {
+ offs = 2;
+ break;
+ }
+ case MOUSE_HOVER: {
+ offs = 0;
+ break;
+ }
+ default: {
+ // Nothing!
+ offs = 0;
+ break;
+ }
}
+
+ setIcon(0, 208, 150, offs, 0, true);
}
- setIcon(0, 208, 150, offs, 0, true);
-
if (indyFightState) {
setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true);
// consolePrintf("%d\n", indyFightRight);
@@ -1631,7 +1805,7 @@ void setMainScreenScroll(int x, int y) {
BG3_CX = x + (((frameCount & 1) == 0)? 64: 0);
BG3_CY = y;
- if (!gameScreenSwap) {
+ if ((!gameScreenSwap) || (touchPadStyle)) {
touchX = x >> 8;
touchY = y >> 8;
}
@@ -1660,7 +1834,7 @@ void setMainScreenScale(int x, int y) {
BG3_YDY = y;
}
- if (!gameScreenSwap) {
+ if ((!gameScreenSwap) || (touchPadStyle)) {
touchScX = x;
touchScY = y;
}
@@ -1676,7 +1850,7 @@ void setZoomedScreenScroll(int x, int y, bool shake) {
touchY = y >> 8;
} else */{
- if (gameScreenSwap) {
+ if ((gameScreenSwap) && (!touchPadStyle)) {
touchX = x >> 8;
touchY = y >> 8;
}
@@ -1696,7 +1870,7 @@ void setZoomedScreenScale(int x, int y) {
} else */{
- if (gameScreenSwap) {
+ if ((gameScreenSwap) && (!touchPadStyle)) {
touchScX = x;
touchScY = y;
}
@@ -1757,18 +1931,22 @@ void VBlankHandler(void) {
frameCount++;
- if ((cursorEnable) && (mouseCursorVisible))
- {
+ if ((cursorEnable) && (mouseCursorVisible)) {
if (!keyboardEnable) {
storedMouseX = penX;
storedMouseY = penY;
}
- setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
- }
- else
- {
+ if (gameScreenSwap) {
+ setIcon(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
+ setIconMain(3, 0, 0, 0, 0, false);
+ } else {
+ setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
+ setIcon(3, 0, 0, 0, 0, false);
+ }
+ } else {
setIconMain(3, 0, 0, 0, 0, false);
+ setIcon(3, 0, 0, 0, 0, false);
}
@@ -1826,7 +2004,7 @@ void VBlankHandler(void) {
SUB_BG3_YDX = 0;
SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256);*/
- static int ratio = ( 320 << 8) / SCUMM_GAME_WIDTH;
+ static int ratio = (320 << 8) / SCUMM_GAME_WIDTH;
bool zooming = false;
@@ -1851,8 +2029,12 @@ void VBlankHandler(void) {
subScreenWidth = 256 >> 1;
subScreenHeight = 192 >> 1;
} else {
- subScreenWidth = (((SCUMM_GAME_HEIGHT * 256) / 192) * subScreenScale) >> 8;
- subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8;
+// subScreenWidth = (((SCUMM_GAME_HEIGHT * 256) / 192) * subScreenScale) >> 8;
+// subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8;
+
+
+ subScreenWidth = (256 * subScreenScale) >> 8;
+ subScreenHeight = (192 * subScreenScale) >> 8;
if ( ((subScreenWidth) > 256 - 8) && ((subScreenWidth) < 256 + 8) ) {
subScreenWidth = 256;
@@ -2215,43 +2397,141 @@ void penUpdate() {
// if (getKeysHeld() & KEY_L) consolePrintf("%d, %d penX=%d, penY=%d tz=%d\n", IPC->touchXpx, IPC->touchYpx, penX, penY, IPC->touchZ1);
- if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me.
+ bool penDownThisFrame = (IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0);
+ bool firstFrame = penDownFrames == 2;
+ static bool moved = false;
- if ((penHeld)) {
- penHeld = true;
- penDown = false;
+ if ((tapScreenClicks) && (!getKeyboardEnable()) && (getIsDisplayMode8Bit())) {
- if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
- penX = IPC->touchXpx + touchXOffset;
- penY = IPC->touchYpx + touchYOffset;
+ if ((tapTimeout >= 0)) {
+ tapTimeout++;
+
+ if (((tapTimeout > 15) || (tapCount == 2)) && (tapCount > 0)) {
+ tapComplete = tapCount;
+ tapCount = 0;
+// consolePrintf("Taps: %d\n", tapComplete);
}
+ }
- } else {
- penDown = true;
- penHeld = true;
- penDownSaved = true;
+
- //if ( (ABS(penX - IPC->touchXpx) < 10) && (ABS(penY - IPC->touchYpx) < 10) ) {
- if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
- penX = IPC->touchXpx;
- penY = IPC->touchYpx;
+ if ((penHeld) && (!penDownThisFrame)) {
+ if ((touchPadStyle) || (moved) || (tapCount == 1)) {
+ if ((penDownFrames > 0) && (penDownFrames < 6) && ((tapTimeout == -1) || (tapTimeout > 2))) {
+ tapCount++;
+ tapTimeout = 0;
+// consolePrintf("Tap! %d\n", penDownFrames);
+ moved = false;
+ }
}
- //}
}
+ }
- } else {
- if (penHeld) {
- penReleased = true;
- penReleasedSaved = true;
+
+
+ if ((touchPadStyle) && (getIsDisplayMode8Bit())) {
+
+ if ((penDownFrames > 0)) {
+
+
+ if ((penHeld)) {
+
+ if (penDownThisFrame)
+ {
+ if (penDownFrames >= 2) {
+ int diffX = IPC->touchXpx - penDownX;
+ int diffY = IPC->touchYpx - penDownY;
+
+ int speed = ABS(diffX) + ABS(diffY);
+
+ if ((ABS(diffX) < 35) && (ABS(diffY) < 35))
+ {
+
+ if (speed >= 8)
+ {
+ diffX *= ((speed >> 3) * touchPadSensitivity) >> 3;
+ diffY *= ((speed >> 3) * touchPadSensitivity) >> 3;
+ }
+
+ penX += diffX;
+ penY += diffY;
+ if (penX > 255) penX = 255;
+ if (penX < 0) penX = 0;
+ if (penY > 191) penY = 191;
+ if (penY < 0) penY = 0;
+ }
+
+// consolePrintf("x: %d y: %d\n", IPC->touchYpx - penDownY, IPC->touchYpx - penDownY);
+ penDownX = IPC->touchXpx;
+ penDownY = IPC->touchYpx;
+
+ }
+ }
+ else
+ {
+ }
+
+
+ } else {
+ penDown = true;
+ penHeld = true;
+ penDownSaved = true;
+
+ // First frame, so save pen positions
+ if (penDownThisFrame) {
+ penDownX = IPC->touchXpx;
+ penDownY = IPC->touchYpx;
+ }
+ }
+
} else {
- penReleased = false;
+ if (penHeld) {
+ penReleased = true;
+ penReleasedSaved = true;
+ } else {
+ penReleased = false;
+ }
+
+ penDown = false;
+ penHeld = false;
}
+ } else {
+ if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me.
+
+ if ((penHeld)) {
+ penHeld = true;
+ penDown = false;
+ } else {
+ penDown = true;
+ penHeld = true;
+ penDownSaved = true;
+ }
+
+ if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
+ penX = IPC->touchXpx + touchXOffset;
+ penY = IPC->touchYpx + touchYOffset;
+ moved = true;
+ }
+
- penDown = false;
- penHeld = false;
+
+ } else {
+ if (penHeld) {
+ penReleased = true;
+ penReleasedSaved = true;
+ } else {
+ penReleased = false;
+ }
+
+ penDown = false;
+ penHeld = false;
+ }
+
+
}
+
if ((IPC->touchZ1 > 0) || ((penDownFrames == 2)) ) {
penDownLastFrame = true;
penDownFrames++;
@@ -2259,7 +2539,6 @@ void penUpdate() {
penDownLastFrame = false;
penDownFrames = 0;
}
-
}
int leftHandedSwap(int keys) {
@@ -2346,8 +2625,7 @@ int getPenX() {
int x = ((penX * touchScX) >> 8) + touchX;
x = x < 0? 0: (x > gameWidth - 1? gameWidth - 1: x);
- if (snapToBorder)
- {
+ if (snapToBorder) {
if (x < 8) x = 0;
if (x > gameWidth - 8) x = gameWidth - 1;
}
@@ -2359,8 +2637,7 @@ int getPenY() {
int y = ((penY * touchScY) >> 8) + touchY;
y = y < 0? 0: (y > gameHeight - 1? gameHeight - 1: y);
- if (snapToBorder)
- {
+ if (snapToBorder) {
if (y < 8) y = 0;
if (y > gameHeight - 8) y = gameHeight - 1;
}
@@ -2377,6 +2654,8 @@ GLvector getPenPos() {
return v;
}
+#ifdef GBA_SRAM_SAVE
+
void formatSramOption() {
consolePrintf("The following files are present in save RAM:\n");
DSSaveFileManager::instance()->listFiles();
@@ -2398,7 +2677,7 @@ void formatSramOption() {
}
}
}
-
+#endif
void setIndyFightState(bool st) {
indyFightState = st;
@@ -2496,8 +2775,6 @@ struct cardTranslate {
char dldiId[5];
};
-#define NUM_CARD_READERS 7
-
cardTranslate cardReaderTable[] = {
{DEVICE_TYPE_M3SD, DEVICE_M3SD, "M3SD"},
{DEVICE_TYPE_M3CF, DEVICE_M3CF, "M3CF"},
@@ -2519,13 +2796,13 @@ void reboot() {
consolePrintf("DLDI Device ID: %s\n", id);
- for (int r = 0; r < NUM_CARD_READERS; r++) {
+ for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) {
if (!stricmp(id, cardReaderTable[r].dldiId)) {
deviceType = cardReaderTable[r].cartResetId;
}
}
} else {
- for (int r = 0; r < NUM_CARD_READERS; r++) {
+ for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) {
if (disc_getDeviceId() == cardReaderTable[r].svmId) {
deviceType = cardReaderTable[r].cartResetId;
}
@@ -2573,13 +2850,66 @@ void powerOff() {
/////////////////
-int main(void)
-{
+
+void dsExceptionHandler() {
+ consolePrintf("Blue screen of death");
+ setExceptionHandler(NULL);
+
+
+ u32 currentMode = getCPSR() & 0x1f;
+ u32 thumbState = ((*(u32*)0x027FFD90) & 0x20);
+
+ u32 codeAddress, exceptionAddress = 0;
+
+ int offset = 8;
+
+ if ( currentMode == 0x17 ) {
+ consolePrintf("\x1b[10Cdata abort!\n\n");
+ codeAddress = exceptionRegisters[15] - offset;
+ if ( (codeAddress > 0x02000000 && codeAddress < 0x02400000) ||
+ (codeAddress > (u32)__itcm_start && codeAddress < (u32)(__itcm_start + 32768)) )
+ exceptionAddress = getExceptionAddress( codeAddress, thumbState);
+ else
+ exceptionAddress = codeAddress;
+
+ } else {
+ if (thumbState)
+ offset = 2;
+ else
+ offset = 4;
+ consolePrintf("\x1b[5Cundefined instruction!\n\n");
+ codeAddress = exceptionRegisters[15] - offset;
+ exceptionAddress = codeAddress;
+ }
+
+ consolePrintf(" pc: %08X addr: %08X\n\n",codeAddress,exceptionAddress);
+
+ int i;
+ for ( i=0; i < 8; i++ ) {
+ consolePrintf( " %s: %08X %s: %08X\n",
+ registerNames[i], exceptionRegisters[i],
+ registerNames[i+8],exceptionRegisters[i+8]);
+ }
+// u32 *stack = (u32 *)exceptionRegisters[13];
+// for ( i=0; i<10; i++ ) {
+// consolePrintf( "\x1b[%d;2H%08X: %08X %08X", i + 14, (u32)&stack[i*2],stack[i*2], stack[(i*2)+1] );
+// }
+
+ memoryReport();
+
+ while(1);
+}
+
+
+
+
+int main(void) {
soundCallback = NULL;
initHardware();
+ setExceptionHandler(dsExceptionHandler);
#ifdef USE_DEBUGGER
for (int r = 0; r < 150; r++) {
@@ -2663,36 +2993,33 @@ int main(void)
consolePrintf("-------------------------------\n");
consolePrintf("ScummVM DS\n");
consolePrintf("Ported by Neil Millstone\n");
- consolePrintf("Version 0.11.1 beta2");
+ consolePrintf("Version 0.13.0 SVN ");
#if defined(DS_BUILD_A)
consolePrintf("build A\n");
consolePrintf("Lucasarts SCUMM games (SCUMM)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_B)
consolePrintf("build B\n");
consolePrintf("BASS, QUEEN\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_C)
consolePrintf("build C\n");
consolePrintf("Simon/Elvira/Waxworks (AGOS)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_D)
consolePrintf("build D\n");
consolePrintf("AGI, CINE, GOB\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_E)
consolePrintf("build E\n");
consolePrintf("Inherit the Earth (SAGA)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_F)
consolePrintf("build F\n");
consolePrintf("The Legend of Kyrandia (KYRA)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_G)
- consolePrintf("build F\n");
- consolePrintf("Lure of the Temptress (LURE)\n");
- consolePrintf("-------------------------------\n");
+ consolePrintf("build G\n");
+ consolePrintf("Lure of the Tempress (LURE)\n");
+#elif defined(DS_BUILD_H)
+ consolePrintf("build H\n");
+ consolePrintf("Nippon Safes (PARALLATION)\n");
#endif
+ consolePrintf("-------------------------------\n");
consolePrintf("L/R + D-pad/pen: Scroll view\n");
consolePrintf("D-pad left: Left mouse button\n");
consolePrintf("D-pad right: Right mouse button\n");
@@ -2808,9 +3135,11 @@ int main(void)
g_system = new OSystem_DS();
assert(g_system);
+#ifdef GBA_SRAM_SAVE
if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) {
formatSramOption();
}
+#endif
IPC->adpcm.semaphore = false;
@@ -2831,6 +3160,8 @@ int main(void)
const char *argv[] = {"/scummvmds", "--config=scummvmf.ini"};
#elif defined(DS_BUILD_G)
const char *argv[] = {"/scummvmds", "--config=scummvmg.ini"};
+#elif defined(DS_BUILD_H)
+ const char *argv[] = {"/scummvmds", "--config=scummvmh.ini"};
#endif
while (1) {
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index 43258b5c5d..ab74554917 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -38,7 +38,8 @@ enum controlType {
CONT_SIMON,
CONT_FUTURE_WARS,
CONT_AGI,
- CONT_GOBLINS
+ CONT_GOBLINS,
+ CONT_NIPPON,
};
struct gameListType {
@@ -56,6 +57,7 @@ int getPenX();
int getPenY();
GLvector getPenPos();
void consumePenEvents();
+controlType getControlType();
// Pad reading
int getKeysHeld();
@@ -64,6 +66,8 @@ int getKeysDown();
int getKeysReleased();
void consumeKeys();
int leftHandedSwap(int keys);
+void setGameScreenSwap(bool enable);
+void setSensitivity(int sensitivity);
// Video
void displayMode8Bit(); // Switch to 8-bit mode5
@@ -81,6 +85,7 @@ u16* getScalerBuffer();
void setTalkPos(int x, int y);
void setTopScreenTarget(int x, int y);
void set200PercentFixedScale(bool on);
+void setTopScreenZoom(int percentage);
// Timers
void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a callback function at a regular interval
@@ -88,7 +93,9 @@ int getMillis(); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Sound
-void doSoundCallback(); // Call function if sound buffers need more data
+void doSoundCallback();
+void startSound(int freq, int buffer); // Start sound hardware
+// Call function if sound buffers need more data
void playSound(const void* data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound
void stopSound(int channel);
int getSoundFrequency();
@@ -131,6 +138,8 @@ void setIndyFightState(bool st);
bool getIndyFightState();
bool isCpuScalerEnabled();
void setCpuScalerEnable(bool enable);
+void setTrackPadStyleEnable(bool enable);
+void setTapScreenClicksEnable(bool enable);
// Display
bool getIsDisplayMode8Bit();
diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp
index edb9c70580..2dbc4b842b 100644
--- a/backends/platform/ds/arm9/source/dsoptions.cpp
+++ b/backends/platform/ds/arm9/source/dsoptions.cpp
@@ -25,6 +25,7 @@
#include "gui/dialog.h"
#include "gui/newgui.h"
#include "gui/ListWidget.h"
+#include "gui/TabWidget.h"
#include "osystem_ds.h"
#include "engines/scumm/scumm.h"
#include "touchkeyboard.h"
@@ -41,8 +42,67 @@ namespace Scumm {
namespace DS {
-DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
- addButton(this, 10, 175, "Close", GUI::kCloseCmd, 'C');
+DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
+
+ addButton(this, 10, 170, "Close", GUI::kCloseCmd, 'C');
+ _tab = new GUI::TabWidget(this, 5, 5, 300, 230 - 20 - 40 - 10);
+
+ _tab->addTab("Controls");
+
+ _leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, "Left handed mode", 0, 'L');
+ _indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, "Indy fight controls", 0, 'I');
+ _showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, "Show mouse cursor", 0, 'T');
+ _snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, "Snap to edges", 0, 'T');
+
+ new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, "Touch X Offset", GUI::kTextAlignLeft);
+ _touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, 1);
+ _touchX->setMinValue(-8);
+ _touchX->setMaxValue(+8);
+ _touchX->setValue(0);
+ _touchX->setFlags(GUI::WIDGET_CLEARBG);
+
+ new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, "Touch Y Offset", GUI::kTextAlignLeft);
+ _touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, 2);
+ _touchY->setMinValue(-8);
+ _touchY->setMaxValue(+8);
+ _touchY->setValue(0);
+ _touchY->setFlags(GUI::WIDGET_CLEARBG);
+
+ new GUI::StaticTextWidget(_tab, 130 + 65 - 10, 65, 20, 15, "0", GUI::kTextAlignCenter);
+ new GUI::StaticTextWidget(_tab, 130 + 130 - 10, 65, 20, 15, "8", GUI::kTextAlignCenter);
+ new GUI::StaticTextWidget(_tab, 130 - 20, 65, 20, 15, "-8", GUI::kTextAlignCenter);
+
+
+ _touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, "Use laptop trackpad-style cursor control", 0x20000001, 'T');
+ _screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, "Tap for left click, double tap right click", 0x20000002, 'T');
+
+ _sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, "Sensitivity", GUI::kTextAlignLeft);
+ _sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, 1);
+ _sensitivity->setMinValue(4);
+ _sensitivity->setMaxValue(16);
+ _sensitivity->setValue(8);
+ _sensitivity->setFlags(GUI::WIDGET_CLEARBG);
+
+ _tab->addTab("Graphics");
+
+ new GUI::StaticTextWidget(_tab, 5, 70, 180, 15, "Initial top screen scale:", GUI::kTextAlignLeft);
+
+ _100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 85, 230, 20, "100%", 0x30000001, 'T');
+ _150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 100, 230, 20, "150%", 0x30000002, 'T');
+ _200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 115, 230, 20, "200%", 0x30000003, 'T');
+
+ new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, "Main screen scaling:", GUI::kTextAlignLeft);
+
+ _hardScaler = new GUI::CheckboxWidget(_tab, 5, 20, 270, 20, "Hardware scale (fast, but low quality)", 0x10000001, 'T');
+ _cpuScaler = new GUI::CheckboxWidget(_tab, 5, 35, 270, 20, "Software scale (good quality, but slower)", 0x10000002, 'S');
+ _unscaledCheckbox = new GUI::CheckboxWidget(_tab, 5, 50, 270, 20, "Unscaled (you must scroll left and right)", 0x10000003, 'S');
+
+ _tab->addTab("General");
+
+ _highQualityAudioCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
+ _disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, "Disable power off", 0, 'T');
+
+ _tab->setActiveTab(0);
_radioButtonMode = false;
@@ -52,46 +112,17 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
}
#endif
- new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
+// new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
- _leftHandedCheckbox = new GUI::CheckboxWidget(this, 5, 70, 130, 20, "Left handed mode", 0, 'L');
- _indyFightCheckbox = new GUI::CheckboxWidget(this, 5, 40, 200, 20, "Indy fighting controls", 0, 'I');
- _twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 5, 55, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T');
- _highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 5, 25, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
- _disablePowerOff = new GUI::CheckboxWidget(this, 5, 85, 130, 20, "Disable power off", 0, 'T');
- _showCursorCheckbox = new GUI::CheckboxWidget(this, 5, 100, 130, 20, "Show mouse cursor", 0, 'T');
//#ifdef ALLOW_CPU_SCALER
// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 'T');
//#endif
- new GUI::StaticTextWidget(this, 180, 70, 130, 15, "Main screen:", GUI::kTextAlignLeft);
-
- _hardScaler = new GUI::CheckboxWidget(this, 140, 85, 170, 20, "Hardware scale (fast)", 0x10000001, 'T');
- _cpuScaler = new GUI::CheckboxWidget(this, 140, 100, 170, 20, "Software scale (quality)", 0x10000002, 'S');
- _unscaledCheckbox = new GUI::CheckboxWidget(this, 140, 115, 170, 20, "Unscaled", 0x10000003, 'S');
- _snapToBorderCheckbox = new GUI::CheckboxWidget(this, 5, 115, 120, 20, "Snap to border", 0, 'T');
- new GUI::StaticTextWidget(this, 20, 145, 110, 15, "Touch X Offset", GUI::kTextAlignLeft);
- _touchX = new GUI::SliderWidget(this, 130, 145, 130, 12, 1);
- _touchX->setMinValue(-8);
- _touchX->setMaxValue(+8);
- _touchX->setValue(0);
- _touchX->setFlags(GUI::WIDGET_CLEARBG);
-
- new GUI::StaticTextWidget(this, 20, 160, 110, 15, "Touch Y Offset", GUI::kTextAlignLeft);
- _touchY = new GUI::SliderWidget(this, 130, 160, 130, 12, 2);
- _touchY->setMinValue(-8);
- _touchY->setMaxValue(+8);
- _touchY->setValue(0);
- _touchY->setFlags(GUI::WIDGET_CLEARBG);
-
- new GUI::StaticTextWidget(this, 130 + 65 - 10, 175, 20, 15, "0", GUI::kTextAlignCenter);
- new GUI::StaticTextWidget(this, 130 + 130 - 10, 175, 20, 15, "8", GUI::kTextAlignCenter);
- new GUI::StaticTextWidget(this, 130 - 10, 175, 20, 15, "-8", GUI::kTextAlignCenter);
#ifdef DS_SCUMM_BUILD
_delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm);
@@ -125,10 +156,36 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
_unscaledCheckbox->setState(false);
}
- if (ConfMan.hasKey("twohundredpercent", "ds")) {
- _twoHundredPercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
+
+ if (ConfMan.hasKey("topscreenzoom", "ds")) {
+
+ _100PercentCheckbox->setState(false);
+ _150PercentCheckbox->setState(false);
+ _200PercentCheckbox->setState(false);
+
+ switch (ConfMan.getInt("topscreenzoom", "ds"))
+ {
+ case 100: {
+ _100PercentCheckbox->setState(true);
+ break;
+ }
+
+ case 150: {
+ _150PercentCheckbox->setState(true);
+ break;
+ }
+
+ case 200: {
+ _200PercentCheckbox->setState(true);
+ break;
+ }
+ }
+
+ } else if (ConfMan.hasKey("twohundredpercent", "ds")) {
+ _200PercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
} else {
- _twoHundredPercentCheckbox->setState(false);
+ // No setting
+ _150PercentCheckbox->setState(true);
}
if (ConfMan.hasKey("22khzaudio", "ds")) {
@@ -165,6 +222,29 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
_touchY->setValue(0);
}
+ if (ConfMan.hasKey("sensitivity", "ds")) {
+ _sensitivity->setValue(ConfMan.getInt("sensitivity", "ds"));
+ } else {
+ _sensitivity->setValue(8);
+ }
+
+ if (ConfMan.hasKey("touchpad", "ds")) {
+ _touchPadStyle->setState(ConfMan.getBool("touchpad", "ds"));
+ } else {
+ _touchPadStyle->setState(0);
+ }
+
+ if (ConfMan.hasKey("screentaps", "ds")) {
+ _screenTaps->setState(ConfMan.getBool("screentaps", "ds"));
+ } else {
+ _screenTaps->setState(0);
+ }
+
+ _screenTaps->setEnabled(!_touchPadStyle->getState());
+ _sensitivity->setEnabled(_touchPadStyle->getState());
+ _sensitivityLabel->setEnabled(_touchPadStyle->getState());
+ _sensitivityLabel->draw();
+
if (!_cpuScaler->getState() && !_unscaledCheckbox->getState()) {
_hardScaler->setState(true);
}
@@ -180,7 +260,7 @@ DSOptionsDialog::~DSOptionsDialog() {
void DSOptionsDialog::updateConfigManager() {
ConfMan.setBool("lefthanded", _leftHandedCheckbox->getState(), "ds");
ConfMan.setBool("unscaled", _unscaledCheckbox->getState(), "ds");
- ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
+// ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds");
ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds");
#ifdef ALLOW_CPU_SCALER
@@ -190,6 +270,24 @@ void DSOptionsDialog::updateConfigManager() {
ConfMan.setInt("yoffset", _touchY->getValue(), "ds");
ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds");
ConfMan.setBool("snaptoborder", _snapToBorderCheckbox->getState(), "ds");
+ ConfMan.setBool("touchpad", _touchPadStyle->getState(), "ds");
+ ConfMan.setBool("screentaps", _screenTaps->getState(), "ds");
+ ConfMan.setInt("sensitivity", _sensitivity->getValue(), "ds");
+
+ u32 zoomLevel = 150;
+
+ if (_100PercentCheckbox->getState()) {
+ zoomLevel = 100;
+ } else if (_150PercentCheckbox->getState()) {
+ zoomLevel = 150;
+ } else if (_200PercentCheckbox->getState()) {
+ zoomLevel = 200;
+ }
+
+ consolePrintf("Saved zoom: %d\n", zoomLevel);
+
+ ConfMan.setInt("topscreenzoom", zoomLevel, "ds");
+
DS::setOptions();
}
@@ -227,6 +325,70 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint
}
+ if ((!guard) && (_radioButtonMode))
+ {
+ guard = true;
+
+ if ((sender == _touchPadStyle) && (cmd == 0x20000001)) {
+
+ if (_touchPadStyle->getState()) {
+ // Swap screens when turning on trackpad style, it feels
+ // much more natural!
+ DS::setGameScreenSwap(true);
+
+ _screenTaps->setState(true);
+ _screenTaps->setEnabled(false);
+ _screenTaps->draw();
+ _sensitivity->setEnabled(true);
+ _sensitivityLabel->setEnabled(true);
+ _sensitivityLabel->draw();
+ _sensitivity->draw();
+ } else {
+ DS::setGameScreenSwap(false);
+
+ _screenTaps->setEnabled(true);
+ _screenTaps->setState(false);
+ _screenTaps->draw();
+ _sensitivity->setEnabled(false);
+ _sensitivityLabel->setEnabled(false);
+ _sensitivityLabel->draw();
+ _sensitivity->draw();
+ }
+ }
+
+ guard = false;
+ }
+
+ if ((!guard) && (_radioButtonMode)) {
+
+ guard = true;
+
+ if (cmd == 0x30000001) {
+ _100PercentCheckbox->setState(true);
+ _150PercentCheckbox->setState(false);
+ _200PercentCheckbox->setState(false);
+ DS::setTopScreenZoom(100);
+ }
+
+ if (cmd == 0x30000002) {
+ _100PercentCheckbox->setState(false);
+ _150PercentCheckbox->setState(true);
+ _200PercentCheckbox->setState(false);
+ DS::setTopScreenZoom(150);
+ }
+
+ if (cmd == 0x30000003) {
+ _100PercentCheckbox->setState(false);
+ _150PercentCheckbox->setState(false);
+ _200PercentCheckbox->setState(true);
+ DS::setTopScreenZoom(200);
+ }
+
+ guard = false;
+
+ }
+
+
if (cmd == GUI::kCloseCmd) {
updateConfigManager();
close();
@@ -297,6 +459,8 @@ void showOptionsDialog() {
}
void setOptions() {
+ static bool firstLoad = true;
+
ConfMan.addGameDomain("ds");
if (ConfMan.hasKey("lefthanded", "ds")) {
@@ -327,10 +491,16 @@ void setOptions() {
DS::setUnscaledMode(false);
}
- if (ConfMan.hasKey("twohundredpercent", "ds")) {
- DS::set200PercentFixedScale(ConfMan.getBool("twohundredpercent", "ds"));
- } else {
- DS::set200PercentFixedScale(false);
+ if (firstLoad) {
+ if (ConfMan.hasKey("topscreenzoom", "ds")) {
+ DS::setTopScreenZoom(ConfMan.getInt("topscreenzoom", "ds"));
+ } else {
+ if (ConfMan.hasKey("twohundredpercent", "ds")) {
+ DS::setTopScreenZoom(200);
+ } else {
+ DS::setTopScreenZoom(150);
+ }
+ }
}
if (ConfMan.hasKey("xoffset", "ds")) {
@@ -345,6 +515,12 @@ void setOptions() {
DS::setTouchXOffset(0);
}
+ if (ConfMan.hasKey("sensitivity", "ds")) {
+ DS::setSensitivity(ConfMan.getInt("sensitivity", "ds"));
+ } else {
+ DS::setSensitivity(8);
+ }
+
#ifdef ALLOW_CPU_SCALER
if (ConfMan.hasKey("cpu_scaler", "ds")) {
DS::setCpuScalerEnable(ConfMan.getBool("cpu_scaler", "ds"));
@@ -353,6 +529,33 @@ void setOptions() {
}
#endif
+ if (ConfMan.hasKey("screentaps", "ds")) {
+ DS::setTapScreenClicksEnable(ConfMan.getBool("screentaps", "ds"));
+ } else {
+ DS::setTapScreenClicksEnable(false);
+ }
+
+ if (ConfMan.hasKey("touchpad", "ds")) {
+ bool enable = ConfMan.getBool("touchpad", "ds");
+
+ DS::setTrackPadStyleEnable(enable);
+
+ if ((enable) and (firstLoad)) {
+ // If we've just booted up, want to swap screens when trackpad mode is in use
+ // but not every time we enter the options dialog.
+ DS::setGameScreenSwap(true);
+ }
+
+ if (enable) {
+ DS::setTapScreenClicksEnable(true);
+ }
+
+ } else {
+ DS::setTrackPadStyleEnable(false);
+ }
+
+
+ firstLoad = false;
}
}
diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h
index 9cfa785ca8..e3ab2f55e0 100644
--- a/backends/platform/ds/arm9/source/dsoptions.h
+++ b/backends/platform/ds/arm9/source/dsoptions.h
@@ -30,6 +30,7 @@
#include "gui/object.h"
#include "gui/widget.h"
#include "gui/dialog.h"
+#include "gui/TabWidget.h"
#include "scumm/dialogs.h"
namespace DS {
@@ -45,11 +46,18 @@ protected:
void togglePause();
void updateConfigManager();
+ GUI::TabWidget* _tab;
+
+ GUI::StaticTextWidget* _sensitivityLabel;
+
GUI::SliderWidget* _touchX;
GUI::SliderWidget* _touchY;
+ GUI::SliderWidget* _sensitivity;
GUI::CheckboxWidget* _leftHandedCheckbox;
GUI::CheckboxWidget* _unscaledCheckbox;
- GUI::CheckboxWidget* _twoHundredPercentCheckbox;
+ GUI::CheckboxWidget* _100PercentCheckbox;
+ GUI::CheckboxWidget* _150PercentCheckbox;
+ GUI::CheckboxWidget* _200PercentCheckbox;
GUI::CheckboxWidget* _indyFightCheckbox;
GUI::CheckboxWidget* _highQualityAudioCheckbox;
GUI::CheckboxWidget* _disablePowerOff;
@@ -59,6 +67,9 @@ protected:
GUI::CheckboxWidget* _hardScaler;
GUI::CheckboxWidget* _cpuScaler;
+ GUI::CheckboxWidget* _touchPadStyle;
+ GUI::CheckboxWidget* _screenTaps;
+
#ifdef DS_SCUMM_BUILD
Scumm::SaveLoadChooser* _delDialog;
#endif
diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp
index 9c8af81a6e..a53ab9739d 100644
--- a/backends/platform/ds/arm9/source/gbampsave.cpp
+++ b/backends/platform/ds/arm9/source/gbampsave.cpp
@@ -54,8 +54,8 @@ bool GBAMPSaveFile::eos() const {
return DS::std_feof(handle);
}
-void GBAMPSaveFile::skip(uint32 bytes) {
- DS::std_fseek(handle, bytes, SEEK_CUR);
+bool GBAMPSaveFile::skip(uint32 bytes) {
+ return DS::std_fseek(handle, bytes, SEEK_CUR) == 0;
}
void GBAMPSaveFile::flushSaveBuffer() {
@@ -67,11 +67,11 @@ void GBAMPSaveFile::flushSaveBuffer() {
}
}
-uint32 GBAMPSaveFile::pos() const {
+int32 GBAMPSaveFile::pos() const {
return DS::std_ftell(handle);
}
-uint32 GBAMPSaveFile::size() const {
+int32 GBAMPSaveFile::size() const {
int position = pos();
DS::std_fseek(handle, 0, SEEK_END);
int size = DS::std_ftell(handle);
@@ -79,8 +79,8 @@ uint32 GBAMPSaveFile::size() const {
return size;
}
-void GBAMPSaveFile::seek(int32 pos, int whence) {
- DS::std_fseek(handle, pos, whence);
+bool GBAMPSaveFile::seek(int32 pos, int whence) {
+ return DS::std_fseek(handle, pos, whence) == 0;
}
@@ -155,11 +155,13 @@ GBAMPSaveFile* GBAMPSaveFileManager::openSavefile(char const* name, bool saveOrL
sprintf(fileSpec, "%s/%s", getSavePath(), name);
}
-// consolePrintf(fileSpec);
+// consolePrintf("Opening the file: %s\n", fileSpec);
GBAMPSaveFile* sf = new GBAMPSaveFile(fileSpec, saveOrLoad);
if (sf->isOpen()) {
+// consolePrintf("Ok");
return sf;
} else {
+// consolePrintf("Fail");
delete sf;
return NULL;
}
@@ -192,8 +194,29 @@ Common::StringList GBAMPSaveFileManager::listSavefiles(const char *pattern) {
enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 };
char name[256];
- DS::std_cwd((char*)getSavePath()); //TODO : Check this suspicious const-cast
-// consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(),pattern);
+ {
+ char dir[128];
+ strcpy(dir, getSavePath());
+ char *realName = dir;
+
+ if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
+ realName += 4;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+ FAT_chdir(realName);
+
+ }
+
+// consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(), pattern);
int fileType = FAT_FindFirstFileLFN(name);
@@ -206,7 +229,7 @@ Common::StringList GBAMPSaveFileManager::listSavefiles(const char *pattern) {
FAT_GetLongFilename(name);
- for (int r = 0; r < strlen(name); r++) {
+ for (int r = 0; name[r] != 0; r++) {
name[r] = tolower(name[r]);
}
diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h
index d0cbc68bfd..6ddc4fd964 100644
--- a/backends/platform/ds/arm9/source/gbampsave.h
+++ b/backends/platform/ds/arm9/source/gbampsave.h
@@ -43,11 +43,11 @@ public:
virtual uint32 write(const void *buf, uint32 size);
virtual bool eos() const;
- virtual void skip(uint32 bytes);
+ virtual bool skip(uint32 bytes);
- virtual uint32 pos() const;
- virtual uint32 size() const;
- virtual void seek(int32 pos, int whence);
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ virtual bool seek(int32 pos, int whence);
void flushSaveBuffer();
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index 79b0c5390b..5ddcb50b15 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -41,7 +41,8 @@
OSystem_DS* OSystem_DS::_instance = NULL;
OSystem_DS::OSystem_DS()
- : eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false)
+ : eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false),
+ _disableCursorPalette(true), _graphicsEnable(true)
{
// eventNum = 0;
// lastPenFrame = 0;
@@ -71,7 +72,13 @@ void OSystem_DS::initBackend() {
_timer = new DSTimerManager();
DS::setTimerCallback(&OSystem_DS::timerHandler, 10);
- _mixer->setOutputRate(11025 /*DS::getSoundFrequency()*/);
+ if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) {
+ DS::startSound(22050, 8192);
+ } else {
+ DS::startSound(11025, 4096);
+ }
+
+ _mixer->setOutputRate(DS::getSoundFrequency());
_mixer->setReady(true);
OSystem::initBackend();
@@ -79,7 +86,7 @@ void OSystem_DS::initBackend() {
bool OSystem_DS::hasFeature(Feature f) {
// consolePrintf("hasfeature\n");
- return (f == kFeatureVirtualKeyboard);
+ return (f == kFeatureVirtualKeyboard) || (f == kFeatureCursorHasPalette);
}
void OSystem_DS::setFeatureState(Feature f, bool enable) {
@@ -107,7 +114,7 @@ bool OSystem_DS::setGraphicsMode(int mode) {
}
bool OSystem_DS::setGraphicsMode(const char *name) {
-// consolePrintf("Set gfx mode %s\n", name);
+ consolePrintf("Set gfx mode %s\n", name);
return true;
}
@@ -116,8 +123,15 @@ int OSystem_DS::getGraphicsMode() const {
}
void OSystem_DS::initSize(uint width, uint height) {
-// consolePrintf("Set gfx mode %d x %d\n", width, height);
- DS::setGameSize(width, height);
+ // For Lost in Time, the title screen is displayed in 640x400.
+ // In order to support this game, the screen mode is set, but
+ // all draw calls are ignored until the game switches to 320x200.
+ if ((width == 640) && (height == 400)) {
+ _graphicsEnable = false;
+ } else {
+ _graphicsEnable = true;
+ DS::setGameSize(width, height);
+ }
}
int16 OSystem_DS::getHeight() {
@@ -129,9 +143,8 @@ int16 OSystem_DS::getWidth() {
}
void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
-// consolePrintf("Set palette %d, %d colours\n", start, num);
-//return;
- if (!DS::getIsDisplayMode8Bit()) return;
+// consolePrintf("Setpal %d, %d\n", start, num);
+
for (unsigned int r = start; r < start + num; r++) {
int red = *colors;
int green = *(colors + 1);
@@ -141,17 +154,44 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
green >>= 3;
blue >>= 3;
- if (r != 255)
+// if (r != 255)
{
- BG_PALETTE[r] = red | (green << 5) | (blue << 10);
- if (!DS::getKeyboardEnable()) {
- BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10);
+ u16 paletteValue = red | (green << 5) | (blue << 10);
+
+ if (DS::getIsDisplayMode8Bit()) {
+ BG_PALETTE[r] = paletteValue;
+ if (!DS::getKeyboardEnable()) {
+ BG_PALETTE_SUB[r] = paletteValue;
+ }
}
+
+ _palette[r] = paletteValue;
}
-// if (num == 16) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
+ // if (num == 255) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
+
+ colors += 4;
+ }
+}
+
+void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
+
+// consolePrintf("Cursor palette set: start: %d, cols: %d\n", start, num);
+ for (unsigned int r = start; r < start + num; r++) {
+ int red = *colors;
+ int green = *(colors + 1);
+ int blue = *(colors + 2);
+
+ red >>= 3;
+ green >>= 3;
+ blue >>= 3;
+ u16 paletteValue = red | (green << 5) | (blue << 10);
+ _cursorPalette[r] = paletteValue;
+
colors += 4;
}
+
+ _disableCursorPalette = false;
}
bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
@@ -184,9 +224,11 @@ void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) {
}
+#define MISALIGNED16(ptr) (((u32) (ptr) & 1) != 0)
+
void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
-// consolePrintf("Copy rect %d, %d %d, %d ", x, y, w, h);
-
+ //consolePrintf("Copy rect %d, %d %d, %d ", x, y, w, h);
+ if (!_graphicsEnable) return;
if (w <= 1) return;
if (h < 0) return;
if (!DS::getIsDisplayMode8Bit()) return;
@@ -195,6 +237,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
s32 stride;
u16* bgSub = (u16 *) BG_GFX_SUB;
+ // The DS video RAM doesn't support 8-bit writes because Nintendo wanted
+ // to save a few pennies/euro cents on the hardware.
+
if (_frameBufferExists) {
bg = (u16 *) _framebuffer.pixels;
stride = _framebuffer.pitch;
@@ -203,46 +248,117 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
stride = DS::get8BitBackBufferStride();
}
- u16* src = (u16 *) buf;
-
- if (DS::getKeyboardEnable()) {
-
+ if (((pitch & 1) != 0) || ((w & 1) != 0) || (((int) (buf) & 1) != 0)) {
+
+ // Something is misaligned, so we have to use the slow but sure method
+
+ int by = 0;
+
for (int dy = y; dy < y + h; dy++) {
- u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
-
- DC_FlushRange(src, w << 1);
- DC_FlushRange(dest, w << 1);
- dmaCopyHalfWords(3, src, dest, w);
-
- src += pitch >> 1;
+ u8* dest = ((u8 *) (bg)) + (dy * stride) + x;
+ u8* destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
+ u8* src = (u8 *) buf + (pitch * by);
+
+ u32 dx;
+
+ u32 pixelsLeft = w;
+
+ if (MISALIGNED16(dest)) {
+ // Read modify write
+
+ dest--;
+ u16 mix = *((u16 *) dest);
+
+ mix = (mix & 0x00FF) | (*src++ << 8);
+
+ *dest = mix;
+ *destSub = mix;
+
+ dest += 2;
+ destSub += 2;
+ pixelsLeft--;
+ }
+
+ // We can now assume dest is aligned
+ u16* dest16 = (u16 *) dest;
+ u16* destSub16 = (u16 *) destSub;
+
+ for (dx = 0; dx < pixelsLeft; dx+=2) {
+ u16 mix;
+
+ mix = *src + (*(src + 1) << 8);
+ *dest16++ = mix;
+ *destSub16++ = mix;
+ src += 2;
+ }
+
+ pixelsLeft -= dx;
+
+ // At the end we may have one pixel left over
+
+ if (pixelsLeft != 0) {
+ u16 mix = *dest16;
+
+ mix = (mix & 0x00FF) | ((*src++) << 8);
+
+ *dest16 = mix;
+ *destSub16 = mix;
+ }
+
+ by++;
+
}
-
+
+// consolePrintf("Slow method used!\n");
+
+
} else {
- for (int dy = y; dy < y + h; dy++) {
- u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
- u16* dest2 = bgSub + (dy << 8) + (x >> 1);
+
+ // Stuff is aligned to 16-bit boundaries, so it's safe to do DMA.
+
+ u16* src = (u16 *) buf;
+
+ if (DS::getKeyboardEnable()) {
+
+ for (int dy = y; dy < y + h; dy++) {
+ u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
- DC_FlushRange(src, w << 1);
- DC_FlushRange(dest1, w << 1);
- DC_FlushRange(dest2, w << 1);
-
- dmaCopyHalfWords(3, src, dest1, w);
- dmaCopyHalfWords(3, src, dest2, w);
-
- src += pitch >> 1;
- }
- }
+ DC_FlushRange(src, w << 1);
+ DC_FlushRange(dest, w << 1);
+ dmaCopyHalfWords(3, src, dest, w);
-// consolePrintf("Done\n");
+ while (dmaBusy(3));
+
+ src += pitch >> 1;
+ }
+
+ } else {
+ for (int dy = y; dy < y + h; dy++) {
+ u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
+ u16* dest2 = bgSub + (dy << 8) + (x >> 1);
+
+ DC_FlushRange(src, w << 1);
+ DC_FlushRange(dest1, w << 1);
+ DC_FlushRange(dest2, w << 1);
+
+ dmaCopyHalfWords(3, src, dest1, w);
-
+ if ((!_frameBufferExists) || (buf == _framebuffer.pixels)) {
+ dmaCopyHalfWords(2, src, dest2, w);
+ }
+ while (dmaBusy(2) || dmaBusy(3));
+
+ src += pitch >> 1;
+ }
+ }
+ }
+// consolePrintf("Done\n");
}
void OSystem_DS::updateScreen() {
- if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit()))
- {
+ if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit())) {
_frameBufferExists = false;
// Copy temp framebuffer back to screen
@@ -253,6 +369,12 @@ void OSystem_DS::updateScreen() {
DS::doSoundCallback();
// DS::doTimerCallback();
DS::addEventsToQueue();
+
+ // Force back buffer usage for Nippon Safes, as it doesn't double buffer it's output
+ if (DS::getControlType() == DS::CONT_NIPPON) {
+ OSystem_DS::instance()->lockScreen();
+ OSystem_DS::instance()->unlockScreen();
+ }
}
void OSystem_DS::setShakePos(int shakeOffset) {
@@ -334,7 +456,21 @@ void OSystem_DS::warpMouse(int x, int y) {
}
void OSystem_DS::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetCursorScale) {
- DS::setCursorIcon(buf, w, h, keycolor, hotspotX, hotspotY);
+ if ((w > 0) && (w < 64) && (h > 0) && (h < 64))
+ {
+ memcpy(_cursorImage, buf, w * h);
+ _cursorW = w;
+ _cursorH = h;
+ _cursorHotX = hotspotX;
+ _cursorHotY = hotspotY;
+ _cursorKey = keycolor;
+ _cursorScale = targetCursorScale;
+ refreshCursor();
+ }
+}
+
+void OSystem_DS::refreshCursor() {
+ DS::setCursorIcon(_cursorImage, _cursorW, _cursorH, _cursorKey, _cursorHotX, _cursorHotY);
}
void OSystem_DS::addEvent(Common::Event& e) {
@@ -489,7 +625,11 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager() {
if (DS::isGBAMPAvailable() && (!forceSram)) {
return &mpSaveManager;
} else {
+#ifdef GBA_SRAM_SAVE
return &saveManager;
+#else
+ return NULL;
+#endif
}
}
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index 8c8d661ad8..16c8f41491 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -52,17 +52,32 @@ protected:
Common::Event eventQueue[96];
int queuePos;
+#ifdef GBA_SRAM_SAVE
DSSaveFileManager saveManager;
+#endif
GBAMPSaveFileManager mpSaveManager;
DSAudioMixer* _mixer;
DSTimerManager* _timer;
Graphics::Surface _framebuffer;
bool _frameBufferExists;
-
+ bool _graphicsEnable;
static OSystem_DS* _instance;
+
+ u16 _palette[256];
+ u16 _cursorPalette[256];
+
+ u8 _cursorImage[64 * 64];
+ uint _cursorW;
+ uint _cursorH;
+ int _cursorHotX;
+ int _cursorHotY;
+ byte _cursorKey;
+ int _cursorScale;
+
Graphics::Surface* createTempFrameBuffer();
+ bool _disableCursorPalette;
public:
typedef void (*SoundProc)(byte *buf, int len);
@@ -159,7 +174,16 @@ public:
virtual void clearAutoComplete();
virtual void setCharactersEntered(int count);
+ u16 getDSPaletteEntry(u32 entry) { return _palette[entry]; }
+ u16 getDSCursorPaletteEntry(u32 entry) { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; }
+
+ virtual void setCursorPalette(const byte *colors, uint start, uint num);
+
+ virtual void disableCursorPalette(bool dis) { _disableCursorPalette = dis; refreshCursor(); }
+
FilesystemFactory *getFilesystemFactory();
+
+ void refreshCursor();
};
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
diff --git a/backends/platform/ds/arm9/source/portdefs.h b/backends/platform/ds/arm9/source/portdefs.h
index de7a5795f5..16f3d8cc9b 100644
--- a/backends/platform/ds/arm9/source/portdefs.h
+++ b/backends/platform/ds/arm9/source/portdefs.h
@@ -81,7 +81,10 @@ void consolePrintf(const char* s, ...);
#define ITCM_DATA __attribute__((section(".itcm")))
-
+// Since I can't change the engine at the moment (post lockdown) this define can go here.
+// This define changes the mouse-relative motion which doesn't make sense on a touch screen to
+// a more conventional form of input where the menus can be clicked on.
+#define LURE_CLICKABLE_MENUS
//#include "common/array.h"
//#include "common/str.h"
diff --git a/backends/platform/ds/arm9/source/ramsave.cpp b/backends/platform/ds/arm9/source/ramsave.cpp
index be355ce76f..a9f4e3d2fc 100644
--- a/backends/platform/ds/arm9/source/ramsave.cpp
+++ b/backends/platform/ds/arm9/source/ramsave.cpp
@@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
- // Save in order 1,2,3,4,larger 2,5
+#ifdef GBA_SRAM_SAVE
+
+
#include "ramsave.h"
#include "nds.h"
#include "compressor/lz.h"
@@ -64,6 +66,7 @@ DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) {
}
isTempFile = false;
+ eosReached = false;
}
DSSaveFile::~DSSaveFile() {
@@ -167,11 +170,13 @@ int DSSaveFile::saveToSaveRAM(vu8* address) {
void DSSaveFile::reset() {
ptr = 0;
+ eosReached = false;
}
uint32 DSSaveFile::read(void *buf, uint32 size) {
if (ptr + size > save.size) {
size = save.size - ptr;
+ eosReached = true;
if (size < 0) size = 0;
}
memcpy(buf, saveData + ptr, size);
@@ -181,15 +186,15 @@ uint32 DSSaveFile::read(void *buf, uint32 size) {
return size;
}
-uint32 DSSaveFile::pos() const {
+int32 DSSaveFile::pos() const {
return ptr;
}
-uint32 DSSaveFile::size() const {
+int32 DSSaveFile::size() const {
return save.size;
}
-void DSSaveFile::seek(int32 pos, int whence) {
+bool DSSaveFile::seek(int32 pos, int whence) {
switch (whence) {
case SEEK_SET: {
ptr = pos;
@@ -204,15 +209,22 @@ void DSSaveFile::seek(int32 pos, int whence) {
break;
}
}
+ eosReached = false;
+ return true;
}
bool DSSaveFile::eos() const {
- return ptr >= (int) save.size;
+ return eosReached;
}
-void DSSaveFile::skip(uint32 bytes) {
+void DSSaveFile::clearErr() {
+ eosReached = false;
+}
+
+bool DSSaveFile::skip(uint32 bytes) {
ptr = ptr + bytes;
if (ptr > (int) save.size) ptr = save.size;
+ return true;
}
uint32 DSSaveFile::write(const void *buf, uint32 size) {
@@ -227,7 +239,7 @@ uint32 DSSaveFile::write(const void *buf, uint32 size) {
return size;
}
-bool DSSaveFile::matches(char* prefix, int num) {
+bool DSSaveFile::matches(const char *prefix, int num) {
char str[16];
if (isValid()) {
sprintf(str, "%s%02d", prefix, num);
@@ -241,7 +253,7 @@ bool DSSaveFile::matches(char* prefix, int num) {
}
}
-bool DSSaveFile::matches(char* filename) {
+bool DSSaveFile::matches(const char *filename) {
if (isValid()) {
return !strcmp(save.name, filename);
} else {
@@ -522,3 +534,5 @@ int DSSaveFileManager::getExtraData() {
return 0;
}
}
+
+#endif
diff --git a/backends/platform/ds/arm9/source/ramsave.h b/backends/platform/ds/arm9/source/ramsave.h
index f919da18db..034e957b7f 100644
--- a/backends/platform/ds/arm9/source/ramsave.h
+++ b/backends/platform/ds/arm9/source/ramsave.h
@@ -52,6 +52,7 @@ class DSSaveFile : public Common::InSaveFile, public Common::OutSaveFile {
SCUMMSave* origHeader;
bool isOpenFlag;
bool isTempFile;
+ bool eosReached;
public:
DSSaveFile();
@@ -62,11 +63,12 @@ public:
bool isOpen() const { return isOpenFlag; }
virtual bool eos() const;
- virtual void skip(uint32 size);
+ virtual void clearErr();
+ virtual bool skip(uint32 size);
- virtual uint32 pos() const;
- virtual uint32 size() const;
- virtual void seek(int32 pos, int whence);
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ virtual bool seek(int32 pos, int whence);
uint32 read(void *buf, uint32 size);
uint32 write(const void *buf, uint32 size);
@@ -76,8 +78,8 @@ public:
bool isValid() { return save.isValid; }
bool isTemp() { return isTempFile; }
- bool matches(char* prefix, int num);
- bool matches(char* filename);
+ bool matches(const char *prefix, int num);
+ bool matches(const char *filename);
void clearData();
void compress();
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp
index 11832f4e3a..85f80fac92 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.cpp
+++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp
@@ -402,6 +402,23 @@ void createKeyEvent(int keyNum, Common::Event& event)
}
}
+void releaseAllKeys() {
+ for (int r = 0; r < DS_NUM_KEYS; r++) {
+ if (keys[r].pressed) {
+ DS::setKeyHighlight(r, false);
+
+ OSystem_DS* system = OSystem_DS::instance();
+
+ Common::Event event;
+ createKeyEvent(r, event);
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+
+ keys[r].pressed = false;
+ }
+ }
+}
+
void addKeyboardEvents() {
bool resetShift = false;
@@ -446,7 +463,7 @@ void addKeyboardEvents() {
// consolePrintf("Key: %d\n", r);
if ((keys[r].character == Common::KEYCODE_INVALID)) {
// Close button
- DS::closed = true;
+ //DS::closed = true;
} else {
createKeyEvent(r, event);
}
@@ -492,9 +509,14 @@ void addKeyboardEvents() {
OSystem_DS* system = OSystem_DS::instance();
Common::Event event;
- createKeyEvent(r, event);
- event.type = Common::EVENT_KEYUP;
- system->addEvent(event);
+ if ((keys[r].character == Common::KEYCODE_INVALID)) {
+ // Close button
+ DS::closed = true;
+ } else {
+ createKeyEvent(r, event);
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+ }
keys[r].pressed = false;
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h
index 8a5fc728ce..91efbc1e9a 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.h
+++ b/backends/platform/ds/arm9/source/touchkeyboard.h
@@ -40,6 +40,7 @@ bool getKeyboardClosed();
void addAutoComplete(char* word);
void clearAutoComplete();
void setCharactersEntered(int count);
+void releaseAllKeys();
}
diff --git a/backends/platform/ds/logog.bmp b/backends/platform/ds/logog.bmp
new file mode 100644
index 0000000000..9c194d3f82
--- /dev/null
+++ b/backends/platform/ds/logog.bmp
Binary files differ
diff --git a/backends/platform/ds/makefile b/backends/platform/ds/makefile
index 3fb19e939c..a9fbb13637 100644
--- a/backends/platform/ds/makefile
+++ b/backends/platform/ds/makefile
@@ -36,3 +36,23 @@ allbuilds:
make all SCUMM_BUILD=f
make semiclean
make all SCUMM_BUILD=g
+ make semiclean
+ make all SCUMM_BUILD=h
+
+allbuildssafe:
+ make clean SCUMM_BUILD=a
+ make all SCUMM_BUILD=a
+ make clean SCUMM_BUILD=b
+ make all SCUMM_BUILD=b
+ make clean SCUMM_BUILD=c
+ make all SCUMM_BUILD=c
+ make clean SCUMM_BUILD=d
+ make all SCUMM_BUILD=d
+ make clean SCUMM_BUILD=e
+ make all SCUMM_BUILD=e
+ make clean SCUMM_BUILD=f
+ make all SCUMM_BUILD=f
+ make clean SCUMM_BUILD=g
+ make all SCUMM_BUILD=g
+ make clean SCUMM_BUILD=h
+ make all SCUMM_BUILD=h
diff --git a/backends/platform/iphone/iphone_keyboard.m b/backends/platform/iphone/iphone_keyboard.m
index bd4948e30a..fda481933d 100644
--- a/backends/platform/iphone/iphone_keyboard.m
+++ b/backends/platform/iphone/iphone_keyboard.m
@@ -54,8 +54,7 @@
@implementation SoftKeyboard
- (id)initWithFrame:(CGRect)frame {
- //self = [super initWithFrame:frame];
- self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
+ self = [super initWithFrame:frame];
inputDelegate = nil;
inputView = [[TextInputHandler alloc] initWithKeyboard:self];
return self;
diff --git a/backends/platform/iphone/iphone_main.m b/backends/platform/iphone/iphone_main.m
index b01e9f3f34..6b709b0803 100644
--- a/backends/platform/iphone/iphone_main.m
+++ b/backends/platform/iphone/iphone_main.m
@@ -79,10 +79,7 @@ int main(int argc, char** argv) {
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// hide the status bar
[UIHardware _setStatusBarHeight:0.0f];
- //[self setStatusBarMode:2 orientation:0 duration:0.0f fenceID:0];
-
- //[self setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
- [self setStatusBarHidden:YES animated:YES];
+ [self setStatusBarHidden:YES animated:NO];
_window = [[UIWindow alloc] initWithContentRect: [UIHardware fullScreenApplicationContentRect]];
[_window retain];
@@ -103,9 +100,13 @@ int main(int argc, char** argv) {
- (void)applicationResume:(GSEventRef)event {
[self removeApplicationBadge];
- [UIHardware _setStatusBarHeight:0.0f];
- [self setStatusBarHidden:YES animated:YES];
[_view applicationResume];
+
+ // Workaround, need to "hide" and unhide the statusbar to properly remove it,
+ // since the Springboard has put it back without apparently flagging our application.
+ [self setStatusBarHidden:NO animated:NO]; // hide status bar
+ [UIHardware _setStatusBarHeight:0.0f];
+ [self setStatusBarHidden:YES animated:NO]; // hide status bar
}
- (void)deviceOrientationChanged:(GSEvent *)event {
diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m
index 89f159c1d9..910f14ab58 100644
--- a/backends/platform/iphone/iphone_video.m
+++ b/backends/platform/iphone/iphone_video.m
@@ -169,10 +169,6 @@ bool getLocalMouseCoords(CGPoint *point) {
nil
];
- if (_screenSurface != nil) {
- //[[sharedInstance _layer] removeSublayer: screenLayer];
- }
-
//("Allocating surface: %d\n", allocSize);
_screenSurface = CoreSurfaceBufferCreate((CFDictionaryRef)dict);
//printf("Surface created.\n");
@@ -205,10 +201,13 @@ bool getLocalMouseCoords(CGPoint *point) {
[screenLayer setFrame: _screenRect];
} else {
float ratio = (float)_height / (float)_width;
- _screenRect = CGRectMake(0, 0, _fullWidth, _fullWidth * ratio);
+ int height = _fullWidth * ratio;
+ //printf("Making rect (%u, %u)\n", _fullWidth, height);
+ _screenRect = CGRectMake(0, 0, _fullWidth - 1, height - 1);
[screenLayer setFrame: _screenRect];
- CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
+ //CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
+ CGRect keyFrame = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
if (_keyboardView == nil) {
_keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
[_keyboardView setInputDelegate:self];
@@ -250,9 +249,6 @@ bool getLocalMouseCoords(CGPoint *point) {
[self lock];
id event = [_events objectAtIndex: 0];
- if (event == nil) {
- return nil;
- }
[_events removeObjectAtIndex: 0];
[self unlock];
diff --git a/backends/platform/iphone/osys_iphone.cpp b/backends/platform/iphone/osys_iphone.cpp
index 3d5571cf3a..521e91a87e 100644
--- a/backends/platform/iphone/osys_iphone.cpp
+++ b/backends/platform/iphone/osys_iphone.cpp
@@ -56,24 +56,27 @@ const OSystem::GraphicsMode OSystem_IPHONE::s_supportedGraphicsModes[] = {
AQCallbackStruct OSystem_IPHONE::s_AudioQueue;
SoundProc OSystem_IPHONE::s_soundCallback = NULL;
void *OSystem_IPHONE::s_soundParam = NULL;
-bool OSystem_IPHONE::s_is113OrHigher = false;
OSystem_IPHONE::OSystem_IPHONE() :
_savefile(NULL), _mixer(NULL), _timer(NULL), _offscreen(NULL),
_overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL),
_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0),
_secondaryTapped(false), _lastSecondaryTap(0), _screenOrientation(kScreenOrientationFlippedLandscape),
- _needEventRestPeriod(false), _mouseClickAndDragEnabled(false),
+ _needEventRestPeriod(false), _mouseClickAndDragEnabled(false), _touchpadModeEnabled(false),
_gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false),
- _mouseDirty(false), _timeSuspended(0)
+ _mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1)
+
{
_queuedInputEvent.type = (Common::EventType)0;
_lastDrawnMouseRect = Common::Rect(0, 0, 0, 0);
+
+ _fsFactory = new POSIXFilesystemFactory();
}
OSystem_IPHONE::~OSystem_IPHONE() {
AudioQueueDispose(s_AudioQueue.queue, true);
+ delete _fsFactory;
delete _savefile;
delete _mixer;
delete _timer;
@@ -665,8 +668,8 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
float xUnit, yUnit;
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit)) {
- int x;
- int y;
+ int x = 0;
+ int y = 0;
switch (_screenOrientation) {
case kScreenOrientationPortrait:
x = (int)(xUnit * _screenWidth);
@@ -684,334 +687,436 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
switch ((InputEvent)eventType) {
case kInputMouseDown:
- //printf("Mouse down at (%u, %u)\n", x, y);
-
- // Workaround: kInputMouseSecondToggled isn't always sent when the
- // secondary finger is lifted. Need to make sure we get out of that mode.
- _secondaryTapped = false;
-
- warpMouse(x, y);
- // event.type = Common::EVENT_MOUSEMOVE;
- // event.mouse.x = _mouseX;
- // event.mouse.y = _mouseY;
-
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- return true;
- } else {
- _lastMouseDown = curTime;
- }
- return false;
+ if (!handleEvent_mouseDown(event, x, y))
+ return false;
break;
- case kInputMouseUp:
- //printf("Mouse up at (%u, %u)\n", x, y);
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- } else {
- if (curTime - _lastMouseDown < 250) {
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
-
- _queuedInputEvent.type = Common::EVENT_LBUTTONUP;
- _queuedInputEvent.mouse.x = _mouseX;
- _queuedInputEvent.mouse.y = _mouseY;
- _lastMouseTap = curTime;
- _needEventRestPeriod = true;
- } else
- return false;
- }
+ case kInputMouseUp:
+ if (!handleEvent_mouseUp(event, x, y))
+ return false;
break;
+
case kInputMouseDragged:
- //printf("Mouse dragged at (%u, %u)\n", x, y);
- if (_secondaryTapped) {
- if (_gestureStartX == -1 || _gestureStartY == -1) {
- return false;
- }
-
- int vecX = (x - _gestureStartX);
- int vecY = (y - _gestureStartY);
- int lengthSq = vecX * vecX + vecY * vecY;
- //printf("Lengthsq: %u\n", lengthSq);
-
- if (lengthSq > 15000) { // Long enough gesture to react upon.
- _gestureStartX = -1;
- _gestureStartY = -1;
-
- float vecLength = sqrt(lengthSq);
- float vecXNorm = vecX / vecLength;
- float vecYNorm = vecY / vecLength;
-
- //printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm);
-
- if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) {
- // Swipe down
- event.type = Common::EVENT_KEYDOWN;
- _queuedInputEvent.type = Common::EVENT_KEYUP;
-
- event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
- _needEventRestPeriod = true;
- } else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
- // Swipe up
- _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
- const char *dialogMsg;
- if (_mouseClickAndDragEnabled)
- dialogMsg = "Mouse-click-and-drag mode enabled.";
- else
- dialogMsg = "Mouse-click-and-drag mode disabled.";
- GUI::TimedMessageDialog dialog(dialogMsg, 1500);
- dialog.runModal();
- return false;
- } else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
- // Swipe right
- // _secondaryTapped = !_secondaryTapped;
- // _gestureStartX = x;
- // _gestureStartY = y;
- //
- // GUI::TimedMessageDialog dialog("Forcing toggle of pressed state.", 1500);
- // dialog.runModal();
- return false;
- } else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
- // Swipe left
- return false;
- } else
- return false;
- } else
- return false;
- } else {
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse.x = x;
- event.mouse.y = y;
- warpMouse(x, y);
- }
+ if (!handleEvent_mouseDragged(event, x, y))
+ return false;
break;
+
case kInputMouseSecondToggled:
_secondaryTapped = !_secondaryTapped;
//printf("Mouse second at (%u, %u). State now %s.\n", x, y, _secondaryTapped ? "on" : "off");
if (_secondaryTapped) {
- _lastSecondaryDown = curTime;
- _gestureStartX = x;
- _gestureStartY = y;
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
-
- _queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
- _queuedInputEvent.mouse.x = _mouseX;
- _queuedInputEvent.mouse.y = _mouseY;
- }
- else
+ if (!handleEvent_secondMouseDown(event, x, y))
return false;
} else {
- if (curTime - _lastSecondaryDown < 250 ) {
- if (curTime - _lastSecondaryTap < 250 && !_overlayVisible) {
- event.type = Common::EVENT_KEYDOWN;
- _queuedInputEvent.type = Common::EVENT_KEYUP;
-
- event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
- _needEventRestPeriod = true;
- _lastSecondaryTap = 0;
- } else if (!_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
- _queuedInputEvent.mouse.x = _mouseX;
- _queuedInputEvent.mouse.y = _mouseY;
- _lastSecondaryTap = curTime;
- _needEventRestPeriod = true;
- }
- }
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_RBUTTONUP;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- }
- }
- break;
- case kInputOrientationChanged:
- //printf("Orientation: %i", (int)xUnit);
-
- ScreenOrientation newOrientation;
- switch ((int)xUnit) {
- case 1:
- newOrientation = kScreenOrientationPortrait;
- break;
- case 3:
- newOrientation = kScreenOrientationLandscape;
- break;
- case 4:
- newOrientation = kScreenOrientationFlippedLandscape;
- break;
- default:
+ if (!handleEvent_secondMouseUp(event, x, y))
return false;
}
+ break;
-
- if (_screenOrientation != newOrientation) {
- _screenOrientation = newOrientation;
- if (_screenOrientation != kScreenOrientationPortrait)
- iPhone_initSurface(_screenHeight, _screenWidth, true);
- else
- iPhone_initSurface(_screenWidth, _screenHeight, false);
-
- dirtyFullScreen();
- updateScreen();
- }
+ case kInputOrientationChanged:
+ handleEvent_orientationChanged((int)xUnit);
+ return false;
break;
case kInputApplicationSuspended:
suspendLoop();
+ return false;
break;
- case kInputKeyPressed: {
- int keyPressed = (int)xUnit;
- int ascii = keyPressed;
- //printf("key: %i\n", keyPressed);
-
- // We remap some of the iPhone keyboard keys.
- // The first ten here are the row of symbols below the numeric keys.
- switch (keyPressed) {
- case 45:
- keyPressed = Common::KEYCODE_F1;
- ascii = Common::ASCII_F1;
- break;
- case 47:
- keyPressed = Common::KEYCODE_F2;
- ascii = Common::ASCII_F2;
- break;
- case 58:
- keyPressed = Common::KEYCODE_F3;
- ascii = Common::ASCII_F3;
- break;
- case 59:
- keyPressed = Common::KEYCODE_F4;
- ascii = Common::ASCII_F4;
- break;
- case 40:
- keyPressed = Common::KEYCODE_F5;
- ascii = Common::ASCII_F5;
- break;
- case 41:
- keyPressed = Common::KEYCODE_F6;
- ascii = Common::ASCII_F6;
- break;
- case 36:
- keyPressed = Common::KEYCODE_F7;
- ascii = Common::ASCII_F7;
- break;
- case 38:
- keyPressed = Common::KEYCODE_F8;
- ascii = Common::ASCII_F8;
- break;
- case 64:
- keyPressed = Common::KEYCODE_F9;
- ascii = Common::ASCII_F9;
- break;
- case 34:
- keyPressed = Common::KEYCODE_F10;
- ascii = Common::ASCII_F10;
- break;
- case 10:
- keyPressed = Common::KEYCODE_RETURN;
- ascii = Common::ASCII_RETURN;
- break;
- }
- event.type = Common::EVENT_KEYDOWN;
- _queuedInputEvent.type = Common::EVENT_KEYUP;
+ case kInputKeyPressed:
+ handleEvent_keyPressed(event, (int)xUnit);
+ break;
- event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
- _needEventRestPeriod = true;
+ case kInputSwipe:
+ if (!handleEvent_swipe(event, (int)xUnit))
+ return false;
break;
- }
- case kInputSwipe: {
- Common::KeyCode keycode = Common::KEYCODE_INVALID;
- switch (_screenOrientation) {
- case kScreenOrientationPortrait:
- switch ((UIViewSwipeDirection)xUnit) {
- case kUIViewSwipeUp:
- keycode = Common::KEYCODE_UP;
- break;
- case kUIViewSwipeDown:
- keycode = Common::KEYCODE_DOWN;
- break;
- case kUIViewSwipeLeft:
- keycode = Common::KEYCODE_LEFT;
- break;
- case kUIViewSwipeRight:
- keycode = Common::KEYCODE_RIGHT;
- break;
- default:
- return false;
- }
- break;
- case kScreenOrientationLandscape:
- switch ((UIViewSwipeDirection)xUnit) {
- case kUIViewSwipeUp:
- keycode = Common::KEYCODE_LEFT;
- break;
- case kUIViewSwipeDown:
- keycode = Common::KEYCODE_RIGHT;
- break;
- case kUIViewSwipeLeft:
- keycode = Common::KEYCODE_DOWN;
- break;
- case kUIViewSwipeRight:
- keycode = Common::KEYCODE_UP;
- break;
- default:
- return false;
- }
- break;
- case kScreenOrientationFlippedLandscape:
- switch ((UIViewSwipeDirection)xUnit) {
- case kUIViewSwipeUp:
- keycode = Common::KEYCODE_RIGHT;
- break;
- case kUIViewSwipeDown:
- keycode = Common::KEYCODE_LEFT;
- break;
- case kUIViewSwipeLeft:
- keycode = Common::KEYCODE_UP;
- break;
- case kUIViewSwipeRight:
- keycode = Common::KEYCODE_DOWN;
- break;
- default:
- return false;
- }
- break;
- }
+ default:
+ break;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+bool OSystem_IPHONE::handleEvent_mouseDown(Common::Event &event, int x, int y) {
+ printf("Mouse down at (%u, %u)\n", x, y);
+
+ // Workaround: kInputMouseSecondToggled isn't always sent when the
+ // secondary finger is lifted. Need to make sure we get out of that mode.
+ _secondaryTapped = false;
+
+ if (_touchpadModeEnabled) {
+ _lastPadX = x;
+ _lastPadY = y;
+ } else
+ warpMouse(x, y);
+
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ return true;
+ } else {
+ _lastMouseDown = getMillis();
+ }
+ return false;
+}
+
+bool OSystem_IPHONE::handleEvent_mouseUp(Common::Event &event, int x, int y) {
+ //printf("Mouse up at (%u, %u)\n", x, y);
+
+ if (_secondaryTapped) {
+ _secondaryTapped = false;
+ if (!handleEvent_secondMouseUp(event, x, y))
+ return false;
+ }
+ else if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ } else {
+ if (getMillis() - _lastMouseDown < 250) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+
+ _queuedInputEvent.type = Common::EVENT_LBUTTONUP;
+ _queuedInputEvent.mouse.x = _mouseX;
+ _queuedInputEvent.mouse.y = _mouseY;
+ _lastMouseTap = getMillis();
+ _needEventRestPeriod = true;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool OSystem_IPHONE::handleEvent_secondMouseDown(Common::Event &event, int x, int y) {
+ _lastSecondaryDown = getMillis();
+ _gestureStartX = x;
+ _gestureStartY = y;
+
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+
+ _queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
+ _queuedInputEvent.mouse.x = _mouseX;
+ _queuedInputEvent.mouse.y = _mouseY;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int y) {
+ int curTime = getMillis();
+
+ if (curTime - _lastSecondaryDown < 400 ) {
+ //printf("Right tap!\n");
+ if (curTime - _lastSecondaryTap < 400 && !_overlayVisible) {
+ //printf("Right escape!\n");
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
+ _needEventRestPeriod = true;
+ _lastSecondaryTap = 0;
+ } else if (!_mouseClickAndDragEnabled) {
+ //printf("Rightclick!\n");
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
+ _queuedInputEvent.mouse.x = _mouseX;
+ _queuedInputEvent.mouse.y = _mouseY;
+ _lastSecondaryTap = curTime;
+ _needEventRestPeriod = true;
+ } else {
+ //printf("Right nothing!\n");
+ return false;
+ }
+ }
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ }
+
+ return true;
+}
+
+bool OSystem_IPHONE::handleEvent_mouseDragged(Common::Event &event, int x, int y) {
+ if (_lastDragPosX == x && _lastDragPosY == y)
+ return false;
+
+ _lastDragPosX = x;
+ _lastDragPosY = y;
+
+ //printf("Mouse dragged at (%u, %u)\n", x, y);
+ if (_secondaryTapped) {
+ if (_gestureStartX == -1 || _gestureStartY == -1) {
+ return false;
+ }
+
+ int vecX = (x - _gestureStartX);
+ int vecY = (y - _gestureStartY);
+ int lengthSq = vecX * vecX + vecY * vecY;
+ //printf("Lengthsq: %u\n", lengthSq);
+
+ if (lengthSq > 15000) { // Long enough gesture to react upon.
+ _gestureStartX = -1;
+ _gestureStartY = -1;
+
+ float vecLength = sqrt(lengthSq);
+ float vecXNorm = vecX / vecLength;
+ float vecYNorm = vecY / vecLength;
+
+ //printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm);
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
+ if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) {
+ // Swipe down
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
+
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
_needEventRestPeriod = true;
- break;
- }
+ } else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
+ // Swipe up
+ _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
+ const char *dialogMsg;
+ if (_mouseClickAndDragEnabled)
+ dialogMsg = "Mouse-click-and-drag mode enabled.";
+ else
+ dialogMsg = "Mouse-click-and-drag mode disabled.";
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
- default:
- break;
+ } else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
+ // Swipe right
+ _touchpadModeEnabled = !_touchpadModeEnabled;
+ const char *dialogMsg;
+ if (_touchpadModeEnabled)
+ dialogMsg = "Touchpad mode enabled.";
+ else
+ dialogMsg = "Touchpad mode disabled.";
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
+
+ } else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
+ // Swipe left
+ return false;
+ } else
+ return false;
+ } else
+ return false;
+ } else {
+ int mouseNewPosX;
+ int mouseNewPosY;
+ if (_touchpadModeEnabled ) {
+ int deltaX = _lastPadX - x;
+ int deltaY = _lastPadY - y;
+ _lastPadX = x;
+ _lastPadY = y;
+
+ mouseNewPosX = (int)(_mouseX - deltaX / 0.5f);
+ mouseNewPosY = (int)(_mouseY - deltaY / 0.5f);
+
+ if (mouseNewPosX < 0)
+ mouseNewPosX = 0;
+ else if (mouseNewPosX > _screenWidth)
+ mouseNewPosX = _screenWidth;
+
+ if (mouseNewPosY < 0)
+ mouseNewPosY = 0;
+ else if (mouseNewPosY > _screenHeight)
+ mouseNewPosY = _screenHeight;
+
+ } else {
+ mouseNewPosX = x;
+ mouseNewPosY = y;
}
+
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse.x = mouseNewPosX;
+ event.mouse.y = mouseNewPosY;
+ warpMouse(mouseNewPosX, mouseNewPosY);
+ }
+
+ return true;
+}
- return true;
+void OSystem_IPHONE::handleEvent_orientationChanged(int orientation) {
+ //printf("Orientation: %i\n", orientation);
+
+ ScreenOrientation newOrientation;
+ switch (orientation) {
+ case 1:
+ newOrientation = kScreenOrientationPortrait;
+ break;
+ case 3:
+ newOrientation = kScreenOrientationLandscape;
+ break;
+ case 4:
+ newOrientation = kScreenOrientationFlippedLandscape;
+ break;
+ default:
+ return;
}
- return false;
+
+
+ if (_screenOrientation != newOrientation) {
+ _screenOrientation = newOrientation;
+ if (_screenOrientation != kScreenOrientationPortrait)
+ iPhone_initSurface(_screenHeight, _screenWidth, true);
+ else
+ iPhone_initSurface(_screenWidth, _screenHeight, false);
+
+ dirtyFullScreen();
+ updateScreen();
+ }
+}
+
+void OSystem_IPHONE::handleEvent_keyPressed(Common::Event &event, int keyPressed) {
+ int ascii = keyPressed;
+ //printf("key: %i\n", keyPressed);
+
+ // We remap some of the iPhone keyboard keys.
+ // The first ten here are the row of symbols below the numeric keys.
+ switch (keyPressed) {
+ case 45:
+ keyPressed = Common::KEYCODE_F1;
+ ascii = Common::ASCII_F1;
+ break;
+ case 47:
+ keyPressed = Common::KEYCODE_F2;
+ ascii = Common::ASCII_F2;
+ break;
+ case 58:
+ keyPressed = Common::KEYCODE_F3;
+ ascii = Common::ASCII_F3;
+ break;
+ case 59:
+ keyPressed = Common::KEYCODE_F4;
+ ascii = Common::ASCII_F4;
+ break;
+ case 40:
+ keyPressed = Common::KEYCODE_F5;
+ ascii = Common::ASCII_F5;
+ break;
+ case 41:
+ keyPressed = Common::KEYCODE_F6;
+ ascii = Common::ASCII_F6;
+ break;
+ case 36:
+ keyPressed = Common::KEYCODE_F7;
+ ascii = Common::ASCII_F7;
+ break;
+ case 38:
+ keyPressed = Common::KEYCODE_F8;
+ ascii = Common::ASCII_F8;
+ break;
+ case 64:
+ keyPressed = Common::KEYCODE_F9;
+ ascii = Common::ASCII_F9;
+ break;
+ case 34:
+ keyPressed = Common::KEYCODE_F10;
+ ascii = Common::ASCII_F10;
+ break;
+ case 10:
+ keyPressed = Common::KEYCODE_RETURN;
+ ascii = Common::ASCII_RETURN;
+ break;
+ }
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
+ _needEventRestPeriod = true;
+}
+
+bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction) {
+ Common::KeyCode keycode = Common::KEYCODE_INVALID;
+ switch (_screenOrientation) {
+ case kScreenOrientationPortrait:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_UP;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case kScreenOrientationLandscape:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_UP;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case kScreenOrientationFlippedLandscape:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_UP;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ _needEventRestPeriod = true;
+
+ return true;
}
void OSystem_IPHONE::suspendLoop() {
@@ -1020,16 +1125,17 @@ void OSystem_IPHONE::suspendLoop() {
float xUnit, yUnit;
uint32 startTime = getMillis();
- AudioQueueStop(s_AudioQueue.queue, true);
-
+ stopSoundsystem();
+
while (!done) {
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit))
if ((InputEvent)eventType == kInputApplicationResumed)
done = true;
usleep(100000);
}
+
+ startSoundsystem();
- AudioQueueStart(s_AudioQueue.queue, NULL);
_timeSuspended += getMillis() - startTime;
}
@@ -1107,7 +1213,10 @@ void OSystem_IPHONE::setupMixer() {
s_soundCallback = mixCallback;
s_soundParam = this;
+ startSoundsystem();
+}
+void OSystem_IPHONE::startSoundsystem() {
s_AudioQueue.dataFormat.mSampleRate = AUDIO_SAMPLE_RATE;
s_AudioQueue.dataFormat.mFormatID = kAudioFormatLinearPCM;
s_AudioQueue.dataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
@@ -1147,6 +1256,17 @@ void OSystem_IPHONE::setupMixer() {
_mixer->setReady(true);
}
+void OSystem_IPHONE::stopSoundsystem() {
+ AudioQueueStop(s_AudioQueue.queue, true);
+
+ for (int i = 0; i < AUDIO_BUFFERS; i++) {
+ AudioQueueFreeBuffer(s_AudioQueue.queue, s_AudioQueue.buffers[i]);
+ }
+
+ AudioQueueDispose(s_AudioQueue.queue, true);
+ _mixer->setReady(false);
+}
+
int OSystem_IPHONE::getOutputSampleRate() const {
return AUDIO_SAMPLE_RATE;
}
@@ -1196,29 +1316,6 @@ const char* OSystem_IPHONE::getConfigPath() {
return SCUMMVM_PREFS_PATH;
}
-void OSystem_IPHONE::migrateApp() {
- // Migrate to the new 1.1.3 directory structure, if needed.
-
- FilesystemNode file("/var/mobile");
- if (file.exists() && file.isDirectory()) {
- // We have 1.1.3 or above.
- s_is113OrHigher = true;
- file = FilesystemNode(SCUMMVM_ROOT_PATH);
- if (!file.exists()) {
- system("mkdir " SCUMMVM_ROOT_PATH);
- system("mkdir " SCUMMVM_SAVE_PATH);
-
- // Copy over the prefs file
- system("cp " SCUMMVM_OLD_PREFS_PATH " " SCUMMVM_PREFS_PATH);
-
- file = FilesystemNode(SCUMMVM_OLD_SAVE_PATH);
- // Copy over old savegames to the new directory.
- if (file.exists() && file.isDirectory())
- system("cp " SCUMMVM_OLD_SAVE_PATH "/* " SCUMMVM_SAVE_PATH "/");
- }
- }
-}
-
void iphone_main(int argc, char *argv[]) {
//OSystem_IPHONE::migrateApp();
@@ -1239,6 +1336,8 @@ void iphone_main(int argc, char *argv[]) {
system("mkdir " SCUMMVM_ROOT_PATH);
system("mkdir " SCUMMVM_SAVE_PATH);
+ chdir("/var/mobile/");
+
g_system = OSystem_IPHONE_create();
assert(g_system);
diff --git a/backends/platform/iphone/osys_iphone.h b/backends/platform/iphone/osys_iphone.h
index c058686c8c..a9a3ddad65 100644
--- a/backends/platform/iphone/osys_iphone.h
+++ b/backends/platform/iphone/osys_iphone.h
@@ -35,14 +35,12 @@
#include <AudioToolbox/AudioQueue.h>
#define AUDIO_BUFFERS 3
-#define WAVE_BUFFER_SIZE 8192
+#define WAVE_BUFFER_SIZE 2048
#define AUDIO_SAMPLE_RATE 44100
#define SCUMMVM_ROOT_PATH "/var/mobile/Library/ScummVM"
#define SCUMMVM_SAVE_PATH SCUMMVM_ROOT_PATH "/Savegames"
-#define SCUMMVM_OLD_SAVE_PATH "/var/root/.scummvm"
#define SCUMMVM_PREFS_PATH SCUMMVM_ROOT_PATH "/Preferences"
-#define SCUMMVM_OLD_PREFS_PATH "/var/root/.scummvmrc"
typedef void (*SoundProc)(void *param, byte *buf, int len);
typedef int (*TimerProc)(int interval);
@@ -61,7 +59,6 @@ protected:
static AQCallbackStruct s_AudioQueue;
static SoundProc s_soundCallback;
static void *s_soundParam;
- static bool s_is113OrHigher;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
@@ -97,6 +94,11 @@ protected:
long _lastSecondaryTap;
int _gestureStartX, _gestureStartY;
bool _mouseClickAndDragEnabled;
+ bool _touchpadModeEnabled;
+ int _lastPadX;
+ int _lastPadY;
+ int _lastDragPosX;
+ int _lastDragPosY;
int _timerCallbackNext;
int _timerCallbackTimer;
@@ -106,6 +108,8 @@ protected:
ScreenOrientation _screenOrientation;
bool _fullScreenIsDirty;
+ FilesystemFactory *_fsFactory;
+
public:
OSystem_IPHONE();
@@ -161,7 +165,7 @@ public:
virtual void quit();
- FilesystemFactory *getFilesystemFactory() { return &POSIXFilesystemFactory::instance(); }
+ FilesystemFactory *getFilesystemFactory() { return _fsFactory; }
virtual void getTimeAndDate(struct tm &t) const;
virtual void setWindowCaption(const char *caption);
@@ -170,7 +174,9 @@ public:
virtual Audio::Mixer *getMixer();
virtual Common::TimerManager *getTimerManager();
- static void migrateApp();
+ void startSoundsystem();
+ void stopSoundsystem();
+
static const char* getConfigPath();
protected:
@@ -182,6 +188,18 @@ protected:
void suspendLoop();
static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB);
static int timerHandler(int t);
+
+ bool handleEvent_swipe(Common::Event &event, int direction);
+ void handleEvent_keyPressed(Common::Event &event, int keyPressed);
+ void handleEvent_orientationChanged(int orientation);
+
+ bool handleEvent_mouseDown(Common::Event &event, int x, int y);
+ bool handleEvent_mouseUp(Common::Event &event, int x, int y);
+
+ bool handleEvent_secondMouseDown(Common::Event &event, int x, int y);
+ bool handleEvent_secondMouseUp(Common::Event &event, int x, int y);
+
+ bool handleEvent_mouseDragged(Common::Event &event, int x, int y);
};
#endif
diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp
index 463e9d7b2d..610f1d3a42 100644
--- a/backends/platform/null/null.cpp
+++ b/backends/platform/null/null.cpp
@@ -50,13 +50,12 @@
#include "backends/fs/windows/windows-fs-factory.h"
#endif
-
-
class OSystem_NULL : public OSystem {
protected:
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
Common::TimerManager *_timer;
+ FilesystemFactory *_fsFactory;
timeval _startTime;
public:
@@ -133,12 +132,23 @@ OSystem_NULL::OSystem_NULL() {
_savefile = 0;
_mixer = 0;
_timer = 0;
+
+ #if defined(__amigaos4__)
+ _fsFactory = new AmigaOSFilesystemFactory();
+ #elif defined(UNIX)
+ _fsFactory = new POSIXFilesystemFactory();
+ #elif defined(WIN32)
+ _fsFactory = new WindowsFilesystemFactory();
+ #else
+ #error Unknown and unsupported FS backend
+ #endif
}
OSystem_NULL::~OSystem_NULL() {
delete _savefile;
delete _mixer;
delete _timer;
+ delete _fsFactory;
}
void OSystem_NULL::initBackend() {
@@ -194,11 +204,11 @@ void OSystem_NULL::initSize(uint width, uint height) {
}
int16 OSystem_NULL::getHeight() {
- return 320;
+ return 200;
}
int16 OSystem_NULL::getWidth() {
- return 200;
+ return 320;
}
void OSystem_NULL::setPalette(const byte *colors, uint start, uint num) {
@@ -327,18 +337,9 @@ void OSystem_NULL::getTimeAndDate(struct tm &t) const {
}
FilesystemFactory *OSystem_NULL::getFilesystemFactory() {
- #if defined(__amigaos4__)
- return &AmigaOSFilesystemFactory::instance();
- #elif defined(UNIX)
- return &POSIXFilesystemFactory::instance();
- #elif defined(WIN32)
- return &WindowsFilesystemFactory::instance();
- #else
- #error Unknown and unsupported backend in OSystem_NULL::getFilesystemFactory
- #endif
+ return _fsFactory;
}
-
OSystem *OSystem_NULL_create() {
return new OSystem_NULL();
}
diff --git a/backends/platform/ps2/rawsavefile.cpp b/backends/platform/ps2/rawsavefile.cpp
index 03270ea9ce..aa3cc57fe7 100644
--- a/backends/platform/ps2/rawsavefile.cpp
+++ b/backends/platform/ps2/rawsavefile.cpp
@@ -31,6 +31,7 @@ RawReadFile::RawReadFile(McAccess *mcAccess) {
_size = -1;
_pos = 0;
_buf = NULL;
+ _eof = false;
}
RawReadFile::~RawReadFile(void) {
@@ -79,12 +80,16 @@ int RawReadFile::bufSeek(int ofs, int whence) {
_pos = 0;
else if (_pos > _size)
_pos = _size;
+
+ _eof = false;
return _pos;
}
int RawReadFile::bufRead(void *dest, int size) {
- if (_pos + size > _size)
+ if (_pos + size > _size) {
size = _size - _pos;
+ _eof = true;
+ }
memcpy(dest, _buf + _pos, size);
_pos += size;
return size;
@@ -94,7 +99,13 @@ int RawReadFile::bufSize(void) const {
return _size;
}
+bool RawReadFile::bufEof(void) const {
+ return _eof;
+}
+void RawReadFile::bufClearErr(void) const {
+ _eof = false;
+}
RawWriteFile::RawWriteFile(McAccess *mcAccess) {
_mcAccess = mcAccess;
diff --git a/backends/platform/ps2/rawsavefile.h b/backends/platform/ps2/rawsavefile.h
index b638d106ab..8e0dba4ab9 100644
--- a/backends/platform/ps2/rawsavefile.h
+++ b/backends/platform/ps2/rawsavefile.h
@@ -40,11 +40,14 @@ public:
int bufTell(void) const;
int bufSeek(int ofs, int whence);
int bufSize(void) const;
+ bool bufEof(void) const;
+ void bufClearErr(void);
protected:
McAccess *_mcAccess;
int _size;
uint8 *_buf;
int _pos;
+ bool _eof;
};
class RawWriteFile {
diff --git a/backends/platform/ps2/savefile.cpp b/backends/platform/ps2/savefile.cpp
index 5ee724cd3f..bfcaf0f57f 100644
--- a/backends/platform/ps2/savefile.cpp
+++ b/backends/platform/ps2/savefile.cpp
@@ -71,7 +71,7 @@ uint32 AutoSaveFile::write(const void *ptr, uint32 size) {
UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mcAccess) : RawReadFile(mcAccess) {
_screen = screen;
- _ioFailed = true;
+ _err = true;
if (bufOpen(filename)) {
if ((_size > 8) && (*(uint32 *)_buf == UCL_MAGIC)) {
@@ -82,13 +82,13 @@ UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess
free(_buf);
_buf = decBuf;
_size = resSize;
- _ioFailed = false;
+ _err = false;
_pos = 0;
} else
free(decBuf);
}
}
- if (_ioFailed) {
+ if (_err) {
if (_buf)
free(_buf);
_buf = NULL;
@@ -100,36 +100,39 @@ UclInSaveFile::~UclInSaveFile(void) {
_screen->wantAnim(false);
}
-bool UclInSaveFile::ioFailed(void) const {
- return _ioFailed;
+bool UclInSaveFile::err(void) const {
+ return _err;
}
-void UclInSaveFile::clearIOFailed(void) {
- _ioFailed = false;
+void UclInSaveFile::clearErr(void) {
+ _err = false;
+ bufClearErr();
}
bool UclInSaveFile::eos(void) const {
- return bufTell() == bufSize();
+ return bufEof();
}
-uint32 UclInSaveFile::pos(void) const {
+int32 UclInSaveFile::pos(void) const {
return bufTell();
}
-uint32 UclInSaveFile::size(void) const {
+int32 UclInSaveFile::size(void) const {
return bufSize();
}
-void UclInSaveFile::seek(int pos, int whence) {
+bool UclInSaveFile::seek(int pos, int whence) {
bufSeek(pos, whence);
+ return true;
}
uint32 UclInSaveFile::read(void *ptr, uint32 size) {
return (uint32)bufRead(ptr, (int)size);
}
-void UclInSaveFile::skip(uint32 offset) {
+bool UclInSaveFile::skip(uint32 offset) {
bufSeek(offset, SEEK_CUR);
+ return true;
}
UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) : RawWriteFile(mc) {
@@ -137,7 +140,7 @@ UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dSc
_system = system;
strcpy(_fileName, filename);
- _ioFailed = !bufOpen(filename);
+ _err = !bufOpen(filename);
_wasFlushed = false;
}
@@ -146,7 +149,7 @@ UclOutSaveFile::~UclOutSaveFile(void) {
if (_pos != 0) {
printf("Engine didn't call SaveFile::flush()\n");
flush();
- if (ioFailed()) {
+ if (err()) {
// unable to save to memory card and it's too late to return an error code to the engine
_system->msgPrintf(5000, "!WARNING!\nCan't write to memory card.\nGame was NOT saved.");
printf("~UclOutSaveFile: Flush failed!\n");
@@ -160,20 +163,20 @@ uint32 UclOutSaveFile::write(const void *ptr, uint32 size) {
return size;
}
-bool UclOutSaveFile::ioFailed(void) const {
- return _ioFailed;
+bool UclOutSaveFile::err(void) const {
+ return _err;
}
-void UclOutSaveFile::clearIOFailed(void) {
- _ioFailed = false;
+void UclOutSaveFile::clearErr(void) {
+ _err = false;
}
-void UclOutSaveFile::flush(void) {
+bool UclOutSaveFile::flush(void) {
if (_pos != 0) {
if (_wasFlushed) {
printf("Multiple calls to UclOutSaveFile::flush!\n");
- _ioFailed = true;
- return;
+ _err = true;
+ return false;
}
uint32 compSize = _pos * 2;
uint8 *compBuf = (uint8*)memalign(64, compSize + 8);
@@ -188,11 +191,12 @@ void UclOutSaveFile::flush(void) {
_pos = compSize + 8;
if (!bufFlush()) {
printf("UclOutSaveFile::flush failed!\n");
- _ioFailed = true;
+ _err = true;
removeFile();
}
_wasFlushed = true;
}
+ return true;
}
/* ----------------------------------------- Glue Classes for POSIX Memory Card Access ----------------------------------------- */
@@ -216,11 +220,11 @@ uint32 Ps2McReadFile::write(const void *src, uint32 len) {
return 0;
}
-uint32 Ps2McReadFile::tell(void) {
+int32 Ps2McReadFile::tell(void) {
return bufTell();
}
-uint32 Ps2McReadFile::size(void) {
+int32 Ps2McReadFile::size(void) {
return bufSize();
}
@@ -253,11 +257,11 @@ uint32 Ps2McWriteFile::write(const void *src, uint32 len) {
return len;
}
-uint32 Ps2McWriteFile::tell(void) {
+int32 Ps2McWriteFile::tell(void) {
return bufTell();
}
-uint32 Ps2McWriteFile::size(void) {
+int32 Ps2McWriteFile::size(void) {
return bufTell();
}
@@ -267,6 +271,3 @@ int Ps2McWriteFile::seek(int32 offset, int origin) {
return 0;
}
-bool Ps2McWriteFile::eof(void) {
- return true;
-}
diff --git a/backends/platform/ps2/savefile.h b/backends/platform/ps2/savefile.h
index 4832b8c3fe..0c0cf922f4 100644
--- a/backends/platform/ps2/savefile.h
+++ b/backends/platform/ps2/savefile.h
@@ -41,14 +41,14 @@ public:
UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc);
virtual ~UclOutSaveFile(void);
virtual uint32 write(const void *ptr, uint32 size);
- virtual void flush(void);
- virtual bool ioFailed(void) const;
- virtual void clearIOFailed(void);
+ virtual bool flush(void);
+ virtual bool err(void) const;
+ virtual void clearErr(void);
private:
OSystem_PS2 *_system;
Gs2dScreen *_screen;
- bool _ioFailed, _wasFlushed;
+ bool _err, _wasFlushed;
char _fileName[128];
};
@@ -58,16 +58,16 @@ public:
virtual ~UclInSaveFile(void);
virtual bool eos(void) const;
virtual uint32 read(void *ptr, uint32 size);
- virtual bool ioFailed(void) const;
- virtual void clearIOFailed(void);
- virtual void skip(uint32 offset);
+ virtual bool err(void) const;
+ virtual void clearErr(void);
+ virtual bool skip(uint32 offset);
- virtual uint32 pos(void) const;
- virtual uint32 size(void) const;
- virtual void seek(int pos, int whence = SEEK_SET);
+ virtual int32 pos(void) const;
+ virtual int32 size(void) const;
+ virtual bool seek(int pos, int whence = SEEK_SET);
private:
Gs2dScreen *_screen;
- bool _ioFailed;
+ bool _err;
};
class AutoSaveFile : public Common::OutSaveFile {
@@ -75,9 +75,9 @@ public:
AutoSaveFile(Ps2SaveFileManager *saveMan, const char *filename);
~AutoSaveFile(void);
virtual uint32 write(const void *ptr, uint32 size);
- virtual void flush(void) {}
- virtual bool ioFailed(void) { return false; };
- virtual void clearIOFailed(void) {}
+ virtual bool flush(void) {}
+ virtual bool err(void) const { return false; }
+ virtual void clearErr(void) {}
private:
Ps2SaveFileManager *_saveMan;
char _fileName[256];
@@ -95,8 +95,8 @@ public:
virtual bool open(const char *name);
virtual uint32 read(void *dest, uint32 len);
virtual uint32 write(const void *src, uint32 len);
- virtual uint32 tell(void);
- virtual uint32 size(void);
+ virtual int32 tell(void);
+ virtual int32 size(void);
virtual int seek(int32 offset, int origin);
virtual bool eof(void);
};
@@ -108,10 +108,9 @@ public:
virtual bool open(const char *name);
virtual uint32 read(void *dest, uint32 len);
virtual uint32 write(const void *src, uint32 len);
- virtual uint32 tell(void);
- virtual uint32 size(void);
+ virtual int32 tell(void);
+ virtual int32 size(void);
virtual int seek(int32 offset, int origin);
- virtual bool eof(void);
};
#endif // __PS2_SAVEFILE__
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index 6e9b5980d4..69be0abcb2 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -98,7 +98,20 @@ OSystem_PSP::~OSystem_PSP() {
void OSystem_PSP::initBackend() {
- _savefile = new DefaultSaveFileManager();
+ _savefile = new DefaultSaveFileManager("ms0:/scummvm_savegames");
+
+ const char *savePath = _savefile->getSavePath().c_str();
+
+ //check if the save directory exists
+ SceUID fd = sceIoDopen(savePath);
+ if (fd < 0) {
+ //No? then let's create it.
+ sceIoMkdir(savePath, 0777);
+ } else {
+ //it exists, so close it again.
+ sceIoDclose(fd);
+ }
+
_timer = new DefaultTimerManager();
setTimerCallback(&timer_handler, 10);
diff --git a/backends/platform/psp/osys_psp_gu.cpp b/backends/platform/psp/osys_psp_gu.cpp
index 7e36fe6db0..1aa3bcd438 100644
--- a/backends/platform/psp/osys_psp_gu.cpp
+++ b/backends/platform/psp/osys_psp_gu.cpp
@@ -94,19 +94,23 @@ OSystem_PSP_GU::OSystem_PSP_GU() {
//decompress keyboard data
uLongf kbdSize = KBD_DATA_SIZE;
keyboard_letters = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_letters, &kbdSize, (const Bytef *)keyboard_letters_compressed, size_keyboard_letters_compressed));
-
+ if (!uncompress((Bytef *)keyboard_letters, &kbdSize, (const Bytef *)keyboard_letters_compressed, size_keyboard_letters_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_letters failed");
+
kbdSize = KBD_DATA_SIZE;
keyboard_letters_shift = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_letters_shift, &kbdSize, (const Bytef *)keyboard_letters_shift_compressed, size_keyboard_letters_shift_compressed));
+ if (!uncompress((Bytef *)keyboard_letters_shift, &kbdSize, (const Bytef *)keyboard_letters_shift_compressed, size_keyboard_letters_shift_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_letters_shift failed");
kbdSize = KBD_DATA_SIZE;
keyboard_symbols = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_symbols, &kbdSize, (const Bytef *)keyboard_symbols_compressed, size_keyboard_symbols_compressed));
+ if (!uncompress((Bytef *)keyboard_symbols, &kbdSize, (const Bytef *)keyboard_symbols_compressed, size_keyboard_symbols_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_symbols failed");
kbdSize = KBD_DATA_SIZE;
keyboard_symbols_shift = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_symbols_shift, &kbdSize, (const Bytef *)keyboard_symbols_shift_compressed, size_keyboard_symbols_shift_compressed));
+ if (!uncompress((Bytef *)keyboard_symbols_shift, &kbdSize, (const Bytef *)keyboard_symbols_shift_compressed, size_keyboard_symbols_shift_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_symbols_shift failed");
_keyboardVisible = false;
_clut = (unsigned short*)(((unsigned int)clut256)|0x40000000);
diff --git a/backends/platform/psp/portdefs.h b/backends/platform/psp/portdefs.h
index af772230d7..1708a70c74 100644
--- a/backends/platform/psp/portdefs.h
+++ b/backends/platform/psp/portdefs.h
@@ -43,7 +43,6 @@
#include "trace.h"
-#define SCUMMVM_SAVEPATH "ms0:/scummvm_savegames"
#define BREAKPOINT asm("break\n")
diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp
index d2ed59efbe..94ef63488d 100644
--- a/backends/platform/psp/psp_main.cpp
+++ b/backends/platform/psp/psp_main.cpp
@@ -122,16 +122,6 @@ int main(void)
{
SetupCallbacks();
- //check if the save directory exists
- SceUID fd = sceIoDopen(SCUMMVM_SAVEPATH);
- if (fd < 0) {
- //No? then let's create it.
- sceIoMkdir(SCUMMVM_SAVEPATH, 0777);
- } else {
- //it exists, so close it again.
- sceIoDclose(fd);
- }
-
static char *argv[] = { "scummvm", NULL };
static int argc = sizeof(argv)/sizeof(char *)-1;
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 5c3b87309d..9a6f294a55 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -32,9 +32,9 @@
#endif
#include "backends/platform/sdl/sdl.h"
+#include "common/archive.h"
#include "common/config-manager.h"
#include "common/events.h"
-#include "common/file.h"
#include "common/util.h"
#include "backends/saves/default/default-saves.h"
@@ -72,6 +72,9 @@
#define DEFAULT_CONFIG_FILE "scummvm.ini"
#endif
+#if defined(MACOSX) || defined(IPHONE)
+#include "CoreFoundation/CoreFoundation.h"
+#endif
static Uint32 timer_handler(Uint32 interval, void *param) {
@@ -196,6 +199,7 @@ OSystem_SDL::OSystem_SDL()
_soundMutex(0), _soundCond(0), _soundThread(0),
_soundThreadIsRunning(false), _soundThreadShouldQuit(false),
#endif
+ _fsFactory(0),
_savefile(0),
_mixer(0),
_timer(0),
@@ -213,6 +217,19 @@ OSystem_SDL::OSystem_SDL()
memset(&_mouseCurState, 0, sizeof(_mouseCurState));
_inited = false;
+
+
+ #if defined(__amigaos4__)
+ _fsFactory = new AmigaOSFilesystemFactory();
+ #elif defined(UNIX)
+ _fsFactory = new POSIXFilesystemFactory();
+ #elif defined(WIN32)
+ _fsFactory = new WindowsFilesystemFactory();
+ #elif defined(__SYMBIAN32__)
+ // Do nothing since its handled by the Symbian SDL inheritance
+ #else
+ #error Unknown and unsupported FS backend
+ #endif
}
OSystem_SDL::~OSystem_SDL() {
@@ -254,19 +271,42 @@ Common::SaveFileManager *OSystem_SDL::getSavefileManager() {
}
FilesystemFactory *OSystem_SDL::getFilesystemFactory() {
- #if defined(__amigaos4__)
- return &AmigaOSFilesystemFactory::instance();
- #elif defined(UNIX)
- return &POSIXFilesystemFactory::instance();
- #elif defined(WIN32)
- return &WindowsFilesystemFactory::instance();
- #elif defined(__SYMBIAN32__)
- // Do nothing since its handled by the Symbian SDL inheritance
- #else
- #error Unknown and unsupported backend in OSystem_SDL::getFilesystemFactory
- #endif
+ assert(_fsFactory);
+ return _fsFactory;
+}
+
+void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, uint priority) {
+
+#ifdef DATA_PATH
+ // Add the global DATA_PATH to the directory search list
+ // FIXME: We use depth = 4 for now, to match the old code. May want to change that
+ Common::FilesystemNode dataNode(DATA_PATH);
+ if (dataNode.exists() && dataNode.isDirectory()) {
+ Common::ArchivePtr dataArchive(new Common::FSDirectory(dataNode, 4));
+ s.add(DATA_PATH, dataArchive, priority);
+ }
+#endif
+
+#if defined(MACOSX) || defined(IPHONE)
+ // Get URL of the Resource directory of the .app bundle
+ CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+ if (fileUrl) {
+ // Try to convert the URL to an absolute path
+ UInt8 buf[MAXPATHLEN];
+ if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) {
+ // Success: Add it to the search path
+ Common::String bundlePath((const char *)buf);
+ Common::ArchivePtr bundleArchive(new Common::FSDirectory(bundlePath));
+ s.add("__OSX_BUNDLE__", bundleArchive, priority);
+ }
+ CFRelease(fileUrl);
+ }
+
+#endif
+
}
+
static Common::String getDefaultConfigFileName() {
char configFile[MAXPATHLEN];
#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
@@ -292,20 +332,19 @@ static Common::String getDefaultConfigFileName() {
CreateDirectory(configFile, NULL);
strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
- if (fopen(configFile, "r") == NULL) {
+ FILE *tmp = NULL;
+ if ((tmp = fopen(configFile, "r")) == NULL) {
// Check windows directory
char oldConfigFile[MAXPATHLEN];
GetWindowsDirectory(oldConfigFile, MAXPATHLEN);
strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE);
- if (fopen(oldConfigFile, "r")) {
- printf("The default location of the config file (scummvm.ini) in ScummVM has changed,\n");
- printf("under Windows NT4/2000/XP/Vista. You may want to consider moving your config\n");
- printf("file from the old default location:\n");
- printf("%s\n", oldConfigFile);
- printf("to the new default location:\n");
- printf("%s\n\n", configFile);
+ if ((tmp = fopen(oldConfigFile, "r"))) {
strcpy(configFile, oldConfigFile);
+
+ fclose(tmp);
}
+ } else {
+ fclose(tmp);
}
} else {
// Check windows directory
@@ -334,23 +373,13 @@ static Common::String getDefaultConfigFileName() {
}
Common::SeekableReadStream *OSystem_SDL::openConfigFileForReading() {
- Common::File *confFile = new Common::File();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForReading();
}
Common::WriteStream *OSystem_SDL::openConfigFileForWriting() {
- Common::DumpFile *confFile = new Common::DumpFile();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForWriting();
}
void OSystem_SDL::setWindowCaption(const char *caption) {
@@ -435,15 +464,21 @@ void OSystem_SDL::quit() {
}
void OSystem_SDL::setupIcon() {
- int w, h, ncols, nbytes, i;
- unsigned int rgba[256], icon[32 * 32];
- unsigned char mask[32][4];
+ int x, y, w, h, ncols, nbytes, i;
+ unsigned int rgba[256];
+ unsigned int *icon;
sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes);
- if ((w != 32) || (h != 32) || (ncols > 255) || (nbytes > 1)) {
- warning("Could not load the icon (%d %d %d %d)", w, h, ncols, nbytes);
+ if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) {
+ warning("Could not load the built-in icon (%d %d %d %d)", w, h, ncols, nbytes);
+ return;
+ }
+ icon = (unsigned int*)malloc(w*h*sizeof(unsigned int));
+ if (!icon) {
+ warning("Could not allocate temp storage for the built-in icon");
return;
}
+
for (i = 0; i < ncols; i++) {
unsigned char code;
char color[32];
@@ -457,26 +492,27 @@ void OSystem_SDL::setupIcon() {
sscanf(color + 1, "%06x", &col);
col |= 0xFF000000;
} else {
- warning("Could not load the icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
+ warning("Could not load the built-in icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
+ free(icon);
return;
}
rgba[code] = col;
}
- memset(mask, 0, sizeof(mask));
- for (h = 0; h < 32; h++) {
- const char *line = scummvm_icon[1 + ncols + h];
- for (w = 0; w < 32; w++) {
- icon[w + 32 * h] = rgba[(int)line[w]];
- if (rgba[(int)line[w]] & 0xFF000000) {
- mask[h][w >> 3] |= 1 << (7 - (w & 0x07));
- }
+ for (y = 0; y < h; y++) {
+ const char *line = scummvm_icon[1 + ncols + y];
+ for (x = 0; x < w; x++) {
+ icon[x + w * y] = rgba[(int)line[x]];
}
}
- SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
- SDL_WM_SetIcon(sdl_surf, (unsigned char *) mask);
+ SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, w, h, 32, w * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
+ if (!sdl_surf) {
+ warning("SDL_CreateRGBSurfaceFrom(icon) failed");
+ }
+ SDL_WM_SetIcon(sdl_surf, NULL);
SDL_FreeSurface(sdl_surf);
+ free(icon);
}
OSystem::MutexRef OSystem_SDL::createMutex(void) {
@@ -515,7 +551,7 @@ void OSystem_SDL::mixerProducerThread() {
// Generate samples and put them into the next buffer
nextSoundBuffer = _activeSoundBuf ^ 1;
_mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
-
+
// Swap buffers
_activeSoundBuf = nextSoundBuffer;
}
@@ -559,7 +595,7 @@ void OSystem_SDL::deinitThreadedMixer() {
SDL_CondBroadcast(_soundCond);
SDL_WaitThread(_soundThread, NULL);
- // Kill the mutex & cond variables.
+ // Kill the mutex & cond variables.
// Attention: AT this point, the mixer callback must not be running
// anymore, else we will crash!
SDL_DestroyMutex(_soundMutex);
@@ -582,10 +618,10 @@ void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) {
// Lock mutex, to ensure our data is not overwritten by the producer thread
SDL_LockMutex(this_->_soundMutex);
-
+
// Copy data from the current sound buffer
memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
-
+
// Unlock mutex and wake up the produced thread
SDL_UnlockMutex(this_->_soundMutex);
SDL_CondSignal(this_->_soundCond);
@@ -645,7 +681,7 @@ void OSystem_SDL::setupMixer() {
// even if it didn't. Probably only happens for "weird" rates, though.
_samplesPerSec = obtained.freq;
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
-
+
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
_mixer->setReady(true);
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 1c1381ec5c..1cc0acbc29 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -209,6 +209,7 @@ public:
virtual Common::SaveFileManager *getSavefileManager();
virtual FilesystemFactory *getFilesystemFactory();
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s, uint priority = 0);
virtual Common::SeekableReadStream *openConfigFileForReading();
virtual Common::WriteStream *openConfigFileForWriting();
@@ -400,14 +401,13 @@ protected:
void deinitThreadedMixer();
#endif
-
+ FilesystemFactory *_fsFactory;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
SDL_TimerID _timerID;
Common::TimerManager *_timer;
-
protected:
void addDirtyRgnAuto(const byte *buf);
void makeChecksums(const byte *buf);
diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl
index b576bb3993..d7b5642f1c 100644
--- a/backends/platform/symbian/AdaptAllMMPs.pl
+++ b/backends/platform/symbian/AdaptAllMMPs.pl
@@ -27,7 +27,7 @@ chdir("../../../");
"mmp/scummvm_sword1.mmp",
"mmp/scummvm_sword2.mmp",
"mmp/scummvm_touche.mmp",
-
+ "mmp/scummvm_tinsel.mmp",
# Target Platform Project Files
"S60/ScummVM_S60.mmp",
@@ -83,6 +83,9 @@ my @excludes_graphics = (
"iff.cpp"
);
+my @excludes_gui = (
+);
+
# the USE_ARM_* defines not parsed correctly, exclude manually:
my @excludes_scumm = (
".*ARM.*", # the *ARM.s files are added in .mpp files based on WINS/ARM build!
@@ -95,7 +98,7 @@ my @excludes_scumm = (
#arseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray])
ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, these never change anyways...
ParseModule("_base", "common", \@section_empty);
-ParseModule("_base", "gui", \@section_empty);
+ParseModule("_base", "gui", \@section_empty, \@excludes_gui);
ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics);
ParseModule("_base", "sound", \@section_empty, \@excludes_snd);
@@ -103,22 +106,23 @@ chdir("engines/");
ParseModule("_scumm", "scumm", \@sections_scumm, \@excludes_scumm );
ParseModule("_queen", "queen", \@section_empty);
ParseModule("_agos", "agos", \@section_empty);
-ParseModule("_sky", "sky", \@section_empty);
-ParseModule("_gob", "gob", \@section_empty);
+ParseModule("_sky", "sky", \@section_empty);
+ParseModule("_gob", "gob", \@section_empty);
ParseModule("_saga", "saga", \@section_empty);
ParseModule("_kyra", "kyra", \@section_empty);
ParseModule("_sword1", "sword1", \@section_empty);
ParseModule("_sword2", "sword2", \@section_empty);
ParseModule("_lure", "lure", \@section_empty);
ParseModule("_cine", "cine", \@section_empty);
-ParseModule("_agi", "agi", \@section_empty);
+ParseModule("_agi", "agi", \@section_empty);
ParseModule("_touche", "touche", \@section_empty);
ParseModule("_parallaction","parallaction",\@section_empty);
ParseModule("_cruise", "cruise", \@section_empty);
ParseModule("_drascula","drascula", \@section_empty);
ParseModule("_igor", "igor", \@section_empty);
ParseModule("_made", "made", \@section_empty);
-ParseModule("_m4", "m4", \@section_empty);
+ParseModule("_m4", "m4", \@section_empty);
+ParseModule("_tinsel", "tinsel", \@section_empty);
print "
=======================================================================================
Done. Enjoy :P
diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
index 94edbf4fcf..ba8afe5084 100644
--- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
+++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
@@ -443,6 +443,10 @@ my $header = "
PrintMessage("Cleaning for $Target") if (!$ReallyQuiet);
system("bldmake bldfiles > NUL 2> NUL");
PrintErrorMessage("'bldmake bldfiles' exited with value " . ($? >> 8)) if ($? >> 8);
+
+ system("abld MAKEFILE $TargetName > NUL 2> NUL");
+ PrintErrorMessage("'abld MAKEFILE $TargetName' exited with value " . ($? >> 8)) if ($? >> 8);
+
system("abld CLEAN $TargetName UREL > NUL 2> NUL");
PrintErrorMessage("'abld CLEAN $TargetName urel' exited with value " . ($? >> 8)) if ($? >> 8);
# remove file so we are sure that after .lib generation we have a fresh copy!
@@ -455,10 +459,10 @@ my $header = "
my $OldSize = (-s $build_log_err);
$Redirection = ($RedirectSTDERR ? "2>> $build_log_err" : "");
- system("abld BUILD $TargetName UREL $Redirection >> $build_log_out");
+ system("abld TARGET $TargetName UREL $Redirection >> $build_log_out");
$OK = 0 if ($? >> 8);
# print " STDERR: ".((-s $build_log_err)-$OldSize)." bytes output written to $build_log_err\n+--------------------------------------------------------------------------------------\n" if ($OldSize != (-s $build_log_err));
- PrintErrorMessage("'abld BUILD $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8);
+ PrintErrorMessage("'abld TARGET $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8);
return 0 if (!$OK); # ABLD always returns ok :( grr
PrintMessage("Done.") if (!$ReallyQuiet);
@@ -475,7 +479,7 @@ my $header = "
}
else
{
- PrintErrorMessage("'abld BUILD $TargetName UREL' apparently failed.");
+ PrintErrorMessage("'abld TARGET $TargetName UREL' apparently failed.");
if ($HaltOnError)
{
PrintErrorMessage("Halting on error as requested!");
diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
index 12e5f8f0c4..8ba743674d 100644
--- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
+++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
@@ -3,14 +3,15 @@
@WorkingEngines = qw(
scumm agos sky queen gob saga drascula
- kyra lure agi touche parallaction
+ kyra lure agi touche parallaction cine
+ cruise igor made m4 tinsel sword1 sword2
);
+
@TestingEngines = qw(
- cruise igor made m4 cine
+
);
- @BrokenEngines = qw(
- sword1
- sword2
+
+ @BrokenEngines = qw(
);
@EnablableEngines = (@WorkingEngines, @TestingEngines);
@@ -29,20 +30,7 @@
# these are normally enabled for each variation
#$DefaultFeatures = qw(zlib,mad);
- $DefaultFeatures = qw(zlib,mad,tremor);
-
-
- # you can use these below for speed & clarity or override with custom settings
- $DefaultTopMacros = "
- MACRO USE_ZLIB // LIB:zlib.lib
- MACRO USE_MAD // LIB:libmad.lib
- MACRO USE_TREMOR // LIB:libtremor.lib
- ";
-
- $DefaultBottomMacros = "
- MACRO DISABLE_SWORD1 // LIB:scummvm_sword1.lib
- MACRO DISABLE_SWORD2 // LIB:scummvm_sword2.lib
- ";
+ $DefaultFeatures = qw(zlib,mad,tremor);
##################################################################################################################
##
@@ -186,6 +174,44 @@
# now you can add $VariationSets only built on this PC below this line :)
}
+ elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-LAPE") #################################################################
+ {
+ $Producer = "AnotherGuest";
+ $RedirectSTDERR = 1;
+ $HaltOnError = 0;
+ $SkipExistingPackages = 1;
+ $ReallyQuiet = 1;
+
+ #$FTP_Host = "host.com";
+ #$FTP_User = "ag@host.com";
+ #$FTP_Pass = "password";
+ #$FTP_Dir = "cvsbuilds";
+
+ #$SDK_RootDirs{'UIQ2'}= "D:\\UIQ2";
+ $SDK_RootDirs{'UIQ3'}= "G:\\UIQ3";
+ #$SDK_RootDirs{'S60v1'}= "D:\\S60v1";
+ #$SDK_RootDirs{'S60v2'}= "D:\\S60v2";
+ $SDK_RootDirs{'S60v3'}= "G:\\S60_3rd_FP1";
+ #$SDK_RootDirs{'S80'}= "D:\\S80";
+ #$SDK_RootDirs{'S90'}= "D:\\S90";
+ $ECompXL_BinDir= "D:\\ECompXL\\";
+ if (0) # so we can turn them on/off easily
+ {
+# $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc";
+# $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "C:\\S\\libmad-0.15.1b\\group";
+# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "C:\\tremor\\epoc";
+ $SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ";
+ $SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60";
+ $SDK_LibraryDirs{'S80'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S80";
+ $SDK_LibraryDirs{'S90'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S90";
+ $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60\\S60V3";
+ $SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ\\UIQ3";
+ #$SDK_LibraryDirs{'ALL'}{'libmpeg2.lib'} = "C:\\S\\mpeg2dec-0.4.0\\epoc";
+ }
+
+ # now you can add $VariationSets only built on this PC below this line :)
+
+ }
else #########################################################################################################
{
print "ERROR: Computer name ".$ENV{'COMPUTERNAME'}." not recognized! Plz edit _LocalSettings.pl!";
@@ -245,15 +271,11 @@
}
# below here you could specify weird & experimental combinations, non-ready engines
- # a small version of the saga engine, because it is so big (no tremor,mad,zlib)
- #$VariationSets{'ALL'}{'saga_mini'} = "saga";
+ # Separate version for the broken sword engines (1&2)
+ $VariationSets{'ALL'}{'brokensword'} = "$DefaultFeatures sword1 sword2";
- # a smaller version of scumm without support for v7, v8 and HE games
- #$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
-
- # maybe you feel lucky and want to test the sword engines? :P
- #$VariationSets{'S60v2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
- #$VariationSets{'UIQ2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
+ # Separate version for Scumm games (COMI) since memory usage might be high
+ $VariationSets{'ALL'}{'scumm'} = "$DefaultFeatures scumm scumm_7_8 he";
# for mega-fast-testing only plz! Warning: contains to engines!
#$VariationSets{'ALL'}{'fast_empty'} = "";
diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README
index db46dae8de..1e011ec4a1 100644
--- a/backends/platform/symbian/README
+++ b/backends/platform/symbian/README
@@ -8,6 +8,18 @@
Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
$Id$
+Using parts of snprintf.c by
+Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
+Copyright © 1999,2000,2001,2002 Mark Martinec. All rights reserved.
+under these conditions:
+"Terms and conditions ...
+
+This program is free software; it is dual licensed, the terms of the "Frontier Artistic License" or
+the "GNU General Public License" can be chosen at your discretion.
+The chosen license then applies solely and in its entirety.
+Both licenses come with this Kit."
+
+
About ScummVM
--------------
diff --git a/backends/platform/symbian/S60/ScummVM_S60.mmp.in b/backends/platform/symbian/S60/ScummVM_S60.mmp.in
index 099b33ed95..35632d9c95 100644
--- a/backends/platform/symbian/S60/ScummVM_S60.mmp.in
+++ b/backends/platform/symbian/S60/ScummVM_S60.mmp.in
@@ -93,6 +93,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg
index bf3c69ae08..91649727df 100644
--- a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg
+++ b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg
@@ -16,7 +16,7 @@
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; $URL:$
-; $Id:$
+; $Id$
;
;
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S60v1"},(0x101f9b57),0,120,0
+#{"ScummVM S60v1"},(0x101f9b57),0,130,0
; Platform type
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
diff --git a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg
index 3f88ec918c..4547af0597 100644
--- a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg
+++ b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg
@@ -27,7 +27,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S60v2"},(0x101f9b57),0,120,0
+#{"ScummVM S60v2"},(0x101f9b57),0,130,0
; Platform type
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
index 8daf76138c..fae74a425a 100644
--- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
+++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
@@ -116,6 +116,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
index 6bd1fbd047..1898ac1b58 100644
--- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
+++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
@@ -34,7 +34,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM S60v3"},(0xA0000657),0,120,0
+#{"ScummVM S60v3"},(0xA0000657),0,13,0
;Supports Series 60 v 3.0
[0x101F7961], 0, 0, 0, {"Series60ProductID"}
@@ -63,7 +63,7 @@
"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\igor.tbl"-"c:\data\scummvm\igor.tbl"
"..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat"
-"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\drascula.dat"
+"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"c:\data\scummvm\scummvm.ini",FILENULL
diff --git a/backends/platform/symbian/S80/ScummVM_S80.mmp.in b/backends/platform/symbian/S80/ScummVM_S80.mmp.in
index 95879dd2af..1c8076fdc3 100644
--- a/backends/platform/symbian/S80/ScummVM_S80.mmp.in
+++ b/backends/platform/symbian/S80/ScummVM_S80.mmp.in
@@ -91,6 +91,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg b/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg
index 29e318a479..c6b3e6f82f 100644
--- a/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg
+++ b/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S80"},(0x101f9b57),0,120,0
+#{"ScummVM S80"},(0x101f9b57),0,130,0
; Platform type -- disabled: seems to be causing trouble
;(0x101F8ED2), 0, 0, 0, {"Series80ProductID"}
diff --git a/backends/platform/symbian/S90/Scummvm_S90.mmp.in b/backends/platform/symbian/S90/Scummvm_S90.mmp.in
index 47a3d9a1d4..8ace71b190 100644
--- a/backends/platform/symbian/S90/Scummvm_S90.mmp.in
+++ b/backends/platform/symbian/S90/Scummvm_S90.mmp.in
@@ -91,6 +91,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg b/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg
index 0173da7699..b578019979 100644
--- a/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg
+++ b/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S90"},(0x101f9b57),0,120,0
+#{"ScummVM S90"},(0x101f9b57),0,130,0
; Platform type -- disabled: seems to be causing trouble
;(0x101FBE04), 0, 0, 0, {"Series90ProductID"}
diff --git a/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in b/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in
index e9dff7b94f..9fab248799 100644
--- a/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in
+++ b/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in
@@ -89,6 +89,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg
index aca927eadd..a8b02d4099 100644
--- a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg
+++ b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg
@@ -16,7 +16,7 @@
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; $URL:$
-; $Id:$
+; $Id$
;
;
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM UIQ2"},(0x101f9b57),0,100,0
+#{"ScummVM UIQ2"},(0x101f9b57),0,130,0
; Platform type
(0x101F617B), 2, 0, 0, {"UIQ20ProductID"}
diff --git a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg
index ecca51bd26..2d08bd01b2 100644
--- a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg
+++ b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg
@@ -6,7 +6,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM SE"},(0x101f9b57),0,110,0
+#{"ScummVM SE"},(0x101f9b57),0,130,0
; Platform type
(0x101F617B), 2, 0, 0, {"UIQ20ProductID"}
diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
index cf3d0c1d7b..6053a72182 100644
--- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
+++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
@@ -117,6 +117,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
index 0883c88a21..cdeb83f192 100644
--- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
+++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
@@ -32,7 +32,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM UIQ3"},(0xA0000657),0,120,0
+#{"ScummVM UIQ3"},(0xA0000657),0,13,0
; ProductID for UIQ 3.0
; Product/platform version UID, Major, Minor, Build, Product ID
diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in
index d1c8878d4b..3277e34ba3 100644
--- a/backends/platform/symbian/mmp/scummvm_base.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in
@@ -85,7 +85,6 @@ SOURCEPATH ..\..\..\..\gui
//SOURCE KeysDialog.cpp
//SOURCE Actions.cpp
-
SOURCEPATH ..\..\..\..\sound
//START_AUTO_OBJECTS_SOUND_//
@@ -108,7 +107,8 @@ SOURCE backends\saves\savefile.cpp
SOURCE backends\saves\default\default-saves.cpp
SOURCE backends\saves\compressed\compressed-saves.cpp
SOURCE engines\engine.cpp
-
-
-// backend specific includes
+SOURCE engines\dialogs.cpp
+SOURCE backends\fs\abstract-fs.cpp
+SOURCE backends\fs\symbian\symbianstream.cpp
// backend specific includes
+
diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
new file mode 100644
index 0000000000..3f68ec086e
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
@@ -0,0 +1,56 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_tinsel.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+// empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\tinsel
+
+//START_AUTO_OBJECTS_TINSEL_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_TINSEL_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp
index 60e402632f..e71b242329 100644
--- a/backends/platform/symbian/src/SymbianActions.cpp
+++ b/backends/platform/symbian/src/SymbianActions.cpp
@@ -153,7 +153,7 @@ void SymbianActions::initInstanceGame() {
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble)
_action_enabled[ACTION_SAVE] = false;
else {
_action_enabled[ACTION_SAVE] = true;
diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp
index 0ce44d1704..23876c5ec1 100644
--- a/backends/platform/symbian/src/SymbianOS.cpp
+++ b/backends/platform/symbian/src/SymbianOS.cpp
@@ -24,10 +24,12 @@
#include <eikenv.h> // for CEikonEnv::Static() @ Symbian::FatalError()
#include <sdlapp.h> // for CSDLApp::GetExecutablePathCStr() @ Symbian::GetExecutablePath()
+#include <bautils.h>
#include "backends/fs/symbian/symbian-fs-factory.h"
#include "backends/platform/symbian/src/SymbianOS.h"
#include "backends/platform/symbian/src/SymbianActions.h"
+#include "backends/saves/default/default-saves.h"
#include "common/config-manager.h"
#include "common/events.h"
#include "common/file.h"
@@ -45,16 +47,7 @@
#define DEFAULT_CONFIG_FILE "scummvm.ini"
-
-
-#define KInputBufferLength 128
-// Symbian libc file functionality in order to provide shared file handles
-struct TSymbianFileEntry {
- RFile iFileHandle;
- char iInputBuffer[KInputBufferLength];
- TInt iInputBufferLen;
- TInt iInputPos;
-};
+#define DEFAULT_SAVE_PATH "Savegames"
#define FILE void
@@ -123,10 +116,6 @@ void OSystem_SDL_Symbian::setFeatureState(Feature f, bool enable) {
}
}
-FilesystemFactory *OSystem_SDL_Symbian::getFilesystemFactory() {
- return &SymbianFilesystemFactory::instance();
-}
-
static Common::String getDefaultConfigFileName() {
char configFile[MAXPATHLEN];
strcpy(configFile, Symbian::GetExecutablePath());
@@ -135,36 +124,48 @@ static Common::String getDefaultConfigFileName() {
}
Common::SeekableReadStream *OSystem_SDL_Symbian::openConfigFileForReading() {
- Common::File *confFile = new Common::File();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForReading();
}
Common::WriteStream *OSystem_SDL_Symbian::openConfigFileForWriting() {
- Common::DumpFile *confFile = new Common::DumpFile();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForWriting();
}
-
OSystem_SDL_Symbian::zoneDesc OSystem_SDL_Symbian::_zones[TOTAL_ZONES] = {
{ 0, 0, 320, 145 },
{ 0, 145, 150, 55 },
{ 150, 145, 170, 55 }
};
OSystem_SDL_Symbian::OSystem_SDL_Symbian() :_channels(0),_stereo_mix_buffer(0) {
+ _RFs = &CEikonEnv::Static()->FsSession();
+ _fsFactory = new SymbianFilesystemFactory();
}
void OSystem_SDL_Symbian::initBackend() {
+ // First set the extrapath (for installed dat files etc)
ConfMan.set("extrapath", Symbian::GetExecutablePath());
+
+ // Calculate the default savepath
+ Common::String savePath;
+ savePath = Symbian::GetExecutablePath();
+ savePath += DEFAULT_SAVE_PATH "\\";
+ _savefile = new DefaultSaveFileManager(savePath);
+
+ // If savepath has not already been set then set it
+ if (!ConfMan.hasKey("savepath")) {
+ ConfMan.set("savepath", savePath);
+
+ }
+
+ // Ensure that the current set path (might have been altered by the user) exists
+ Common::String currentPath = ConfMan.get("savepath");
+ TFileName fname;
+ TPtrC8 ptr((const unsigned char*)currentPath.c_str(),currentPath.size());
+ fname.Copy(ptr);
+ BaflUtils::EnsurePathExistsL(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), fname);
+
ConfMan.setBool("FM_high_quality", false);
#if !defined(S60) || defined(S60V3) // S60 has low quality as default
ConfMan.setBool("FM_medium_quality", true);
@@ -488,223 +489,60 @@ void OSystem_SDL_Symbian::initZones() {
}
}
-FILE* symbian_fopen(const char* name, const char* mode) {
- TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
- fileEntry->iInputPos = KErrNotFound;
-
- if (fileEntry != NULL) {
- TInt modeLen = strlen(mode);
-
- TPtrC8 namePtr((unsigned char*) name, strlen(name));
- TFileName tempFileName;
- tempFileName.Copy(namePtr);
-
- TInt fileMode = EFileRead;
-
- if (mode[0] == 'a')
- fileMode = EFileWrite;
-
- if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) {
- fileMode |= EFileStreamText;
- }
-
- if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) {
- fileMode = fileMode| EFileWrite;
- }
-
- fileMode = fileMode| EFileShareAny;
-
- switch(mode[0]) {
- case 'a':
- if (fileEntry->iFileHandle.Open(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- if (fileEntry->iFileHandle.Create(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- delete fileEntry;
- fileEntry = NULL;
- }
- }
- break;
- case 'r':
- if (fileEntry->iFileHandle.Open(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- delete fileEntry;
- fileEntry = NULL;
- }
- break;
-
- case 'w':
- if (fileEntry->iFileHandle.Replace(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- delete fileEntry;
- fileEntry = NULL;
- }
- break;
- }
+RFs& OSystem_SDL_Symbian::FsSession() {
+ return *_RFs;
+}
+
+// Symbian bsearch implementation is flawed
+void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
+ // Perform binary search
+ size_t lo = 0;
+ size_t hi = nmemb;
+ while (lo < hi) {
+ size_t mid = (lo + hi) / 2;
+ const void *p = ((const char *)base) + mid * size;
+ int tmp = (*compar)(key, p);
+ if (tmp < 0)
+ hi = mid;
+ else if (tmp > 0)
+ lo = mid + 1;
+ else
+ return (void *)p;
}
- return (FILE*) fileEntry;
-}
-
-void symbian_fclose(FILE* handle) {
- ((TSymbianFileEntry*)(handle))->iFileHandle.Close();
- delete (TSymbianFileEntry*)(handle);
+ return NULL;
}
-size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
- TUint32 totsize = size*numItems;
- TPtr8 pointer ( (unsigned char*) ptr, totsize);
-
- // Nothing cached and we want to load at least KInputBufferLength bytes
- if(totsize >= KInputBufferLength) {
- TUint32 totLength = 0;
- if(entry->iInputPos != KErrNotFound)
- {
- TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer+entry->iInputPos, entry->iInputBufferLen - entry->iInputPos, KInputBufferLength);
- pointer.Append(cacheBuffer);
- entry->iInputPos = KErrNotFound;
- totLength+=pointer.Length();
- pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
- }
-
- entry->iFileHandle.Read(pointer);
- totLength+=pointer.Length();
-
- pointer.Set((unsigned char*) ptr, totLength, totsize);
-
- }
- else {
- // Nothing in buffer
- if(entry->iInputPos == KErrNotFound) {
- TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength);
- entry->iFileHandle.Read(cacheBuffer);
-
- if(cacheBuffer.Length() >= totsize) {
- pointer.Copy(cacheBuffer.Left(totsize));
- entry->iInputPos = totsize;
- entry->iInputBufferLen = cacheBuffer.Length();
- }
- else {
- pointer.Copy(cacheBuffer);
- entry->iInputPos = KErrNotFound;
- }
-
- }
- else {
- TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, entry->iInputBufferLen, KInputBufferLength);
-
- if(entry->iInputPos+totsize < entry->iInputBufferLen) {
- pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize));
- entry->iInputPos+=totsize;
- }
- else {
-
- pointer.Copy(cacheBuffer.Mid(entry->iInputPos, entry->iInputBufferLen-entry->iInputPos));
- cacheBuffer.SetLength(0);
- entry->iFileHandle.Read(cacheBuffer);
-
- if(cacheBuffer.Length() >= totsize-pointer.Length()) {
- TUint32 restSize = totsize-pointer.Length();
- pointer.Append(cacheBuffer.Left(restSize));
- entry->iInputPos = restSize;
- entry->iInputBufferLen = cacheBuffer.Length();
- }
- else {
- pointer.Append(cacheBuffer);
- entry->iInputPos = KErrNotFound;
- }
- }
- }
- }
-
- return pointer.Length()/size;
-}
-
-size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
- TPtrC8 pointer( (unsigned char*) ptr, size*numItems);
-
- ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound;
- if (((TSymbianFileEntry*)(handle))->iFileHandle.Write(pointer) == KErrNone) {
- return numItems;
- }
-
- return 0;
-}
-
-bool symbian_feof(FILE* handle) {
- TInt pos = 0;
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
-
- if (entry->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) {
-
- TInt size = 0;
- if (entry->iFileHandle.Size(size) == KErrNone) {
- if(entry->iInputPos == KErrNotFound && pos == size)
- return true;
-
- if(entry->iInputPos != KErrNotFound && pos == size && entry->iInputPos == entry->iInputBufferLen)
- return true;
-
- return false;
- }
- }
- return true;
-}
-
-long int symbian_ftell(FILE* handle) {
- TInt pos = 0;
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
-
- entry->iFileHandle.Seek(ESeekCurrent, pos);
- if(entry->iInputPos != KErrNotFound)
- {
- pos+=(entry->iInputPos - entry->iInputBufferLen);
- }
- return pos;
-}
-
-int symbian_fseek(FILE* handle, long int offset, int whence) {
-
- TSeek seekMode = ESeekStart;
- TInt pos = offset;
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
-
- switch(whence) {
- case SEEK_SET:
- seekMode = ESeekStart;
- break;
- case SEEK_CUR:
- seekMode = ESeekCurrent;
- if(entry->iInputPos != KErrNotFound) {
- pos+=(entry->iInputPos - entry->iInputBufferLen);
- }
- break;
- case SEEK_END:
- seekMode = ESeekEnd;
- break;
-
- }
-
- entry->iInputPos = KErrNotFound;
-
- return entry->iFileHandle.Seek(seekMode, pos);
-}
-
-void symbian_clearerr(FILE* /*handle*/) {
+extern "C"
+{
+// Include the snprintf and vsnprintf implementations as 'C' code
+#include "vsnprintf.h"
}
/** Vibration support */
#ifdef USE_VIBRA_SE_PXXX
void OSystem_SDL_Symbian::initializeVibration() {
- _vibrationApi = SonyEricsson::CVibration::NewL();
+#ifdef UIQ3
+#else
+#endif
}
void OSystem_SDL_Symbian::vibrationOn(int vibraLength) {
- // initialize?
+#ifdef UIQ3
+ // initialize?
if (!_vibrationApi) _vibrationApi = SonyEricsson::CVibration::NewL();
// do it!
_vibrationApi->VibrationOn(1, 1, vibraLength);
+#else
+
+#endif
}
void OSystem_SDL_Symbian::vibrationOff() {
+#ifdef UIQ3
+#else
_vibrationApi->VibrationOff();
+#endif
}
#endif // USE_SE_PXX_VIBRA
diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h
index 68a6fb492f..03d7fb972c 100644
--- a/backends/platform/symbian/src/SymbianOS.h
+++ b/backends/platform/symbian/src/SymbianOS.h
@@ -27,12 +27,8 @@
#include "backends/platform/sdl/sdl.h"
-/** Vibration support */
-#ifdef USE_VIBRA_SE_PXXX
-#include <vibration.h>
-#endif
-
#define TOTAL_ZONES 3
+class RFs;
class OSystem_SDL_Symbian : public OSystem_SDL {
public:
@@ -62,6 +58,9 @@ public:
// Overloaded from SDL_Commmon
void quit();
+
+ // Returns reference to File session
+ RFs& FsSession();
protected:
//
// The mixer callback function, passed on to OSystem::setSoundCallback().
@@ -70,7 +69,6 @@ protected:
//
static void symbianMixCallback(void *s, byte *samples, int len);
- virtual FilesystemFactory *getFilesystemFactory();
virtual Common::SeekableReadStream *openConfigFileForReading();
virtual Common::WriteStream *openConfigFileForWriting();
@@ -134,6 +132,7 @@ protected:
} zoneDesc;
static zoneDesc _zones[TOTAL_ZONES];
+ RFs* _RFs;
};
#endif
diff --git a/backends/platform/symbian/src/main_features.inl b/backends/platform/symbian/src/main_features.inl
deleted file mode 100644
index 30bbbea52c..0000000000
--- a/backends/platform/symbian/src/main_features.inl
+++ /dev/null
@@ -1,92 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
- * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
- * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
- * Copyright (C) 2005-2006 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifdef USE_VIBRA_SE_PXXX
- "Vibra "
-#endif
- "\n"
-
-// we want a list of supported engines visible in the program,
-// because we also release special builds with only one engine
-#ifdef ENABLE_SCUMM
- "SCUMM "
-#endif
-#ifdef ENABLE_AGOS
- "AGOS "
-#endif
-#ifdef ENABLE_SKY
- "Sky "
-#endif
-#ifdef ENABLE_QUEEN
- "Queen "
-#endif
-#ifdef ENABLE_GOB
- "Gob "
-#endif
-#ifdef ENABLE_SAGA
- "Saga "
-#endif
-#ifdef ENABLE_KYRA
- "Kyra "
-#endif
-#ifdef ENABLE_SWORD1
- "Sword1 "
-#endif
-#ifdef ENABLE_SWORD2
- "Sword2 "
-#endif
-#ifdef ENABLE_CINE
- "Cine "
-#endif
-#ifdef ENABLE_LURE
- "Lure "
-#endif
-#ifdef ENABLE_AGI
- "AGI "
-#endif
-#ifdef ENABLE_TOUCHE
- "Touche "
-#endif
-#ifdef ENABLE_DRASCULA
- "Drascula "
-#endif
-#ifdef ENABLE_IGOR
- "Igor "
-#endif
-#ifdef ENABLE_PARALLACTION
- "Parallaction "
-#endif
-#ifdef ENABLE_CRUISE
- "Cruise "
-#endif
-#ifdef ENABLE_MADE
- "MADE "
-#endif
-#ifdef ENABLE_M4
- "M4 "
-#endif
-
-
-
-
-
-
diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h
index 4577824b33..ab8333c986 100644
--- a/backends/platform/symbian/src/portdefs.h
+++ b/backends/platform/symbian/src/portdefs.h
@@ -35,9 +35,6 @@
#include <e32std.h>
#include <math.h>
-//#define DISABLE_SCALERS // we only need 1x
-//#define DISABLE_HQ_SCALERS
-
#if defined(USE_TREMOR) && !defined(USE_VORBIS)
#define USE_VORBIS // make sure this one is defined together with USE_TREMOR!
#endif
@@ -107,56 +104,35 @@
*/
#elif defined (__WINS__) // WINS
+ extern "C" int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...);
+ extern "C" int symbian_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
+ #define snprintf(buf,len,args...) symbian_snprintf(buf,len,args)
+ #define vsnprintf(buf,len,format,valist) symbian_vsnprintf(buf,len,format,valist)
- // let's just blatantly ignore this for now and just get it to work :P but does n't work from the debug function
- int inline scumm_snprintf (char *str, unsigned long /*n*/, char const *fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vsprintf(str, fmt, args);
- va_end(args);
- return strlen(str);
- }
-
- int inline scumm_vsnprintf (char *str, unsigned long /*n*/, char const *fmt, va_list valist) {
- vsprintf(str, fmt, valist);
- return strlen(str);
- }
-
- #define snprintf scumm_snprintf
- #define vsnprintf scumm_vsnprintf
void* symbian_malloc (size_t _size);
#define malloc symbian_malloc
#else // GCCE and the rest
- #define snprintf(buf,len,args...) sprintf(buf,args)
- #define vsnprintf(buf,len,format,valist) vsprintf(buf,format,valist)
+ extern "C" int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...);
+ extern "C" int symbian_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
+ #define snprintf(buf,len,args...) symbian_snprintf(buf,len,args)
+ #define vsnprintf(buf,len,format,valist) symbian_vsnprintf(buf,len,format,valist)
#endif
#ifndef __WINS__
#define USE_ARM_GFX_ASM
-#define ARM_USE_GFX_ASM
#define USE_ARM_SMUSH_ASM
#define USE_ARM_COSTUME_ASM
#define USE_ARM_SOUND_ASM
#endif
-// somehow nobody has this function...
-#define hypot(a, b) sqrt((a)*(a) + (b)*(b))
// Symbian bsearch implementation is flawed
-void inline *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
- size_t i;
-
- for (i=0; i < nmemb; i++)
- if (compar(key, (void *)((size_t)base + size * i)) == 0)
- return (void *)((size_t)base + size * i);
- return NULL;
-}
-#define bsearch scumm_bsearch
+void *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
+#define bsearch scumm_bsearch
// we cannot include SymbianOS.h everywhere, but this works too (functions code is in SymbianOS.cpp)
namespace Symbian {
extern void FatalError(const char *msg);
extern char* GetExecutablePath();
-#define DYNAMIC_MODULES 1
}
#endif
diff --git a/backends/platform/symbian/src/vsnprintf.h b/backends/platform/symbian/src/vsnprintf.h
new file mode 100644
index 0000000000..5ed04b1980
--- /dev/null
+++ b/backends/platform/symbian/src/vsnprintf.h
@@ -0,0 +1,668 @@
+/*
+ * This is the vsnprintf for scummvm/symbian implementation from the original snprintf.c,
+ * all support functions has been removed and vsnprintf renamed to symbian_vsnprintf
+ * snprintf.c - a portable implementation of snprintf
+ * According to the homepage this function could be licensed as either Frontier Aritistic or GPL.
+ *
+ * AUTHOR
+ * Mark Martinec <mark.martinec@ijs.si>, April 1999.
+ *
+ * Copyright 1999, Mark Martinec. All rights reserved.
+ *
+ * TERMS AND CONDITIONS
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the "Frontier Artistic License" which comes
+ * with this Kit.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Frontier Artistic License for more details.
+ *
+ * You should have received a copy of the Frontier Artistic License
+ * with this Kit in the file named LICENSE.txt .
+ * If not, I'll be glad to provide one.
+ *
+ * FEATURES
+ * - careful adherence to specs regarding flags, field width and precision;
+ * - good performance for large string handling (large format, large
+ * argument or large paddings). Performance is similar to system's sprintf
+ * and in several cases significantly better (make sure you compile with
+ * optimizations turned on, tell the compiler the code is strict ANSI
+ * if necessary to give it more freedom for optimizations);
+ * - return value semantics per ISO/IEC 9899:1999 ("ISO C99");
+ * - written in standard ISO/ANSI C - requires an ANSI C compiler.
+ *
+ * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES
+ *
+ * This snprintf only supports the following conversion specifiers:
+ * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
+ * with flags: '-', '+', ' ', '0' and '#'.
+ * An asterisk is supported for field width as well as precision.
+ *
+ * Length modifiers 'h' (short int), 'l' (long int),
+ * and 'll' (long long int) are supported.
+ * NOTE:
+ * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the
+ * length modifier 'll' is recognized but treated the same as 'l',
+ * which may cause argument value truncation! Defining
+ * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also
+ * handles length modifier 'll'. long long int is a language extension
+ * which may not be portable.
+ *
+ * Conversion of numeric data (conversion specifiers d, u, o, x, X, p)
+ * with length modifiers (none or h, l, ll) is left to the system routine
+ * sprintf, but all handling of flags, field width and precision as well as
+ * c and s conversions is done very carefully by this portable routine.
+ * If a string precision (truncation) is specified (e.g. %.8s) it is
+ * guaranteed the string beyond the specified precision will not be referenced.
+ *
+ * Length modifiers h, l and ll are ignored for c and s conversions (data
+ * types wint_t and wchar_t are not supported).
+ *
+ * The following common synonyms for conversion characters are supported:
+ * - i is a synonym for d
+ * - D is a synonym for ld, explicit length modifiers are ignored
+ * - U is a synonym for lu, explicit length modifiers are ignored
+ * - O is a synonym for lo, explicit length modifiers are ignored
+ * The D, O and U conversion characters are nonstandard, they are supported
+ * for backward compatibility only, and should not be used for new code.
+ *
+ * The following is specifically NOT supported:
+ * - flag ' (thousands' grouping character) is recognized but ignored
+ * - numeric conversion specifiers: f, e, E, g, G and synonym F,
+ * as well as the new a and A conversion specifiers
+ * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead)
+ * - wide character/string conversions: lc, ls, and nonstandard
+ * synonyms C and S
+ * - writeback of converted string length: conversion character n
+ * - the n$ specification for direct reference to n-th argument
+ * - locales
+ *
+ * It is permitted for str_m to be zero, and it is permitted to specify NULL
+ * pointer for resulting string argument if str_m is zero (as per ISO C99).
+ *
+ * The return value is the number of characters which would be generated
+ * for the given input, excluding the trailing null. If this value
+ * is greater or equal to str_m, not all characters from the result
+ * have been stored in str, output bytes beyond the (str_m-1) -th character
+ * are discarded. If str_m is greater than zero it is guaranteed
+ * the resulting string will be null-terminated.
+ *
+ * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1,
+ * but is different from some older and vendor implementations,
+ * and is also different from XPG, XSH5, SUSv2 specifications.
+ * For historical discussion on changes in the semantics and standards
+ * of snprintf see printf(3) man page in the Linux programmers manual.
+ *
+ * Routines asprintf and vasprintf return a pointer (in the ptr argument)
+ * to a buffer sufficiently large to hold the resulting string. This pointer
+ * should be passed to free(3) to release the allocated storage when it is
+ * no longer needed. If sufficient space cannot be allocated, these functions
+ * will return -1 and set ptr to be a NULL pointer. These two routines are a
+ * GNU C library extensions (glibc).
+ *
+ * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf,
+ * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1
+ * characters into the allocated output string, the last character in the
+ * allocated buffer then gets the terminating null. If the formatted string
+ * length (the return value) is greater than or equal to the str_m argument,
+ * the resulting string was truncated and some of the formatted characters
+ * were discarded. These routines present a handy way to limit the amount
+ * of allocated memory to some sane value.
+ *
+ * AVAILABILITY
+ * http://www.ijs.si/software/snprintf/
+ *
+ * REVISION HISTORY
+ * 1999-04 V0.9 Mark Martinec
+ * - initial version, some modifications after comparing printf
+ * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10,
+ * and checking how Perl handles sprintf (differently!);
+ * 1999-04-09 V1.0 Mark Martinec <mark.martinec@ijs.si>
+ * - added main test program, fixed remaining inconsistencies,
+ * added optional (long long int) support;
+ * 1999-04-12 V1.1 Mark Martinec <mark.martinec@ijs.si>
+ * - support the 'p' conversion (pointer to void);
+ * - if a string precision is specified
+ * make sure the string beyond the specified precision
+ * will not be referenced (e.g. by strlen);
+ * 1999-04-13 V1.2 Mark Martinec <mark.martinec@ijs.si>
+ * - support synonyms %D=%ld, %U=%lu, %O=%lo;
+ * - speed up the case of long format string with few conversions;
+ * 1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
+ * - fixed runaway loop (eventually crashing when str_l wraps
+ * beyond 2^31) while copying format string without
+ * conversion specifiers to a buffer that is too short
+ * (thanks to Edwin Young <edwiny@autonomy.com> for
+ * spotting the problem);
+ * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR)
+ * to snprintf.h
+ * 2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
+ * - relaxed license terms: The Artistic License now applies.
+ * You may still apply the GNU GENERAL PUBLIC LICENSE
+ * as was distributed with previous versions, if you prefer;
+ * - changed REVISION HISTORY dates to use ISO 8601 date format;
+ * - added vsnprintf (patch also independently proposed by
+ * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
+ * 2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
+ * - removed POSIX check for str_m<1; value 0 for str_m is
+ * allowed by ISO C99 (and GNU C library 2.1) - (pointed out
+ * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie).
+ * Besides relaxed license this change in standards adherence
+ * is the main reason to bump up the major version number;
+ * - added nonstandard routines asnprintf, vasnprintf, asprintf,
+ * vasprintf that dynamically allocate storage for the
+ * resulting string; these routines are not compiled by default,
+ * see comments where NEED_V?ASN?PRINTF macros are defined;
+ * - autoconf contributed by Caolan McNamara
+ * 2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si>
+ * - BUG FIX: the %c conversion used a temporary variable
+ * that was no longer in scope when referenced,
+ * possibly causing incorrect resulting character;
+ * - BUG FIX: make precision and minimal field width unsigned
+ * to handle huge values (2^31 <= n < 2^32) correctly;
+ * also be more careful in the use of signed/unsigned/size_t
+ * internal variables - probably more careful than many
+ * vendor implementations, but there may still be a case
+ * where huge values of str_m, precision or minimal field
+ * could cause incorrect behaviour;
+ * - use separate variables for signed/unsigned arguments,
+ * and for short/int, long, and long long argument lengths
+ * to avoid possible incompatibilities on certain
+ * computer architectures. Also use separate variable
+ * arg_sign to hold sign of a numeric argument,
+ * to make code more transparent;
+ * - some fiddling with zero padding and "0x" to make it
+ * Linux compatible;
+ * - systematically use macros fast_memcpy and fast_memset
+ * instead of case-by-case hand optimization; determine some
+ * breakeven string lengths for different architectures;
+ * - terminology change: 'format' -> 'conversion specifier',
+ * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")',
+ * 'alternative form' -> 'alternate form',
+ * 'data type modifier' -> 'length modifier';
+ * - several comments rephrased and new ones added;
+ * - make compiler not complain about 'credits' defined but
+ * not used;
+ */
+/* ============================================= */
+/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */
+/* ============================================= */
+
+#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
+#define PORTABLE_SNPRINTF_VERSION_MINOR 2
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <errno.h>
+#ifdef isdigit
+#undef isdigit
+#endif
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+
+#ifndef breakeven_point
+# define breakeven_point 6 /* some reasonable one-size-fits-all value */
+#endif
+
+#define fast_memcpy(d,s,n) \
+{ register size_t nn = (size_t)(n); \
+ if (nn >= breakeven_point) memcpy((d), (s), nn); \
+ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
+ register char *dd; register const char *ss; \
+for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
+
+#define fast_memset(d,c,n) \
+{ register size_t nn = (size_t)(n); \
+ if (nn >= breakeven_point) memset((d), (int)(c), nn); \
+ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
+ register char *dd; register const int cc=(int)(c); \
+for (dd=(d); nn>0; nn--) *dd++ = cc; } }
+
+
+/* declarations */
+
+static char credits[] = "\n\
+@(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
+@(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
+@(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
+int symbian_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
+
+ size_t str_l = 0;
+ const char *p = fmt;
+
+ /* In contrast with POSIX, the ISO C99 now says
+ * that str can be NULL and str_m can be 0.
+ * This is more useful than the old: if (str_m < 1) return -1; */
+
+ if (!p) p = "";
+ while (*p) {
+ if (*p != '%') {
+ /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */
+ /* but the following code achieves better performance for cases
+ * where format string is long and contains few conversions */
+ const char *q = strchr(p+1,'%');
+ size_t n = !q ? strlen(p) : (q-p);
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memcpy(str+str_l, p, (n>avail?avail:n));
+ }
+ p += n; str_l += n;
+ } else {
+ const char *starting_p;
+ size_t min_field_width = 0, precision = 0;
+ int zero_padding = 0, precision_specified = 0, justify_left = 0;
+ int alternate_form = 0, force_sign = 0;
+ int space_for_positive = 1; /* If both the ' ' and '+' flags appear,
+ the ' ' flag should be ignored. */
+ char length_modifier = '\0'; /* allowed values: \0, h, l, L */
+ char tmp[32];/* temporary buffer for simple numeric->string conversion */
+
+ const char *str_arg; /* string address in case of string argument */
+ size_t str_arg_l; /* natural field width of arg without padding
+ and sign */
+ unsigned char uchar_arg;
+ /* unsigned char argument value - only defined for c conversion.
+ N.B. standard explicitly states the char argument for
+ the c conversion is unsigned */
+
+ size_t number_of_zeros_to_pad = 0;
+ /* number of zeros to be inserted for numeric conversions
+ as required by the precision or minimal field width */
+
+ size_t zero_padding_insertion_ind = 0;
+ /* index into tmp where zero padding is to be inserted */
+
+ char fmt_spec = '\0';
+ /* current conversion specifier character */
+
+ str_arg = credits;/* just to make compiler happy (defined but not used)*/
+ str_arg = NULL;
+ starting_p = p; p++; /* skip '%' */
+ /* parse flags */
+ while (*p == '0' || *p == '-' || *p == '+' ||
+ *p == ' ' || *p == '#' || *p == '\'') {
+ switch (*p) {
+ case '0': zero_padding = 1; break;
+ case '-': justify_left = 1; break;
+ case '+': force_sign = 1; space_for_positive = 0; break;
+ case ' ': force_sign = 1;
+ /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
+ break;
+ case '#': alternate_form = 1; break;
+ case '\'': break;
+ }
+ p++;
+ }
+ /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
+
+ /* parse field width */
+ if (*p == '*') {
+ int j;
+ p++; j = va_arg(ap, int);
+ if (j >= 0) min_field_width = j;
+ else { min_field_width = -j; justify_left = 1; }
+ } else if (isdigit((int)(*p))) {
+ /* size_t could be wider than unsigned int;
+ make sure we treat argument like common implementations do */
+ unsigned int uj = *p++ - '0';
+ while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
+ min_field_width = uj;
+ }
+ /* parse precision */
+ if (*p == '.') {
+ p++; precision_specified = 1;
+ if (*p == '*') {
+ int j = va_arg(ap, int);
+ p++;
+ if (j >= 0) precision = j;
+ else {
+ precision_specified = 0; precision = 0;
+ /* NOTE:
+ * Solaris 2.6 man page claims that in this case the precision
+ * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page
+ * claim that this case should be treated as unspecified precision,
+ * which is what we do here.
+ */
+ }
+ } else if (isdigit((int)(*p))) {
+ /* size_t could be wider than unsigned int;
+ make sure we treat argument like common implementations do */
+ unsigned int uj = *p++ - '0';
+ while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
+ precision = uj;
+ }
+ }
+ /* parse 'h', 'l' and 'll' length modifiers */
+ if (*p == 'h' || *p == 'l') {
+ length_modifier = *p; p++;
+ if (length_modifier == 'l' && *p == 'l') { /* double l = long long */
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ length_modifier = '2'; /* double l encoded as '2' */
+#else
+ length_modifier = 'l'; /* treat it as a single 'l' */
+#endif
+ p++;
+ }
+ }
+ fmt_spec = *p;
+ /* common synonyms: */
+ switch (fmt_spec) {
+ case 'i': fmt_spec = 'd'; break;
+ case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
+ case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
+ case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
+ default: break;
+ }
+ /* get parameter value, do initial processing */
+ switch (fmt_spec) {
+ case '%': /* % behaves similar to 's' regarding flags and field widths */
+ case 'c': /* c behaves similar to 's' regarding flags and field widths */
+ case 's':
+ length_modifier = '\0'; /* wint_t and wchar_t not supported */
+ /* the result of zero padding flag with non-numeric conversion specifier*/
+ /* is undefined. Solaris and HPUX 10 does zero padding in this case, */
+ /* Digital Unix and Linux does not. */
+ zero_padding = 0; /* turn zero padding off for string conversions */
+ str_arg_l = 1;
+ switch (fmt_spec) {
+ case '%':
+ str_arg = p; break;
+ case 'c': {
+ int j = va_arg(ap, int);
+ uchar_arg = (unsigned char) j; /* standard demands unsigned char */
+ str_arg = (const char *) &uchar_arg;
+ break;
+ }
+ case 's':
+ str_arg = va_arg(ap, const char *);
+ if (!str_arg) str_arg_l = 0;
+ /* make sure not to address string beyond the specified precision !!! */
+ else if (!precision_specified) str_arg_l = strlen(str_arg);
+ /* truncate string if necessary as requested by precision */
+ else if (precision == 0) str_arg_l = 0;
+ else {
+ /* memchr on HP does not like n > 2^31 !!! */
+ const char *q = (const char*) memchr(str_arg, '\0',
+ precision <= 0x7fffffff ? precision : 0x7fffffff);
+ str_arg_l = !q ? precision : (q-str_arg);
+ }
+ break;
+ default: break;
+ }
+ break;
+ case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
+ /* NOTE: the u, o, x, X and p conversion specifiers imply
+ the value is unsigned; d implies a signed value */
+
+ int arg_sign = 0;
+ /* 0 if numeric argument is zero (or if pointer is NULL for 'p'),
+ +1 if greater than zero (or nonzero for unsigned arguments),
+ -1 if negative (unsigned argument is never negative) */
+
+ int int_arg = 0; unsigned int uint_arg = 0;
+ /* only defined for length modifier h, or for no length modifiers */
+
+ long int long_arg = 0; unsigned long int ulong_arg = 0;
+ /* only defined for length modifier l */
+
+ void *ptr_arg = NULL;
+ /* pointer argument value -only defined for p conversion */
+
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ long long int long_long_arg = 0;
+ unsigned long long int ulong_long_arg = 0;
+ /* only defined for length modifier ll */
+#endif
+ if (fmt_spec == 'p') {
+ /* HPUX 10: An l, h, ll or L before any other conversion character
+ * (other than d, i, u, o, x, or X) is ignored.
+ * Digital Unix:
+ * not specified, but seems to behave as HPUX does.
+ * Solaris: If an h, l, or L appears before any other conversion
+ * specifier (other than d, i, u, o, x, or X), the behavior
+ * is undefined. (Actually %hp converts only 16-bits of address
+ * and %llp treats address as 64-bit data which is incompatible
+ * with (void *) argument on a 32-bit system).
+ */
+ length_modifier = '\0';
+ ptr_arg = va_arg(ap, void *);
+ if (ptr_arg != NULL) arg_sign = 1;
+ } else if (fmt_spec == 'd') { /* signed */
+ switch (length_modifier) {
+ case '\0':
+ case 'h':
+ /* It is non-portable to specify a second argument of char or short
+ * to va_arg, because arguments seen by the called function
+ * are not char or short. C converts char and short arguments
+ * to int before passing them to a function.
+ */
+ int_arg = va_arg(ap, int);
+ if (int_arg > 0) arg_sign = 1;
+ else if (int_arg < 0) arg_sign = -1;
+ break;
+ case 'l':
+ long_arg = va_arg(ap, long int);
+ if (long_arg > 0) arg_sign = 1;
+ else if (long_arg < 0) arg_sign = -1;
+ break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2':
+ long_long_arg = va_arg(ap, long long int);
+ if (long_long_arg > 0) arg_sign = 1;
+ else if (long_long_arg < 0) arg_sign = -1;
+ break;
+#endif
+ }
+ } else { /* unsigned */
+ switch (length_modifier) {
+ case '\0':
+ case 'h':
+ uint_arg = va_arg(ap, unsigned int);
+ if (uint_arg) arg_sign = 1;
+ break;
+ case 'l':
+ ulong_arg = va_arg(ap, unsigned long int);
+ if (ulong_arg) arg_sign = 1;
+ break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2':
+ ulong_long_arg = va_arg(ap, unsigned long long int);
+ if (ulong_long_arg) arg_sign = 1;
+ break;
+#endif
+ }
+ }
+ str_arg = tmp; str_arg_l = 0;
+ /* NOTE:
+ * For d, i, u, o, x, and X conversions, if precision is specified,
+ * the '0' flag should be ignored. This is so with Solaris 2.6,
+ * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
+ */
+ if (precision_specified) zero_padding = 0;
+ if (fmt_spec == 'd') {
+ if (force_sign && arg_sign >= 0)
+ tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
+ /* leave negative numbers for sprintf to handle,
+ to avoid handling tricky cases like (short int)(-32768) */
+ } else if (alternate_form) {
+ if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
+ { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; }
+ /* alternate form should have no effect for p conversion, but ... */
+ }
+ zero_padding_insertion_ind = str_arg_l;
+ if (!precision_specified) precision = 1; /* default precision is 1 */
+ if (precision == 0 && arg_sign == 0
+ ) {
+ /* converted to null string */
+ /* When zero value is formatted with an explicit precision 0,
+ the resulting formatted string is empty (d, i, u, o, x, X, p). */
+ } else {
+ char f[5]; int f_l = 0;
+ f[f_l++] = '%'; /* construct a simple format string for sprintf */
+ if (!length_modifier) { }
+ else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
+ else f[f_l++] = length_modifier;
+ f[f_l++] = fmt_spec; f[f_l++] = '\0';
+ if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
+ else if (fmt_spec == 'd') { /* signed */
+ switch (length_modifier) {
+ case '\0':
+ case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break;
+ case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
+#endif
+ }
+ } else { /* unsigned */
+ switch (length_modifier) {
+ case '\0':
+ case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break;
+ case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break;
+#endif
+ }
+ }
+ /* include the optional minus sign and possible "0x"
+ in the region before the zero padding insertion point */
+ if (zero_padding_insertion_ind < str_arg_l &&
+ tmp[zero_padding_insertion_ind] == '-') {
+ zero_padding_insertion_ind++;
+ }
+ if (zero_padding_insertion_ind+1 < str_arg_l &&
+ tmp[zero_padding_insertion_ind] == '0' &&
+ (tmp[zero_padding_insertion_ind+1] == 'x' ||
+ tmp[zero_padding_insertion_ind+1] == 'X') ) {
+ zero_padding_insertion_ind += 2;
+ }
+ }
+ { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
+ if (alternate_form && fmt_spec == 'o'
+ /* unless zero is already the first character */
+ && !(zero_padding_insertion_ind < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '0')
+ ) { /* assure leading zero for alternate-form octal numbers */
+ if (!precision_specified || precision < num_of_digits+1) {
+ /* precision is increased to force the first character to be zero,
+ except if a zero value is formatted with an explicit precision
+ of zero */
+ precision = num_of_digits+1; precision_specified = 1;
+ }
+ }
+ /* zero padding to specified precision? */
+ if (num_of_digits < precision)
+ number_of_zeros_to_pad = precision - num_of_digits;
+ }
+ /* zero padding to specified minimal field width? */
+ if (!justify_left && zero_padding) {
+ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
+ if (n > 0) number_of_zeros_to_pad += n;
+ }
+ break;
+ }
+ default: /* unrecognized conversion specifier, keep format string as-is*/
+ zero_padding = 0; /* turn zero padding off for non-numeric convers. */
+ justify_left = 1; min_field_width = 0; /* reset flags */
+ /* discard the unrecognized conversion, just keep *
+ * the unrecognized conversion character */
+ str_arg = p; str_arg_l = 0;
+ if (*p) str_arg_l++; /* include invalid conversion specifier unchanged
+ if not at end-of-string */
+ break;
+ }
+ if (*p) p++; /* step over the just processed conversion specifier */
+ /* insert padding to the left as requested by min_field_width;
+ this does not include the zero padding in case of numerical conversions*/
+ if (!justify_left) { /* left padding with blank or zero */
+ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ /* zero padding as requested by the precision or by the minimal field width
+ * for numeric conversions required? */
+ if (number_of_zeros_to_pad <= 0) {
+ /* will not copy first part of numeric right now, *
+ * force it to be copied later in its entirety */
+ zero_padding_insertion_ind = 0;
+ } else {
+ /* insert first part of numerics (sign or '0x') before zero padding */
+ int n = zero_padding_insertion_ind;
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ /* insert zero padding as requested by the precision or min field width */
+ n = number_of_zeros_to_pad;
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memset(str+str_l, '0', (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ /* insert formatted string
+ * (or as-is conversion specifier for unknown conversions) */
+ { int n = str_arg_l - zero_padding_insertion_ind;
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
+ (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ /* insert right padding */
+ if (justify_left) { /* right blank padding to the field width */
+ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memset(str+str_l, ' ', (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ }
+ }
+ if (str_m > 0) { /* make sure the string is null-terminated
+ even at the expense of overwriting the last character
+ (shouldn't happen, but just in case) */
+ str[str_l <= str_m-1 ? str_l : str_m-1] = '\0';
+ }
+ /* Return the number of characters formatted (excluding trailing null
+ * character), that is, the number of characters that would have been
+ * written to the buffer if it were large enough.
+ *
+ * The value of str_l should be returned, but str_l is of unsigned type
+ * size_t, and snprintf is int, possibly leading to an undetected
+ * integer overflow, resulting in a negative return value, which is illegal.
+ * Both XSH5 and ISO C99 (at least the draft) are silent on this issue.
+ * Should errno be set to EOVERFLOW and EOF returned in this case???
+ */
+ return (int) str_l;
+}
+
+int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...) {
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ retval = symbian_vsnprintf(text, maxlen, fmt, ap);
+ va_end(ap);
+
+ return retval;
+}
diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp
index 3626c4c10b..7f78517762 100644
--- a/backends/platform/wince/CEActionsPocket.cpp
+++ b/backends/platform/wince/CEActionsPocket.cpp
@@ -147,7 +147,7 @@ void CEActionsPocket::initInstanceGame() {
_key_action[POCKET_ACTION_PAUSE].setKey(VK_SPACE);
_action_enabled[POCKET_ACTION_PAUSE] = true;
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble)
_action_enabled[POCKET_ACTION_SAVE] = false;
else if (is_queen) {
_action_enabled[POCKET_ACTION_SAVE] = true;
diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp
index 87f73f5a66..0c4113cc0c 100644
--- a/backends/platform/wince/CEActionsSmartphone.cpp
+++ b/backends/platform/wince/CEActionsSmartphone.cpp
@@ -130,7 +130,7 @@ void CEActionsSmartphone::initInstanceGame() {
// Initialize keys for different actions
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble)
_action_enabled[SMARTPHONE_ACTION_SAVE] = false;
else if (is_queen) {
_action_enabled[SMARTPHONE_ACTION_SAVE] = true;
diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp
index edfdad84b3..7e306be114 100644
--- a/backends/platform/wince/CELauncherDialog.cpp
+++ b/backends/platform/wince/CELauncherDialog.cpp
@@ -72,10 +72,10 @@ void CELauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 d
}
}
-void CELauncherDialog::automaticScanDirectory(const FilesystemNode &node) {
+void CELauncherDialog::automaticScanDirectory(const Common::FilesystemNode &node) {
// First check if we have a recognized game in the current directory
- FSList files;
- node.getChildren(files, FilesystemNode::kListFilesOnly);
+ Common::FSList files;
+ node.getChildren(files, Common::FilesystemNode::kListFilesOnly);
// detect
GameList candidates(EngineMan.detectGames(files));
// insert
@@ -85,9 +85,9 @@ void CELauncherDialog::automaticScanDirectory(const FilesystemNode &node) {
addGameToConf(result);
}
// Then recurse on the subdirectories
- FSList dirs;
- node.getChildren(dirs, FilesystemNode::kListDirectoriesOnly);
- for (FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir)
+ Common::FSList dirs;
+ node.getChildren(dirs, Common::FilesystemNode::kListDirectoriesOnly);
+ for (Common::FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir)
automaticScanDirectory(*currentDir);
}
diff --git a/backends/platform/wince/CELauncherDialog.h b/backends/platform/wince/CELauncherDialog.h
index 55d177bcb8..a5f3fd0d43 100644
--- a/backends/platform/wince/CELauncherDialog.h
+++ b/backends/platform/wince/CELauncherDialog.h
@@ -36,7 +36,7 @@ public:
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
protected:
void addGame();
- void automaticScanDirectory(const FilesystemNode &node);
+ void automaticScanDirectory(const Common::FilesystemNode &node);
};
typedef GUI::LauncherDialog GUILauncherDialog;
diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile
index 4400d50e3a..9f040bbed1 100644
--- a/backends/platform/wince/Makefile
+++ b/backends/platform/wince/Makefile
@@ -45,8 +45,8 @@ ENABLE_DRASCULA = STATIC_PLUGIN
USE_MAD = 1
USE_MPEG2 = 1
-USE_TREMOR = 1
-#USE_TREMOLO = 1
+#USE_TREMOR = 1
+USE_TREMOLO = 1
USE_FLAC = 1
USE_ZLIB = 1
@@ -139,7 +139,7 @@ LIBS += -ltremorce
endif
ifdef USE_TREMOLO
-DEFINES += -DUSE_TREMOR -DUSE_VORBIS
+DEFINES += -DUSE_TREMOR -DUSE_VORBIS -DUSE_TREMOLO
INCLUDES += -Ilibs/include/tremolo
LIBS += -llibTremolo
endif
diff --git a/backends/platform/wince/README-WinCE.txt b/backends/platform/wince/README-WinCE.txt
index f4cb00dcfa..86c627d764 100644
--- a/backends/platform/wince/README-WinCE.txt
+++ b/backends/platform/wince/README-WinCE.txt
@@ -1,29 +1,28 @@
ScummVM Windows CE FAQ
Last updated: $Date$
-Release version: 0.11.0
+Release version: 0.12.0
------------------------------------------------------------------------
New in this version
-------------------
-0.11.0
-- Redesigned 'Free Look' action (Pocket PCs)
-In order to accommodate for the requirements of the lure engine, the
-usage characteristics of the 'Free Look' action have been improved. The
-new behavior is available for use in all engines, but is is *strongly*
-recommended for at least when playing 'Lure of the Temptress'. By using
-the new scheme, when in 'Free Look' mode, it is now possible to enter
-left clicks by clicking a second time near the current location of the
-mouse pointer. Left and Right clicks at the current point location
-are also available by using the respective actions' bound key.
+0.12.0:
+- Improved SMUSH support (deprecated 'Smush_force_redraw' option)
+No skipped frames in Full Throttle action sequences. The 'Smush_force_redraw'
+option is not needed/honored anymore.
-- Reduced optimization build
-The ScummVM executable has grown quite large, prohibiting some devices
-from running memory demanding games (or any games at all). Code
-optimization level has been reduced to offset the growth of the executable.
-Games run slightly slower. This will be addressed before next release.
+- Fixed MultiFuntion key in Full Throttle
-- Several bugfixes
+- Improved sound output
+Fixed a long standing bug which led to distorted sound output in all games.
+
+- Switched to faster ogg vorbis library
+Robin Watts' libTremolo is used for ogg vorbis (tremor) replay. Info patch
+by Lostech.
+
+- New right click through double tap inhibiting option
+Check out the 'no_doubletap_rightclick' option if double-tapping as a right
+click input method annoys you. Patch by spookypeanut.
------------------------------------------------------------------------
@@ -109,10 +108,10 @@ and report your success ...
How do I install ScummVM for Windows CE ?
-----------------------------------------
-Simple! Unpack the release package on your desktop pc, then copy all its contents
-to a folder on your device. Typically, you should at least have scummvm.exe,
-modern.ini and modern.zip in the same directory. Finally, upload your beloved games
-and fire it up :-)
+Simple! Unpack the release package on your desktop pc, then copy all its
+contents to a folder on your device. Typically, you should at least have
+scummvm.exe, modern.ini and modern.zip in the same directory. Finally, upload
+your beloved games and fire it up :-)
Some devices (like Pocket PC 2000) require GAPI to be present.
@@ -184,18 +183,19 @@ The following actions are available :
* Right click : acts as a right mouse button click
* Cursor : hide or display the mouse cursor
* Free look : go in or out of free-look mode. In this mode, you can tap
- the screen to look for interesting locations without walking.
- Cling a second time near the pointer's location equals to left click.
+ the screen to look for interesting locations without
+ walking. Click a second time near the pointer's location
+ equals to a left click.
* Zoom up : magnify the upper part of the screen for 640x480 games
rendered on a QVGA device.
* Zoom down : magnify the lower part of the screen for 640x480 games
rendered on a QVGA device.
- * Multi Function : this key performs a different function depending on the game
- : Full Throttle -> win an action sequence (cheat)
- : Fate of Atlantis -> sucker punch (cheat)
- : Bargon -> F1 (start the game)
- : All AGI games -> bring up the predictive input dialog
- * Bind keys : map a key action to a device button
+ * Multi Function : performs a different function depending on the game :
+ Full Throttle -> win an action sequence (cheat)
+ Fate of Atlantis -> sucker punch (cheat)
+ Bargon -> F1 (start the game)
+ All AGI games -> bring up the predictive input dialog
+ * Bind keys map a key action to a device button
* Up,Down,Left :
Right, : emulate mouse/stylus behavior
Left Click :
@@ -245,11 +245,11 @@ the list of available actions for Smartphones:
* Skip : skip a non interactive sequence, the current dialog or
behaves like the ESC key on a regular keyboard
* Zone : switch between the 3 different mouse zones
- * Multi Function : this key performs a different function depending on the game
- : Full Throttle -> win an action sequence (cheat)
- : Fate of Atlantis -> sucker punch (cheat)
- : Bargon -> F1 (start the game)
- : All AGI games -> bring up the predictive input dialog
+ * Multi Function : performs a different function depending on the game
+ Full Throttle -> win an action sequence (cheat)
+ Fate of Atlantis -> sucker punch (cheat)
+ Bargon -> F1 (start the game)
+ All AGI games -> bring up the predictive input dialog
* Bind keys : map a key action to a device button
* Keyboard : hide or display the virtual keyboard
* Rotate : rotate the screen (also rotates dpad keys)
@@ -287,32 +287,34 @@ Some parameters are specific to this port :
Game specific sections (f.e. [monkey2]) - performance options
- * high_sample_rate bool Desktop quality (22 kHz) sound output if set.
- 11 kHz otherwise. The default is 11 kHz.
- If you have a fast device, you can set this to
- true to enjoy better sound effects and music.
+ * high_sample_rate bool Desktop quality (22 kHz) sound output if
+ set. The default is 11 kHz.
+ If you have a fast device, you can set this
+ to true to enjoy better sound effects and
+ music.
* FM_high_quality bool Desktop quality FM synthesis if set. Lower
- quality otherwise. The default is low quality.
- You can change this if you have a fast device.
- * sound_thread_priority int Set the priority of the sound thread (0, 1, 2).
- Depending on the release, this is set to 1
- internally (above normal). If you get sound
- stuttering try setting this to a higher value.
+ quality otherwise. The default is low
+ quality. You can change this if you have a
+ fast device.
+ * sound_thread_priority int Set the priority of the sound thread (0, 1,
+ 2). Depending on the release, this is set
+ to 1 internally (above normal).
+ If you get sound stuttering try setting
+ this to a higher value.
Set to 0 if your device is fast enough or if
- you prefer better audio/video synchronization.
- * Smush_force_redraw int Force a Smush frame redraw every X missed
- frames. Mainly used for Full Throttle action
- sequences. Setting it lower gives more
- priority to screen redraws. Setting it higher
- gives more priority to stylus/keyboard input.
- The default is 30.
+ you prefer better audio/video sync.
Game specific sections (f.e. [monkey2]) - game options
- * landscape int 0: Portrait, 1: Landscape, 2: Inverse Landscape
- You can also use this in the [scummvm] section
- in QVGA Pocket PCs to display the launcher in
- landscape, for example, at startup.
+ * landscape int 0: Portrait, 1: Landscape,
+ 2: Inverse Landscape.
+ You can also use this in the [scummvm]
+ section to display the launcher in landscape
+ for example, at startup.
+ * no_doubletap_rightclick int 1: Turn off the default behavior of
+ simulating a right-click when the screen is
+ double-tapped.
+
[scummvm] section - keys definition
@@ -335,18 +337,18 @@ You can tweak these parameters to customize how the cursor is handled.
consider being repeated.
* repeatX int Number of key repeat events before changing
horizontal cursor behaviour.
- * stepX1 int Horizontal cursor offset value when the key is
- not repeated.
- * stepX2 int Horizontal cursor offset value when the key is
- repeated less than repeatX.
- * stepX3 int Horizontal cursor offset value when the key is
- repeated more than repeatX.
+ * stepX1 int Horizontal cursor offset value when the key
+ is not repeated.
+ * stepX2 int Horizontal cursor offset value when the key
+ is repeated less than repeatX.
+ * stepX3 int Horizontal cursor offset value when the key
+ is repeated more than repeatX.
* repeatY int Number of key repeat events before changing
- vertical cursor behaviour.
+ vertical cursor behavior.
* stepY1 int Vertical cursor offset value when the key is
not repeated.
- * stepY2 int Horizontal cursor offset value when the key is
- repeated less than repeatY.
+ * stepY2 int Horizontal cursor offset value when the key
+ is repeated less than repeatY.
* stepY3 int Vertical cursor offset value when the key is
repeated more than repeatY.
@@ -361,8 +363,8 @@ Game specific questions
I need to press a special key
-----------------------------
-Bring up the virtual keyboard. On Smartphones take a look at the Keyboard action above.
-On Pocket PCs it's easier to double-tap at the top of the screen.
+Bring up the virtual keyboard. On Smartphones take a look at the Keyboard
+action above. On Pocket PCs it's easier to double-tap at the top of the screen.
The panel is obscuring the playfield area
-----------------------------------------
@@ -383,17 +385,18 @@ Bind and use the quit action to quit.
I cannot rotate the screen to landscape/inverse landscape
---------------------------------------------------------
-Depending on the video driver, ScummVM may opt to not provide such functionality.
-In general, when ScummVM starts in normal "portrait" orientation, the device driver
-reports better display characteristics and you should consider launching from portrait.
+Depending on the video driver, ScummVM may opt to not provide such
+functionality. In general, when ScummVM starts in normal "portrait"
+orientation, the device driver reports better display characteristics and you
+should consider launching from portrait.
I'm having problems. Is there diagnostic output available ?
-----------------------------------------------------------
Insert a line in the [scummvm] section of scummvm.ini with the following:
debuglevel=1
-Run ScummVM. When it closes scummvm_stdout.txt and scummvm_stderr.txt files will be
-available at the program directory (see section above).
+Run ScummVM. When it closes scummvm_stdout.txt and scummvm_stderr.txt files
+will be available at the program directory (see section above).
ScummVM crashes and returns to desktop
--------------------------------------
@@ -548,18 +551,19 @@ Use the Multi Function action.
-- AGI engine games --
----------------------
-Do you expect me to play these games on keyboard less devices ?
+Do you expect me to play these games on keyboard-less devices ?
---------------------------------------------------------------
Sure we do :-)
-If you want to get some mileage on your stylus you can use the virtual keyboard.
-There is a very useful alternative though, the AGI engine's predictive input dialog.
-It requires a dictionary to be present. Just tap on the command line or use the
-Multi Function action to bring it up. On Smartphones, when the dialog is shown
-all key mapping is disabled temporarily (including mouse emulation). Input is
-performed either by pressing the phone's numeric keypad keys and dpad enter to
-close the dialog, or by navigating the buttons using the dpad arrows and pressing
-with dpad enter. Check the main Readme file for more information on this.
+If you want to get some mileage on your stylus you can use the virtual
+keyboard. There is a very useful alternative though, the AGI engine's
+predictive input dialog. It requires a dictionary to be present. Just tap on
+the command line or use the Multi Function action to bring it up. On
+Smartphones, when the dialog is shown all key mapping is disabled temporarily
+(including mouse emulation). Input is performed either by pressing the phone's
+numeric keypad keys and dpad enter to close the dialog, or by navigating the
+buttons using the dpad arrows and pressing with dpad enter. Check the main
+Readme file for more information on this.
---------------------------
-- Lure of the Temptress --
@@ -595,8 +599,9 @@ I think I found a bug, ScummVM crashes in ...
See the "Reporting Bugs" section in ScummVM readme.
-If you have a Pocket PC or Handheld PC, be sure to include its resolution (obtained
-on the second dialog displayed on the "About" menu) in your bug report.
+If you have a Pocket PC or Handheld PC, be sure to include its resolution
+(obtained on the second dialog displayed on the "About" menu) in your bug
+report.
If you cannot reproduce this bug on another ScummVM version, you can cross
post your bug report on ScummVM forums.
@@ -619,6 +624,26 @@ http://www.scummvm.org/
Old news follow ...
------------------------------------------------------------------------
+0.11.0:
+- Redesigned 'Free Look' action (Pocket PCs)
+In order to accommodate for the requirements of the lure engine, the
+usage characteristics of the 'Free Look' action have been improved. The
+new behavior is available for use in all engines, but is is *strongly*
+recommended for at least when playing 'Lure of the Temptress'. By using
+the new scheme, when in 'Free Look' mode, it is now possible to enter
+left clicks by clicking a second time near the current location of the
+mouse pointer. Left and Right clicks at the current point location
+are also available by using the respective actions' bound key.
+
+- Reduced optimization build
+The ScummVM executable has grown quite large, prohibiting some devices
+from running memory demanding games (or any games at all). Code
+optimization level has been reduced to offset the growth of the executable.
+Games run slightly slower. This will be addressed before next release.
+
+- Several bugfixes
+
+
0.10.0:
Major improvements have taken place in this version, mostly for behind-
the-scenes stuff. First, we have migrated to GCC for building the Windows
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index 48f157f6ff..f09a483086 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -461,7 +461,7 @@ OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(),
_orientationLandscape(0), _newOrientation(0), _panelInitialized(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),
+ _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)
{
@@ -1059,14 +1059,11 @@ void OSystem_WINCE3::update_game_settings() {
panel->setVisible(false);
_saveToolbarState = true;
-
- // Set Smush Force Redraw rate for Full Throttle
- if (!ConfMan.hasKey("Smush_force_redraw")) {
- ConfMan.setInt("Smush_force_redraw", 30);
- ConfMan.flushToDisk();
- }
}
+ if (ConfMan.hasKey("no_doubletap_rightclick"))
+ _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick");
+
compute_sample_rate();
}
@@ -2340,7 +2337,7 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) {
if (_closeClick && (GetTickCount() - _tapTime < 1000)) {
if (event.mouse.y <= 20 && _panelInitialized) { // top of screen (show panel)
swap_panel_visibility();
- } else { // right click
+ } else if (!_noDoubleTapRMB) { // right click
event.type = Common::EVENT_RBUTTONDOWN;
_rbutton = true;
}
diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h
index 8853c156d8..ece8c9b7b1 100644
--- a/backends/platform/wince/wince-sdl.h
+++ b/backends/platform/wince/wince-sdl.h
@@ -200,6 +200,7 @@ private:
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
diff --git a/backends/saves/compressed/compressed-saves.cpp b/backends/saves/compressed/compressed-saves.cpp
index 150cf5c47d..11cb1689cd 100644
--- a/backends/saves/compressed/compressed-saves.cpp
+++ b/backends/saves/compressed/compressed-saves.cpp
@@ -23,278 +23,14 @@
*
*/
-#include "common/savefile.h"
-#include "common/util.h"
+#include "common/zlib.h"
#include "backends/saves/compressed/compressed-saves.h"
-#if defined(USE_ZLIB)
-#include <zlib.h>
-
-#if ZLIB_VERNUM < 0x1204
-#error Version 1.2.0.4 or newer of zlib is required for this code
-#endif
-
-/**
- * A simple wrapper class which can be used to wrap around an arbitrary
- * other InSaveFile and will then provide on-the-fly decompression support.
- * Assumes the compressed data to be in gzip format.
- */
-class CompressedInSaveFile : public Common::InSaveFile {
-protected:
- enum {
- BUFSIZE = 16384 // 1 << MAX_WBITS
- };
-
- byte _buf[BUFSIZE];
-
- Common::InSaveFile *_wrapped;
- z_stream _stream;
- int _zlibErr;
- uint32 _pos;
- uint32 _origSize;
-
-public:
-
- CompressedInSaveFile(Common::InSaveFile *w) : _wrapped(w) {
- assert(w != 0);
-
- _stream.zalloc = Z_NULL;
- _stream.zfree = Z_NULL;
- _stream.opaque = Z_NULL;
-
- // Verify file header is correct once more
- w->seek(0, SEEK_SET);
- uint16 header = w->readUint16BE();
- assert(header == 0x1F8B ||
- ((header & 0x0F00) == 0x0800 && header % 31 == 0));
-
- if (header == 0x1F8B) {
- // Retrieve the original file size
- w->seek(-4, SEEK_END);
- _origSize = w->readUint32LE();
- } else {
- // Original size not available in zlib format
- _origSize = 0;
- }
- _pos = 0;
- w->seek(0, SEEK_SET);
-
- // Adding 32 to windowBits indicates to zlib that it is supposed to
- // automatically detect whether gzip or zlib headers are used for
- // the compressed file. This feature was added in zlib 1.2.0.4,
- // released 10 August 2003.
- // Note: This is *crucial* for savegame compatibility, do *not* remove!
- _zlibErr = inflateInit2(&_stream, MAX_WBITS + 32);
- if (_zlibErr != Z_OK)
- return;
-
- // Setup input buffer
- _stream.next_in = _buf;
- _stream.avail_in = 0;
- }
-
- ~CompressedInSaveFile() {
- inflateEnd(&_stream);
- delete _wrapped;
- }
-
- bool ioFailed() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); }
- void clearIOFailed() { /* errors here are not recoverable! */ }
-
- uint32 read(void *dataPtr, uint32 dataSize) {
- _stream.next_out = (byte *)dataPtr;
- _stream.avail_out = dataSize;
-
- // Keep going while we get no error
- while (_zlibErr == Z_OK && _stream.avail_out) {
- if (_stream.avail_in == 0 && !_wrapped->eos()) {
- // If we are out of input data: Read more data, if available.
- _stream.next_in = _buf;
- _stream.avail_in = _wrapped->read(_buf, BUFSIZE);
- }
- _zlibErr = inflate(&_stream, Z_NO_FLUSH);
- }
-
- // Update the position counter
- _pos += dataSize - _stream.avail_out;
-
- return dataSize - _stream.avail_out;
- }
-
- bool eos() const {
- return (_zlibErr == Z_STREAM_END);
- //return _pos == _origSize;
- }
- uint32 pos() const {
- return _pos;
- }
- uint32 size() const {
- return _origSize;
- }
- void seek(int32 offset, int whence = SEEK_SET) {
- int32 newPos = 0;
- switch(whence) {
- case SEEK_END:
- newPos = size() - offset;
- break;
- case SEEK_SET:
- newPos = offset;
- break;
- case SEEK_CUR:
- newPos = _pos + offset;
- }
- offset = newPos - _pos;
-
- if (offset < 0)
- error("Backward seeking not supported in compressed savefiles");
-
- // We could implement backward seeking, but it is tricky to do efficiently.
- // A simple solution would be to restart the whole decompression from the
- // start of the file. Or we could decompress the whole file in one go
- // in the constructor, and wrap it into a MemoryReadStream -- but that
- // would be rather wasteful. As long as we don't need it, I'd rather not
- // implement this at all. -- Fingolfin
-
- // Skip the given amount of data (very inefficient if one tries to skip
- // huge amounts of data, but usually client code will only skip a few
- // bytes, so this should be fine.
- byte tmpBuf[1024];
- while (!ioFailed() && offset > 0) {
- offset -= read(tmpBuf, MIN((int32)sizeof(tmpBuf), offset));
- }
- }
-};
-
-/**
- * A simple wrapper class which can be used to wrap around an arbitrary
- * other OutSaveFile and will then provide on-the-fly compression support.
- * The compressed data is written in the gzip format.
- */
-class CompressedOutSaveFile : public Common::OutSaveFile {
-protected:
- enum {
- BUFSIZE = 16384 // 1 << MAX_WBITS
- };
-
- byte _buf[BUFSIZE];
- Common::OutSaveFile *_wrapped;
- z_stream _stream;
- int _zlibErr;
-
- void processData(int flushType) {
- // This function is called by both write() and finalize().
- while (_zlibErr == Z_OK && (_stream.avail_in || flushType == Z_FINISH)) {
- if (_stream.avail_out == 0) {
- if (_wrapped->write(_buf, BUFSIZE) != BUFSIZE) {
- _zlibErr = Z_ERRNO;
- break;
- }
- _stream.next_out = _buf;
- _stream.avail_out = BUFSIZE;
- }
- _zlibErr = deflate(&_stream, flushType);
- }
- }
-
-public:
- CompressedOutSaveFile(Common::OutSaveFile *w) : _wrapped(w) {
- assert(w != 0);
- _stream.zalloc = Z_NULL;
- _stream.zfree = Z_NULL;
- _stream.opaque = Z_NULL;
-
- // Adding 16 to windowBits indicates to zlib that it is supposed to
- // write gzip headers. This feature was added in zlib 1.2.0.4,
- // released 10 August 2003.
- // Note: This is *crucial* for savegame compatibility, do *not* remove!
- _zlibErr = deflateInit2(&_stream,
- Z_DEFAULT_COMPRESSION,
- Z_DEFLATED,
- MAX_WBITS + 16,
- 8,
- Z_DEFAULT_STRATEGY);
- assert(_zlibErr == Z_OK);
-
- _stream.next_out = _buf;
- _stream.avail_out = BUFSIZE;
- _stream.avail_in = 0;
- _stream.next_in = 0;
- }
-
- ~CompressedOutSaveFile() {
- finalize();
- deflateEnd(&_stream);
- delete _wrapped;
- }
-
- bool ioFailed() const {
- return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->ioFailed();
- }
-
- void clearIOFailed() {
- // Note: we don't reset the _zlibErr here, as it is not
- // clear in general ho
- _wrapped->clearIOFailed();
- }
-
- void finalize() {
- if (_zlibErr != Z_OK)
- return;
-
- // Process whatever remaining data there is.
- processData(Z_FINISH);
-
- // Since processData only writes out blocks of size BUFSIZE,
- // we may have to flush some stragglers.
- uint remainder = BUFSIZE - _stream.avail_out;
- if (remainder > 0) {
- if (_wrapped->write(_buf, remainder) != remainder) {
- _zlibErr = Z_ERRNO;
- }
- }
-
- // Finalize the wrapped savefile, too
- _wrapped->finalize();
- }
-
- uint32 write(const void *dataPtr, uint32 dataSize) {
- if (ioFailed())
- return 0;
-
- // Hook in the new data ...
- // Note: We need to make a const_cast here, as zlib is not aware
- // of the const keyword.
- _stream.next_in = const_cast<byte *>((const byte *)dataPtr);
- _stream.avail_in = dataSize;
-
- // ... and flush it to disk
- processData(Z_NO_FLUSH);
-
- return dataSize - _stream.avail_in;
- }
-};
-
-#endif // USE_ZLIB
Common::InSaveFile *wrapInSaveFile(Common::InSaveFile *toBeWrapped) {
-#if defined(USE_ZLIB)
- if (toBeWrapped) {
- uint16 header = toBeWrapped->readUint16BE();
- bool isCompressed = (header == 0x1F8B ||
- ((header & 0x0F00) == 0x0800 &&
- header % 31 == 0));
- toBeWrapped->seek(-2, SEEK_CUR);
- if (isCompressed)
- return new CompressedInSaveFile(toBeWrapped);
- }
-#endif
- return toBeWrapped;
+ return Common::wrapCompressedReadStream(toBeWrapped);
}
Common::OutSaveFile *wrapOutSaveFile(Common::OutSaveFile *toBeWrapped) {
-#if defined(USE_ZLIB)
- if (toBeWrapped)
- return new CompressedOutSaveFile(toBeWrapped);
-#endif
- return toBeWrapped;
+ return Common::wrapCompressedWriteStream(toBeWrapped);
}
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index dc5e8adca7..0cfd265890 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -28,7 +28,6 @@
#include "common/savefile.h"
#include "common/util.h"
#include "common/fs.h"
-#include "common/file.h"
#include "common/config-manager.h"
#include "backends/saves/default/default-saves.h"
#include "backends/saves/compressed/compressed-saves.h"
@@ -37,7 +36,7 @@
#include <string.h>
#include <errno.h>
-#if defined(UNIX) || defined(__SYMBIAN32__)
+#if defined(UNIX)
#include <sys/stat.h>
#endif
@@ -47,8 +46,6 @@
#else
#define DEFAULT_SAVE_PATH ".scummvm"
#endif
-#elif defined(__SYMBIAN32__)
-#define DEFAULT_SAVE_PATH "Savegames"
#endif
DefaultSaveFileManager::DefaultSaveFileManager() {
@@ -64,10 +61,6 @@ DefaultSaveFileManager::DefaultSaveFileManager() {
savePath += "/" DEFAULT_SAVE_PATH;
ConfMan.registerDefault("savepath", savePath);
}
-#elif defined(__SYMBIAN32__)
- savePath = Symbian::GetExecutablePath();
- savePath += DEFAULT_SAVE_PATH "\\";
- ConfMan.registerDefault("savepath", savePath);
#endif
#endif // #ifdef DEFAULT_SAVE_PATH
}
@@ -78,13 +71,13 @@ DefaultSaveFileManager::DefaultSaveFileManager(const Common::String &defaultSave
Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) {
- FilesystemNode savePath(getSavePath());
- FSList savefiles;
+ Common::FilesystemNode savePath(getSavePath());
+ Common::FSList savefiles;
Common::StringList results;
Common::String search(pattern);
if (savePath.lookupFile(savefiles, search, false, true, 0)) {
- for (FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
+ for (Common::FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
results.push_back(file->getName());
}
}
@@ -92,11 +85,11 @@ Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) {
return results;
}
-void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
+void DefaultSaveFileManager::checkPath(const Common::FilesystemNode &dir) {
const Common::String path = dir.getPath();
clearError();
-#if defined(UNIX) || defined(__SYMBIAN32__)
+#if defined(UNIX)
struct stat sb;
// Check whether the dir exists
@@ -108,11 +101,9 @@ void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
case EACCES:
setError(SFM_DIR_ACCESS, "Search or write permission denied: "+path);
break;
-#if !defined(__SYMBIAN32__)
case ELOOP:
setError(SFM_DIR_LOOP, "Too many symbolic links encountered while traversing the path: "+path);
break;
-#endif
case ENAMETOOLONG:
setError(SFM_DIR_NAMETOOLONG, "The path name is too long: "+path);
break;
@@ -130,11 +121,9 @@ void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
case EMLINK:
setError(SFM_DIR_LINKMAX, "The link count of the parent directory would exceed {LINK_MAX}: "+path);
break;
-#if !defined(__SYMBIAN32__)
case ELOOP:
setError(SFM_DIR_LOOP, "Too many symbolic links encountered while traversing the path: "+path);
break;
-#endif
case ENAMETOOLONG:
setError(SFM_DIR_NAMETOOLONG, "The path name is too long: "+path);
break;
@@ -173,11 +162,11 @@ void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename) {
// Ensure that the savepath is valid. If not, generate an appropriate error.
- FilesystemNode savePath(getSavePath());
+ Common::FilesystemNode savePath(getSavePath());
checkPath(savePath);
if (getError() == SFM_NO_ERROR) {
- FilesystemNode file = savePath.getChild(filename);
+ Common::FilesystemNode file = savePath.getChild(filename);
// Open the file for reading
Common::SeekableReadStream *sf = file.openForReading();
@@ -190,11 +179,11 @@ Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename)
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename) {
// Ensure that the savepath is valid. If not, generate an appropriate error.
- FilesystemNode savePath(getSavePath());
+ Common::FilesystemNode savePath(getSavePath());
checkPath(savePath);
if (getError() == SFM_NO_ERROR) {
- FilesystemNode file = savePath.getChild(filename);
+ Common::FilesystemNode file = savePath.getChild(filename);
// Open the file for saving
Common::WriteStream *sf = file.openForWriting();
@@ -208,8 +197,8 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename)
bool DefaultSaveFileManager::removeSavefile(const char *filename) {
clearError();
- FilesystemNode savePath(getSavePath());
- FilesystemNode file = savePath.getChild(filename);
+ Common::FilesystemNode savePath(getSavePath());
+ Common::FilesystemNode file = savePath.getChild(filename);
// TODO: Add new method FilesystemNode::remove()
if (remove(file.getPath().c_str()) != 0) {
diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h
index 97845c4623..c02ce588c2 100644
--- a/backends/saves/default/default-saves.h
+++ b/backends/saves/default/default-saves.h
@@ -28,6 +28,7 @@
#include "common/savefile.h"
#include "common/str.h"
+#include "common/fs.h"
/**
* Provides a default savefile manager implementation for common platforms.
@@ -54,7 +55,7 @@ protected:
* Checks the given path for read access, existence, etc.
* Sets the internal error and error message accordingly.
*/
- void checkPath(const FilesystemNode &dir);
+ void checkPath(const Common::FilesystemNode &dir);
};
#endif
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index f8ca8a90cd..410777209f 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -56,6 +56,7 @@ static const char HELP_STRING[] =
" -h, --help Display a brief help text and exit\n"
" -z, --list-games Display list of supported games and exit\n"
" -t, --list-targets Display list of configured targets and exit\n"
+ " --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n"
"\n"
" -c, --config=CONFIG Use alternate configuration file\n"
" -p, --path=PATH Path to where the game is installed\n"
@@ -364,7 +365,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_OPTION('p', "path")
- FilesystemNode path(option);
+ Common::FilesystemNode path(option);
if (!path.exists()) {
usage("Non-existent game path '%s'", option);
} else if (!path.isReadable()) {
@@ -407,7 +408,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("soundfont")
- FilesystemNode path(option);
+ Common::FilesystemNode path(option);
if (!path.exists()) {
usage("Non-existent soundfont path '%s'", option);
} else if (!path.isReadable()) {
@@ -437,7 +438,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("savepath")
- FilesystemNode path(option);
+ Common::FilesystemNode path(option);
if (!path.exists()) {
usage("Non-existent savegames path '%s'", option);
} else if (!path.isWritable()) {
@@ -446,7 +447,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("extrapath")
- FilesystemNode path(option);
+ Common::FilesystemNode path(option);
if (!path.exists()) {
usage("Non-existent extra path '%s'", option);
} else if (!path.isReadable()) {
@@ -464,7 +465,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("themepath")
- FilesystemNode path(option);
+ Common::FilesystemNode path(option);
if (!path.exists()) {
usage("Non-existent theme path '%s'", option);
} else if (!path.isReadable()) {
@@ -622,9 +623,9 @@ static void runDetectorTest() {
gameid = name;
}
- FilesystemNode dir(path);
- FSList files;
- if (!dir.getChildren(files, FilesystemNode::kListAll)) {
+ Common::FilesystemNode dir(path);
+ Common::FSList files;
+ if (!dir.getChildren(files, Common::FilesystemNode::kListAll)) {
printf(" ... invalid path, skipping\n");
continue;
}
@@ -735,7 +736,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings) {
if (!settings.contains("savepath")) {
const char *dir = getenv("SCUMMVM_SAVEPATH");
if (dir && *dir && strlen(dir) < MAXPATHLEN) {
- FilesystemNode saveDir(dir);
+ Common::FilesystemNode saveDir(dir);
if (!saveDir.exists()) {
warning("Non-existent SCUMMVM_SAVEPATH save path. It will be ignored.");
} else if (!saveDir.isWritable()) {
diff --git a/base/main.cpp b/base/main.cpp
index 031e8fd522..e1b65aebbd 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -38,6 +38,7 @@
#include "base/version.h"
#include "common/config-manager.h"
+#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/system.h"
@@ -62,6 +63,11 @@ static bool launcherDialog(OSystem &system) {
system.setGraphicsMode(ConfMan.get("gfx_mode").c_str());
system.initSize(320, 200);
+
+ if (ConfMan.hasKey("aspect_ratio"))
+ system.setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio"));
+ if (ConfMan.hasKey("fullscreen"))
+ system.setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
system.endGFXTransaction();
// Set initial window caption
@@ -156,8 +162,16 @@ static int runGame(const EnginePlugin *plugin, OSystem &system, const Common::St
system.setWindowCaption(caption.c_str());
}
+ // FIXME: at this moment, game path handling is being discussed in the mailing list,
+ // while Common::File is being reworked under the hood. After commit 34444, which
+ // changed the implementation of Common::File (specifically removing usage of fopen
+ // and fOpenNoCase, which implicitly supported backslashes in file names), some games
+ // stopped working. Example of this are the HE games which use subdirectories: Kirben
+ // found this issue on lost-win-demo at first. Thus, in commit 34450, searching the
+ // game path was made recursive as a temporary fix/workaround.
+
// Add the game path to the directory search list
- Common::File::addDefaultDirectory(path);
+ Common::File::addDefaultDirectoryRecursive(path);
// Add extrapath (if any) to the directory search list
if (ConfMan.hasKey("extrapath"))
@@ -202,7 +216,8 @@ static int runGame(const EnginePlugin *plugin, OSystem &system, const Common::St
// Reset the file/directory mappings
Common::File::resetDefaultDirectories();
- return 0;
+ // Return result (== 0 means no error)
+ return result;
}
@@ -263,13 +278,13 @@ extern "C" int scummvm_main(int argc, char *argv[]) {
// Unless a game was specified, show the launcher dialog
if (0 == ConfMan.getActiveDomain()) {
- launcherDialog(system);
-
// Discard any command line options. Those that affect the graphics
// mode etc. already have should have been handled by the backend at
// this point. And the others (like bootparam etc.) should not
// blindly be passed to the first game launched from the launcher.
ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear();
+
+ launcherDialog(system);
}
// FIXME: We're now looping the launcher. This, of course, doesn't
@@ -285,12 +300,19 @@ extern "C" int scummvm_main(int argc, char *argv[]) {
// Try to run the game
int result = runGame(plugin, system, specialDebug);
- // TODO: We should keep running if starting the selected game failed
- // (so instead of just quitting, show a nice error dialog to the
- // user and let him pick another game).
- if (result == 0)
+
+ // Did an error occur ?
+ if (result != 0) {
+ // TODO: Show an informative error dialog if starting the selected game failed.
+ }
+
+ // Quit unless an error occurred, or Return to launcher was requested
+ if (result == 0 && !g_system->getEventManager()->shouldRTL())
break;
+ // Reset RTL flag in case we want to load another engine
+ g_system->getEventManager()->resetRTL();
+
// Discard any command line options. It's unlikely that the user
// wanted to apply them to *all* games ever launched.
ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear();
diff --git a/base/module.mk b/base/module.mk
index dd89c5fb2d..f12a710920 100644
--- a/base/module.mk
+++ b/base/module.mk
@@ -3,7 +3,6 @@ MODULE := base
MODULE_OBJS := \
main.o \
commandLine.o \
- game.o \
plugins.o \
version.o
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 216c6ef1af..7b372587a1 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -29,6 +29,7 @@
#ifdef DYNAMIC_MODULES
#include "common/config-manager.h"
+#include "common/fs.h"
#endif
// Plugin versioning
@@ -157,9 +158,12 @@ public:
#if defined(UNIX) && defined(USE_ALSA)
LINK_PLUGIN(ALSA)
#endif
- #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__)
+ #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
LINK_PLUGIN(SEQ)
#endif
+ #if defined(__MINT__)
+ LINK_PLUGIN(STMIDI)
+ #endif
#if defined(IRIX)
LINK_PLUGIN(DMEDIA)
#endif
@@ -200,11 +204,11 @@ PluginList FilePluginProvider::getPlugins() {
PluginList pl;
// Prepare the list of directories to search
- FSList pluginDirs;
+ Common::FSList pluginDirs;
// Add the default directories
- pluginDirs.push_back(FilesystemNode("."));
- pluginDirs.push_back(FilesystemNode("plugins"));
+ pluginDirs.push_back(Common::FilesystemNode("."));
+ pluginDirs.push_back(Common::FilesystemNode("plugins"));
// Add the provider's custom directories
addCustomDirectories(pluginDirs);
@@ -212,21 +216,21 @@ PluginList FilePluginProvider::getPlugins() {
// Add the user specified directory
Common::String pluginsPath(ConfMan.get("pluginspath"));
if (!pluginsPath.empty())
- pluginDirs.push_back(FilesystemNode(pluginsPath));
+ pluginDirs.push_back(Common::FilesystemNode(pluginsPath));
- FSList::const_iterator dir;
+ Common::FSList::const_iterator dir;
for (dir = pluginDirs.begin(); dir != pluginDirs.end(); dir++) {
// Load all plugins.
// Scan for all plugins in this directory
- FSList files;
- if (!dir->getChildren(files, FilesystemNode::kListFilesOnly)) {
+ Common::FSList files;
+ if (!dir->getChildren(files, Common::FilesystemNode::kListFilesOnly)) {
debug(1, "Couldn't open plugin directory '%s'", dir->getPath().c_str());
continue;
} else {
debug(1, "Reading plugins from plugin directory '%s'", dir->getPath().c_str());
}
- for (FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
+ for (Common::FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
if (isPluginFilename(i->getName())) {
pl.push_back(createPlugin(i->getPath()));
}
@@ -252,9 +256,9 @@ bool FilePluginProvider::isPluginFilename(const Common::String &filename) const
return true;
}
-void FilePluginProvider::addCustomDirectories(FSList &dirs) const {
+void FilePluginProvider::addCustomDirectories(Common::FSList &dirs) const {
#ifdef PLUGIN_DIRECTORY
- dirs.push_back(FilesystemNode(PLUGIN_DIRECTORY));
+ dirs.push_back(Common::FilesystemNode(PLUGIN_DIRECTORY));
#endif
}
@@ -376,7 +380,7 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Eng
return result;
}
-GameList EngineManager::detectGames(const FSList &fslist) const {
+GameList EngineManager::detectGames(const Common::FSList &fslist) const {
GameList candidates;
const EnginePlugin::List &plugins = getPlugins();
diff --git a/base/plugins.h b/base/plugins.h
index 02116f6433..90c4469e4d 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -30,9 +30,10 @@
#include "common/singleton.h"
#include "common/util.h"
-#ifdef DYNAMIC_MODULES
-#include "common/fs.h"
-#endif
+namespace Common {
+ class FSList;
+}
+
/**
* @page pagePlugins An overview of the ScummVM plugin system
@@ -258,7 +259,7 @@ protected:
* @param dirs the reference to the list of directories to be used when
* searching for plugins.
*/
- virtual void addCustomDirectories(FSList &dirs) const;
+ virtual void addCustomDirectories(Common::FSList &dirs) const;
};
#endif // DYNAMIC_MODULES
diff --git a/base/version.cpp b/base/version.cpp
index 8de96d0b78..eabafecc30 100644
--- a/base/version.cpp
+++ b/base/version.cpp
@@ -62,7 +62,12 @@ const char *gScummVMVersionDate = SCUMMVM_VERSION " (" __DATE__ " " __TIME__ ")"
const char *gScummVMFullVersion = "ScummVM " SCUMMVM_VERSION " (" __DATE__ " " __TIME__ ")";
const char *gScummVMFeatures = ""
#ifdef USE_TREMOR
+#ifdef USE_TREMOLO
+ // libTremolo is used on WinCE for better ogg performance
+ "Tremolo "
+#else
"Tremor "
+#endif
#else
#ifdef USE_VORBIS
"Vorbis "
@@ -92,11 +97,5 @@ const char *gScummVMFeatures = ""
#ifdef USE_FLUIDSYNTH
"FluidSynth "
#endif
-
-#ifdef __SYMBIAN32__
-// we want a list of compiled in engines visible in the program,
-// because we also release special builds with only one engine
-#include "backends/platform/symbian/src/main_features.inl"
-#endif
;
diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp
index 522b24163e..1b0db4755a 100644
--- a/common/advancedDetector.cpp
+++ b/common/advancedDetector.cpp
@@ -82,12 +82,12 @@ static void upgradeTargetIfNecessary(const Common::ADParams &params) {
if (params.obsoleteList == 0)
return;
- const char *gameid = ConfMan.get("gameid").c_str();
+ String gameid = ConfMan.get("gameid");
for (const Common::ADObsoleteGameID *o = params.obsoleteList; o->from; ++o) {
- if (!scumm_stricmp(gameid, o->from)) {
+ if (gameid.equalsIgnoreCase(o->from)) {
gameid = o->to;
- ConfMan.set("gameid", o->to);
+ ConfMan.set("gameid", gameid);
if (o->platform != Common::kPlatformUnknown)
ConfMan.set("platform", Common::getPlatformCode(o->platform));
diff --git a/common/advancedDetector.h b/common/advancedDetector.h
index 40f5823d1b..b72b9fbfc4 100644
--- a/common/advancedDetector.h
+++ b/common/advancedDetector.h
@@ -28,8 +28,6 @@
#include "common/fs.h"
#include "common/error.h"
-#include "base/game.h" // For PlainGameDescriptor and GameList
-
#include "engines/metaengine.h"
namespace Common {
diff --git a/common/archive.cpp b/common/archive.cpp
new file mode 100644
index 0000000000..7e17fdca32
--- /dev/null
+++ b/common/archive.cpp
@@ -0,0 +1,344 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/archive.h"
+#include "common/fs.h"
+#include "common/util.h"
+
+namespace Common {
+
+
+int Archive::matchPattern(StringList &list, const String &pattern) {
+ // Get all "names" (TODO: "files" ?)
+ StringList allNames;
+ getAllNames(allNames);
+
+ int matches = 0;
+
+ // need to match lowercase key
+ String lowercasePattern = pattern;
+ lowercasePattern.toLowercase();
+
+ StringList::iterator it = allNames.begin();
+ for ( ; it != allNames.end(); it++) {
+ if (it->matchString(lowercasePattern)) {
+ list.push_back(*it);
+ matches++;
+ }
+ }
+
+ return matches;
+}
+
+
+FSDirectory::FSDirectory(const FilesystemNode &node, int depth)
+ : _node(node), _cached(false), _depth(depth) {
+}
+
+FSDirectory::FSDirectory(const String &name, int depth)
+ : _node(name), _cached(false), _depth(depth) {
+}
+
+FSDirectory::~FSDirectory() {
+}
+
+FilesystemNode FSDirectory::getFSNode() const {
+ return _node;
+}
+
+FilesystemNode FSDirectory::lookupCache(NodeCache &cache, const String &name) {
+ // make caching as lazy as possible
+ if (!name.empty()) {
+ if (!_cached) {
+ cacheDirectoryRecursive(_node, _depth, "");
+ _cached = true;
+ }
+
+ if (cache.contains(name))
+ return cache[name];
+ }
+
+ return FilesystemNode();
+}
+
+bool FSDirectory::hasFile(const String &name) {
+ if (name.empty() || !_node.isDirectory()) {
+ return false;
+ }
+
+ FilesystemNode node = lookupCache(_fileCache, name);
+ return node.exists();
+}
+
+SeekableReadStream *FSDirectory::openFile(const String &name) {
+ if (name.empty() || !_node.isDirectory()) {
+ return 0;
+ }
+
+ FilesystemNode node = lookupCache(_fileCache, name);
+
+ if (!node.exists()) {
+ warning("FSDirectory::openFile: FilesystemNode does not exist");
+ return 0;
+ } else if (node.isDirectory()) {
+ warning("FSDirectory::openFile: FilesystemNode is a directory");
+ return 0;
+ }
+
+ SeekableReadStream *stream = node.openForReading();
+ if (!stream) {
+ warning("FSDirectory::openFile: Can't create stream for file '%s'", name.c_str());
+ }
+
+ return stream;
+}
+
+FSDirectory *FSDirectory::getSubDirectory(const String &name) {
+ if (name.empty() || !_node.isDirectory()) {
+ return 0;
+ }
+
+ FilesystemNode node = lookupCache(_subDirCache, name);
+ return new FSDirectory(node);
+}
+
+void FSDirectory::cacheDirectoryRecursive(FilesystemNode node, int depth, const String& prefix) {
+ if (depth <= 0) {
+ return;
+ }
+
+ FSList list;
+ node.getChildren(list, FilesystemNode::kListAll, false);
+
+ FSList::iterator it = list.begin();
+ for ( ; it != list.end(); it++) {
+ String name = prefix + (*it).getName();
+
+ // don't touch name as it might be used for warning messages
+ String lowercaseName = name;
+ lowercaseName.toLowercase();
+
+ // since the hashmap is case insensitive, we need to check for clashes when caching
+ if ((*it).isDirectory()) {
+ if (_subDirCache.contains(lowercaseName)) {
+ warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str());
+ } else {
+ cacheDirectoryRecursive(*it, depth - 1, lowercaseName + "/");
+ _subDirCache[lowercaseName] = *it;
+ }
+ } else {
+ if (_fileCache.contains(lowercaseName)) {
+ warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", name.c_str());
+ } else {
+ _fileCache[lowercaseName] = *it;
+ }
+ }
+ }
+
+}
+
+int FSDirectory::matchPattern(StringList &list, const String &pattern) {
+ if (!_node.isDirectory())
+ return 0;
+
+ // Cache dir data
+ if (!_cached) {
+ cacheDirectoryRecursive(_node, _depth, "");
+ _cached = true;
+ }
+
+ // Small optimization: Ensure the StringList has to grow at most once
+ list.reserve(list.size() + _fileCache.size());
+
+ // Add all filenames from our cache
+ NodeCache::iterator it = _fileCache.begin();
+ for ( ; it != _fileCache.end(); it++) {
+ if (it->_key.matchString(pattern))
+ list.push_back(it->_key);
+ }
+
+ return _fileCache.size();
+}
+
+int FSDirectory::getAllNames(StringList &list) {
+ if (!_node.isDirectory())
+ return 0;
+
+ // Cache dir data
+ if (!_cached) {
+ cacheDirectoryRecursive(_node, _depth, "");
+ _cached = true;
+ }
+
+ // Small optimization: Ensure the StringList has to grow at most once
+ list.reserve(list.size() + _fileCache.size());
+
+ // Add all filenames from our cache
+ NodeCache::iterator it = _fileCache.begin();
+ for ( ; it != _fileCache.end(); it++) {
+ list.push_back((*it)._key);
+ }
+
+ return _fileCache.size();
+}
+
+
+
+SearchSet::ArchiveList::iterator SearchSet::find(const String &name) const {
+ ArchiveList::iterator it = _list.begin();
+ for ( ; it != _list.end(); it++) {
+ if ((*it)._name == name) {
+ break;
+ }
+ }
+ return it;
+}
+
+/*
+ Keep the nodes sorted according to descending priorities.
+ In case two or node nodes have the same priority, insertion
+ order prevails.
+*/
+void SearchSet::insert(const Node &node) {
+ ArchiveList::iterator it = _list.begin();
+ for ( ; it != _list.end(); it++) {
+ if ((*it)._priority < node._priority) {
+ break;
+ }
+ }
+ _list.insert(it, node);
+}
+
+void SearchSet::add(const String& name, ArchivePtr archive, uint priority) {
+ if (find(name) == _list.end()) {
+ Node node = { priority, name, archive };
+ insert(node);
+ } else {
+ warning("SearchSet::add: archive '%s' already present", name.c_str());
+ }
+
+}
+
+void SearchSet::remove(const String& name) {
+ ArchiveList::iterator it = find(name);
+ if (it != _list.end()) {
+ _list.erase(it);
+ }
+}
+
+bool SearchSet::hasArchive(const String &name) const {
+ return (find(name) != _list.end());
+}
+
+void SearchSet::clear() {
+ _list.clear();
+}
+
+void SearchSet::setPriority(const String& name, uint priority) {
+ ArchiveList::iterator it = find(name);
+ if (it == _list.end()) {
+ warning("SearchSet::setPriority: archive '%s' is not present", name.c_str());
+ return;
+ }
+
+ if (priority == (*it)._priority) {
+ return;
+ }
+
+ Node node(*it);
+ _list.erase(it);
+ node._priority = priority;
+ insert(node);
+}
+
+bool SearchSet::hasFile(const String &name) {
+ if (name.empty()) {
+ return false;
+ }
+
+ ArchiveList::iterator it = _list.begin();
+ for ( ; it != _list.end(); it++) {
+ if ((*it)._arc->hasFile(name)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int SearchSet::matchPattern(StringList &list, const String &pattern) {
+ int matches = 0;
+
+ ArchiveList::iterator it = _list.begin();
+ for ( ; it != _list.end(); it++) {
+ matches += (*it)._arc->matchPattern(list, pattern);
+ }
+
+ return matches;
+}
+
+int SearchSet::getAllNames(StringList &list) {
+ int matches = 0;
+
+ ArchiveList::iterator it = _list.begin();
+ for ( ; it != _list.end(); it++) {
+ matches += (*it)._arc->getAllNames(list);
+ }
+
+ return matches;
+}
+
+SeekableReadStream *SearchSet::openFile(const String &name) {
+ if (name.empty()) {
+ return 0;
+ }
+
+ ArchiveList::iterator it = _list.begin();
+ for ( ; it != _list.end(); it++) {
+ if ((*it)._arc->hasFile(name)) {
+ return (*it)._arc->openFile(name);
+ }
+ }
+
+ return 0;
+}
+
+
+DECLARE_SINGLETON(SearchManager);
+
+void SearchManager::addArchive(const String &name, ArchivePtr archive) {
+ add(name, archive);
+}
+
+void SearchManager::addDirectory(const String &name, const String &directory) {
+ addDirectoryRecursive(name, 1);
+}
+
+void SearchManager::addDirectoryRecursive(const String &name, const String &directory, int depth) {
+ add(name, SharedPtr<FSDirectory>(new FSDirectory(directory, depth)));
+}
+
+
+} // namespace Common
diff --git a/common/archive.h b/common/archive.h
new file mode 100644
index 0000000000..89ea6a5ce2
--- /dev/null
+++ b/common/archive.h
@@ -0,0 +1,231 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_ARCHIVES_H
+#define COMMON_ARCHIVES_H
+
+#include "common/fs.h"
+#include "common/str.h"
+#include "common/hash-str.h"
+#include "common/list.h"
+#include "common/ptr.h"
+#include "common/singleton.h"
+#include "common/stream.h"
+
+namespace Common {
+
+/**
+ * FilePtr is a convenient way to keep track of a SeekableReadStream without
+ * having to worry about releasing its memory.
+ */
+typedef SharedPtr<SeekableReadStream> FilePtr;
+
+/**
+ * Archive allows searches of (file)names into an arbitrary container.
+ * It also supports opening a file and returning an usable input stream.
+ */
+class Archive {
+public:
+ virtual ~Archive() { }
+
+ /**
+ * Check if a name is present in the Archive. Patterns are not allowed,
+ * as this is meant to be a quick File::exists() replacement.
+ */
+ virtual bool hasFile(const String &name) = 0;
+
+ /**
+ * Add all the names present in the Archive which match pattern to
+ * list. Returned names can be used as parameters to openFile.
+ * Must not remove elements from the list.
+ *
+ * @return the number of names added to list
+ */
+ virtual int matchPattern(StringList &list, const String &pattern);
+
+ /**
+ * Add all the names present in the Archive to list. Returned
+ * names can be used as parameters to openFile.
+ * Must not remove elements from the list.
+ *
+ * @return the number of names added to list
+ */
+ virtual int getAllNames(StringList &list) = 0;
+
+ /**
+ * Create a stream bound to a file in the archive.
+ * @return the newly created input stream
+ */
+ virtual SeekableReadStream *openFile(const String &name) = 0;
+};
+
+
+typedef SharedPtr<Archive> ArchivePtr;
+
+
+/**
+ * FSDirectory models a directory tree from the filesystem and allows users
+ * to access it through the Archive interface. FSDirectory can represent a
+ * single directory, or a tree with specified depth, rooted in a 'base'
+ * directory.
+ * Searching is case-insensitive, as the main intended goal is supporting
+ * retrieval of game data. First case-insensitive match is returned when
+ * searching, thus making FSDirectory heavily dependant on the underlying
+ * FilesystemNode implementation.
+ */
+class FSDirectory : public Archive {
+ FilesystemNode _node;
+
+ // Caches are case insensitive, clashes are dealt with when creating
+ // Key is stored in lowercase.
+ typedef HashMap<String, FilesystemNode, IgnoreCase_Hash, IgnoreCase_EqualTo> NodeCache;
+ NodeCache _fileCache, _subDirCache;
+
+ // look for a match
+ FilesystemNode lookupCache(NodeCache &cache, const String &name);
+
+ // cache management
+ void cacheDirectoryRecursive(FilesystemNode node, int depth, const String& prefix);
+ bool _cached;
+ int _depth;
+
+public:
+ /**
+ * Create a FSDirectory representing a tree with the specified depth. Will result in an
+ * unbound FSDirectory if name is not found on the filesystem or is not a directory.
+ */
+ FSDirectory(const String &name, int depth = 1);
+
+ /**
+ * Create a FSDirectory representing a tree with the specified depth. Will result in an
+ * unbound FSDirectory if node does not exist or is not a directory.
+ */
+ FSDirectory(const FilesystemNode &node, int depth = 1);
+
+ virtual ~FSDirectory();
+
+ /**
+ * This return the underlying FSNode of the FSDirectory.
+ */
+ FilesystemNode getFSNode() const;
+
+ /**
+ * Create a new FSDirectory pointing to a sub directory of the instance.
+ * @return a new FSDirectory instance
+ */
+ FSDirectory *getSubDirectory(const String &name);
+
+ virtual bool hasFile(const String &name);
+ virtual int matchPattern(StringList &list, const String &pattern);
+ virtual int getAllNames(StringList &list);
+ virtual SeekableReadStream *openFile(const String &name);
+};
+
+
+/**
+ * SearchSet enables access to a group of Archives through the Archive interface.
+ * Its intended usage is a situation in which there are no name clashes among names in the
+ * contained Archives, hence the simplistic policy of always looking for the first
+ * match. SearchSet *DOES* guarantee that searches are performed in *DESCENDING*
+ * priority order. In case of conflicting priorities, insertion order prevails.
+ */
+class SearchSet : public Archive {
+ struct Node {
+ uint _priority;
+ String _name;
+ ArchivePtr _arc;
+ };
+ typedef List<Node> ArchiveList;
+ ArchiveList _list;
+
+ ArchiveList::iterator find(const String &name) const;
+
+ // Add an archive keeping the list sorted by ascending priorities.
+ void insert(const Node& node);
+
+public:
+ /**
+ * Add a new archive to the searchable set.
+ */
+ void add(const String& name, ArchivePtr archive, uint priority = 0);
+
+ /**
+ * Remove an archive from the searchable set.
+ */
+ void remove(const String& name);
+
+ /**
+ * Check if a given archive name is already present.
+ */
+ bool hasArchive(const String &name) const;
+
+ /**
+ * Empties the searchable set.
+ */
+ void clear();
+
+ /**
+ * Change the order of searches.
+ */
+ void setPriority(const String& name, uint priority);
+
+ virtual bool hasFile(const String &name);
+ virtual int matchPattern(StringList &list, const String &pattern);
+ virtual int getAllNames(StringList &list);
+
+ /**
+ * Implements openFile from Archive base class. The current policy is
+ * opening the first file encountered that matches the name.
+ */
+ virtual SeekableReadStream *openFile(const String &name);
+};
+
+
+class SearchManager : public Singleton<SearchManager>, public SearchSet {
+public:
+ /**
+ * Add an existing Archive. This is meant to support searching in system-specific
+ * archives, namely the MACOSX/IPHONE bundles.
+ */
+ void addArchive(const String &name, ArchivePtr archive);
+
+ /**
+ * Create and add a FSDirectory by name
+ */
+ void addDirectory(const String &name, const String &directory);
+
+ /**
+ * Create and add a FSDirectory and its subdirectories by name
+ */
+ void addDirectoryRecursive(const String &name, const String &directory, int depth = 4);
+
+};
+
+/** Shortcut for accessing the search manager. */
+#define SearchMan Common::SearchManager::instance()
+
+} // namespace Common
+
+#endif
diff --git a/common/array.h b/common/array.h
index 854ce5b91d..693c024d11 100644
--- a/common/array.h
+++ b/common/array.h
@@ -35,7 +35,7 @@ class Array {
protected:
uint _capacity;
uint _size;
- T *_data;
+ T *_storage;
public:
typedef T *iterator;
@@ -44,41 +44,41 @@ public:
typedef T value_type;
public:
- Array() : _capacity(0), _size(0), _data(0) {}
- Array(const Array<T> &array) : _capacity(0), _size(0), _data(0) {
+ Array() : _capacity(0), _size(0), _storage(0) {}
+ Array(const Array<T> &array) : _capacity(0), _size(0), _storage(0) {
_size = array._size;
_capacity = _size + 32;
- _data = new T[_capacity];
- copy(array._data, array._data + _size, _data);
+ _storage = new T[_capacity];
+ copy(array._storage, array._storage + _size, _storage);
}
~Array() {
- delete[] _data;
+ delete[] _storage;
}
void push_back(const T &element) {
ensureCapacity(_size + 1);
- _data[_size++] = element;
+ _storage[_size++] = element;
}
void push_back(const Array<T> &array) {
ensureCapacity(_size + array._size);
- copy(array._data, array._data + array._size, _data + _size);
+ copy(array._storage, array._storage + array._size, _storage + _size);
_size += array._size;
}
void insert_at(int idx, const T &element) {
assert(idx >= 0 && (uint)idx <= _size);
ensureCapacity(_size + 1);
- copy_backward(_data + idx, _data + _size, _data + _size + 1);
- _data[idx] = element;
+ copy_backward(_storage + idx, _storage + _size, _storage + _size + 1);
+ _storage[idx] = element;
_size++;
}
T remove_at(int idx) {
assert(idx >= 0 && (uint)idx < _size);
- T tmp = _data[idx];
- copy(_data + idx + 1, _data + _size, _data + idx);
+ T tmp = _storage[idx];
+ copy(_storage + idx + 1, _storage + _size, _storage + idx);
_size--;
return tmp;
}
@@ -87,23 +87,23 @@ public:
T& operator[](int idx) {
assert(idx >= 0 && (uint)idx < _size);
- return _data[idx];
+ return _storage[idx];
}
const T& operator[](int idx) const {
assert(idx >= 0 && (uint)idx < _size);
- return _data[idx];
+ return _storage[idx];
}
Array<T>& operator=(const Array<T> &array) {
if (this == &array)
return *this;
- delete[] _data;
+ delete[] _storage;
_size = array._size;
_capacity = _size + 32;
- _data = new T[_capacity];
- copy(array._data, array._data + _size, _data);
+ _storage = new T[_capacity];
+ copy(array._storage, array._storage + _size, _storage);
return *this;
}
@@ -113,8 +113,8 @@ public:
}
void clear() {
- delete[] _data;
- _data = 0;
+ delete[] _storage;
+ _storage = 0;
_size = 0;
_capacity = 0;
}
@@ -125,33 +125,33 @@ public:
iterator begin() {
- return _data;
+ return _storage;
}
iterator end() {
- return _data + _size;
+ return _storage + _size;
}
const_iterator begin() const {
- return _data;
+ return _storage;
}
const_iterator end() const {
- return _data + _size;
+ return _storage + _size;
}
void reserve(uint newCapacity) {
if (newCapacity <= _capacity)
return;
- T *old_data = _data;
+ T *old_storage = _storage;
_capacity = newCapacity;
- _data = new T[newCapacity];
+ _storage = new T[newCapacity];
- if (old_data) {
+ if (old_storage) {
// Copy old data
- copy(old_data, old_data + _size, _data);
- delete[] old_data;
+ copy(old_storage, old_storage + _size, _storage);
+ delete[] old_storage;
}
}
@@ -159,14 +159,14 @@ public:
if (newSize == _size)
return;
- T *old_data = _data;
+ T *old_storage = _storage;
_capacity = newSize;
- _data = new T[newSize];
- if (old_data) {
+ _storage = new T[newSize];
+ if (old_storage) {
// Copy old data
int cnt = (_size < newSize ? _size : newSize);
- copy(old_data, old_data + cnt, _data);
- delete[] old_data;
+ copy(old_storage, old_storage + cnt, _storage);
+ delete[] old_storage;
}
_size = newSize;
}
diff --git a/common/config-file.cpp b/common/config-file.cpp
index 9f54c9ddde..c3764a02da 100644
--- a/common/config-file.cpp
+++ b/common/config-file.cpp
@@ -77,7 +77,6 @@ bool ConfigFile::loadFromSaveFile(const char *filename) {
}
bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
- char buf[MAXLINELEN];
Section section;
KeyValue kv;
String comment;
@@ -86,18 +85,21 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
// TODO: Detect if a section occurs multiple times (or likewise, if
// a key occurs multiple times inside one section).
- while (!stream.eos()) {
+ while (!stream.eos() && !stream.ioFailed()) {
lineno++;
- if (!stream.readLine(buf, MAXLINELEN))
- break;
- if (buf[0] == '#') {
+ // Read a line
+ String line = stream.readLine();
+
+ if (line.size() == 0) {
+ // Do nothing
+ } else if (line[0] == '#') {
// Accumulate comments here. Once we encounter either the start
// of a new section, or a key-value-pair, we associate the value
// of the 'comment' variable with that entity.
- comment += buf;
+ comment += line;
comment += "\n";
- } else if (buf[0] == '(') {
+ } else if (line[0] == '(') {
// HACK: The following is a hack added by Kirben to support the
// "map.ini" used in the HE SCUMM game "SPY Fox in Hold the Mustard".
//
@@ -105,11 +107,11 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
// but the current design of this class doesn't allow to do that
// in a nice fashion (a "isMustard" parameter is *not* a nice
// solution).
- comment += buf;
+ comment += line;
comment += "\n";
- } else if (buf[0] == '[') {
+ } else if (line[0] == '[') {
// It's a new section which begins here.
- char *p = buf + 1;
+ const char *p = line.c_str() + 1;
// Get the section name, and check whether it's valid (that
// is, verify that it only consists of alphanumerics,
// dashes and underscores).
@@ -121,23 +123,25 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
else if (*p != ']')
error("ConfigFile::loadFromStream: Invalid character '%c' occured in section name in line %d", *p, lineno);
- *p = 0;
-
// Previous section is finished now, store it.
if (!section.name.empty())
_sections.push_back(section);
- section.name = buf + 1;
+ section.name = String(line.c_str() + 1, p);
section.keys.clear();
section.comment = comment;
comment.clear();
assert(isValidName(section.name));
} else {
- // Skip leading & trailing whitespaces
- char *t = rtrim(ltrim(buf));
-
- // Skip empty lines
+ // This line should be a line with a 'key=value' pair, or an empty one.
+
+ // Skip leading whitespaces
+ const char *t = line.c_str();
+ while (isspace(*t))
+ t++;
+
+ // Skip empty lines / lines with only whitespace
if (*t == 0)
continue;
@@ -146,14 +150,20 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno);
}
- // Split string at '=' into 'key' and 'value'.
- char *p = strchr(t, '=');
+ // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter.
+ const char *p = strchr(t, '=');
if (!p)
- error("ConfigFile::loadFromStream: Junk found in line line %d: '%s'", lineno, t);
- *p = 0;
+ error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
+
+ // Extract the key/value pair
+ kv.key = String(t, p);
+ kv.value = String(p + 1);
+
+ // Trim of spaces
+ kv.key.trim();
+ kv.value.trim();
- kv.key = rtrim(t);
- kv.value = ltrim(p + 1);
+ // Store comment
kv.comment = comment;
comment.clear();
@@ -225,7 +235,7 @@ bool ConfigFile::saveToStream(WriteStream &stream) {
void ConfigFile::removeSection(const String &section) {
assert(isValidName(section));
for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
- if (!scumm_stricmp(section.c_str(), i->name.c_str())) {
+ if (section.equalsIgnoreCase(i->name)) {
_sections.erase(i);
return;
}
@@ -318,7 +328,7 @@ const ConfigFile::SectionKeyList ConfigFile::getKeys(const String &section) cons
ConfigFile::Section *ConfigFile::getSection(const String &section) {
for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
- if (!scumm_stricmp(section.c_str(), i->name.c_str())) {
+ if (section.equalsIgnoreCase(i->name)) {
return &(*i);
}
}
@@ -327,7 +337,7 @@ ConfigFile::Section *ConfigFile::getSection(const String &section) {
const ConfigFile::Section *ConfigFile::getSection(const String &section) const {
for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) {
- if (!scumm_stricmp(section.c_str(), i->name.c_str())) {
+ if (section.equalsIgnoreCase(i->name)) {
return &(*i);
}
}
@@ -340,7 +350,7 @@ bool ConfigFile::Section::hasKey(const String &key) const {
const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const {
for (List<KeyValue>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
- if (!scumm_stricmp(key.c_str(), i->key.c_str())) {
+ if (key.equalsIgnoreCase(i->key)) {
return &(*i);
}
}
@@ -349,7 +359,7 @@ const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const
void ConfigFile::Section::setKey(const String &key, const String &value) {
for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
- if (!scumm_stricmp(key.c_str(), i->key.c_str())) {
+ if (key.equalsIgnoreCase(i->key)) {
i->value = value;
return;
}
@@ -363,7 +373,7 @@ void ConfigFile::Section::setKey(const String &key, const String &value) {
void ConfigFile::Section::removeKey(const String &key) {
for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
- if (!scumm_stricmp(key.c_str(), i->key.c_str())) {
+ if (key.equalsIgnoreCase(i->key)) {
keys.erase(i);
return;
}
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 138fcc201f..b741757cc5 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -103,13 +103,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
lineno++;
// Read a line
- String line;
- while (line.lastChar() != '\n') {
- char buf[256];
- if (!stream.readLine_NEW(buf, 256))
- break;
- line += buf;
- }
+ String line = stream.readLine();
if (line.size() == 0) {
// Do nothing
@@ -118,6 +112,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
// of a new domain, or a key-value-pair, we associate the value
// of the 'comment' variable with that entity.
comment += line;
+ comment += "\n";
} else if (line[0] == '[') {
// It's a new domain which begins here.
const char *p = line.c_str() + 1;
diff --git a/common/events.h b/common/events.h
index d0cb740692..f01282765a 100644
--- a/common/events.h
+++ b/common/events.h
@@ -27,6 +27,7 @@
#define COMMON_EVENTS_H
#include "common/keyboard.h"
+#include "common/queue.h"
#include "common/rect.h"
#include "common/system.h"
#include "common/noncopyable.h"
@@ -58,6 +59,9 @@ enum EventType {
EVENT_MBUTTONDOWN = 13,
EVENT_MBUTTONUP = 14,
+ EVENT_MAINMENU = 15,
+ EVENT_RTL = 16,
+
EVENT_QUIT = 10,
EVENT_SCREEN_CHANGED = 11,
/**
@@ -142,6 +146,11 @@ public:
*/
virtual bool pollEvent(Common::Event &event) = 0;
+ /**
+ * Pushes a "fake" event of the specified type into the event queue
+ */
+ virtual void pushEvent(Common::Event event) = 0;
+
/** Register random source so it can be serialized in game test purposes **/
virtual void registerRandomSource(Common::RandomSource &rnd, const char *name) = 0;
@@ -166,6 +175,17 @@ public:
*/
virtual int shouldQuit() const = 0;
+ /**
+ * Should we return to the launcher?
+ */
+ virtual int shouldRTL() const = 0;
+
+ /**
+ * Reset the "return to launcher" flag (as returned shouldRTL()) to false.
+ * Used when we have returned to the launcher.
+ */
+ virtual void resetRTL() = 0;
+
// Optional: check whether a given key is currently pressed ????
//virtual bool isKeyPressed(int keycode) = 0;
@@ -173,6 +193,9 @@ public:
// TODO: Consider removing OSystem::getScreenChangeID and
// replacing it by a generic getScreenChangeID method here
+protected:
+
+ Common::Queue<Common::Event> artificialEventQueue;
};
} // End of namespace Common
diff --git a/common/file.cpp b/common/file.cpp
index fb837b9499..cf396a32cd 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -23,254 +23,51 @@
*
*/
+#include "common/archive.h"
#include "common/file.h"
#include "common/fs.h"
-#include "common/hashmap.h"
#include "common/util.h"
-#include "common/hash-str.h"
-#include <errno.h>
-
-#if defined(MACOSX) || defined(IPHONE)
-#include "CoreFoundation/CoreFoundation.h"
-#endif
-
-#ifdef __PLAYSTATION2__
- // for those replaced fopen/fread/etc functions
- typedef unsigned long uint64;
- typedef signed long int64;
- #include "backends/platform/ps2/fileio.h"
-
- #define fopen(a, b) ps2_fopen(a, b)
- #define fclose(a) ps2_fclose(a)
- #define fseek(a, b, c) ps2_fseek(a, b, c)
- #define ftell(a) ps2_ftell(a)
- #define feof(a) ps2_feof(a)
- #define fread(a, b, c, d) ps2_fread(a, b, c, d)
- #define fwrite(a, b, c, d) ps2_fwrite(a, b, c, d)
-
- //#define fprintf ps2_fprintf // used in common/util.cpp
- //#define fflush(a) ps2_fflush(a) // used in common/util.cpp
-
- //#define fgetc(a) ps2_fgetc(a) // not used
- //#define fgets(a, b, c) ps2_fgets(a, b, c) // not used
- //#define fputc(a, b) ps2_fputc(a, b) // not used
- //#define fputs(a, b) ps2_fputs(a, b) // not used
-
- //#define fsize(a) ps2_fsize(a) // not used -- and it is not a standard function either
-#endif
-
-#ifdef __DS__
-
- // These functions replease the standard library functions of the same name.
- // As this header is included after the standard one, I have the chance to #define
- // all of these to my own code.
- //
- // A #define is the only way, as redefinig the functions would cause linker errors.
-
- // These functions need to be #undef'ed, as their original definition
- // in devkitarm is done with #includes (ugh!)
- #undef feof
- #undef clearerr
- //#undef getc
- //#undef ferror
-
- #include "backends/fs/ds/ds-fs.h"
-
-
- //void std_fprintf(FILE* handle, const char* fmt, ...); // used in common/util.cpp
- //void std_fflush(FILE* handle); // used in common/util.cpp
-
- //char* std_fgets(char* str, int size, FILE* file); // not used
- //int std_getc(FILE* handle); // not used
- //char* std_getcwd(char* dir, int dunno); // not used
- //void std_cwd(char* dir); // not used
- //int std_ferror(FILE* handle); // not used
-
- // Only functions used in the ScummVM source have been defined here!
- #define fopen(name, mode) DS::std_fopen(name, mode)
- #define fclose(handle) DS::std_fclose(handle)
- #define fread(ptr, size, items, file) DS::std_fread(ptr, size, items, file)
- #define fwrite(ptr, size, items, file) DS::std_fwrite(ptr, size, items, file)
- #define feof(handle) DS::std_feof(handle)
- #define ftell(handle) DS::std_ftell(handle)
- #define fseek(handle, offset, whence) DS::std_fseek(handle, offset, whence)
- #define clearerr(handle) DS::std_clearerr(handle)
-
- //#define printf(fmt, ...) consolePrintf(fmt, ##__VA_ARGS__)
-
- //#define fprintf(file, fmt, ...) { char str[128]; sprintf(str, fmt, ##__VA_ARGS__); DS::std_fwrite(str, strlen(str), 1, file); }
- //#define fflush(file) DS::std_fflush(file) // used in common/util.cpp
-
- //#define fgets(str, size, file) DS::std_fgets(str, size, file) // not used
- //#define getc(handle) DS::std_getc(handle) // not used
- //#define getcwd(dir, dunno) DS::std_getcwd(dir, dunno) // not used
- #define ferror(handle) DS::std_ferror(handle)
-
-#endif
-
-#ifdef __SYMBIAN32__
- #undef feof
- #undef clearerr
-
- #define FILE void
-
- FILE* symbian_fopen(const char* name, const char* mode);
- void symbian_fclose(FILE* handle);
- size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
- size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
- bool symbian_feof(FILE* handle);
- long int symbian_ftell(FILE* handle);
- int symbian_fseek(FILE* handle, long int offset, int whence);
- void symbian_clearerr(FILE* handle);
-
- // Only functions used in the ScummVM source have been defined here!
- #define fopen(name, mode) symbian_fopen(name, mode)
- #define fclose(handle) symbian_fclose(handle)
- #define fread(ptr, size, items, file) symbian_fread(ptr, size, items, file)
- #define fwrite(ptr, size, items, file) symbian_fwrite(ptr, size, items, file)
- #define feof(handle) symbian_feof(handle)
- #define ftell(handle) symbian_ftell(handle)
- #define fseek(handle, offset, whence) symbian_fseek(handle, offset, whence)
- #define clearerr(handle) symbian_clearerr(handle)
-#endif
+#include "common/system.h"
namespace Common {
-typedef HashMap<String, int> StringIntMap;
-
-// The following two objects could be turned into static members of class
-// File. However, then we would be forced to #include hashmap in file.h
-// which seems to be a high price just for a simple beautification...
-static StringIntMap *_defaultDirectories;
-static StringMap *_filesMap;
-
-static FILE *fopenNoCase(const String &filename, const String &directory, const char *mode) {
- FILE *file;
- String dirBuf(directory);
- String fileBuf(filename);
-
-#if !defined(__GP32__) && !defined(PALMOS_MODE)
- // Add a trailing slash, if necessary.
- if (!dirBuf.empty()) {
- const char c = dirBuf.lastChar();
- if (c != ':' && c != '/' && c != '\\')
- dirBuf += '/';
- }
-#endif
-
- // Append the filename to the path string
- String pathBuf(dirBuf);
- pathBuf += fileBuf;
-
- //
- // Try to open the file normally
- //
- file = fopen(pathBuf.c_str(), mode);
-
- //
- // Try again, with file name converted to upper case
- //
- if (!file) {
- fileBuf.toUppercase();
- pathBuf = dirBuf + fileBuf;
- file = fopen(pathBuf.c_str(), mode);
- }
-
- //
- // Try again, with file name converted to lower case
- //
- if (!file) {
- fileBuf.toLowercase();
- pathBuf = dirBuf + fileBuf;
- file = fopen(pathBuf.c_str(), mode);
- }
-
- //
- // Try again, with file name capitalized
- //
- if (!file) {
- fileBuf.toLowercase();
- fileBuf.setChar(toupper(fileBuf[0]),0);
- pathBuf = dirBuf + fileBuf;
- file = fopen(pathBuf.c_str(), mode);
- }
-
-#ifdef __amigaos4__
- //
- // Work around for possibility that someone uses AmigaOS "newlib" build with SmartFileSystem (blocksize 512 bytes), leading
- // to buffer size being only 512 bytes. "Clib2" sets the buffer size to 8KB, resulting smooth movie playback. This forces the buffer
- // to be enough also when using "newlib" compile on SFS.
- //
- if (file) {
- setvbuf(file, NULL, _IOFBF, 8192);
- }
-#endif
+static Common::SearchSet *s_searchSet = 0;
- return file;
-}
void File::addDefaultDirectory(const String &directory) {
FilesystemNode dir(directory);
addDefaultDirectoryRecursive(dir, 1);
}
-void File::addDefaultDirectoryRecursive(const String &directory, int level, const String &prefix) {
+void File::addDefaultDirectoryRecursive(const String &directory, int level) {
FilesystemNode dir(directory);
- addDefaultDirectoryRecursive(dir, level, prefix);
+ addDefaultDirectoryRecursive(dir, level);
}
void File::addDefaultDirectory(const FilesystemNode &directory) {
addDefaultDirectoryRecursive(directory, 1);
}
-void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, const String &prefix) {
- if (level <= 0)
+void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level) {
+ if (level <= 0 || !dir.exists() || !dir.isDirectory())
return;
- FSList fslist;
- if (!dir.getChildren(fslist, FilesystemNode::kListAll)) {
- // Failed listing the contents of this node, so it is either not a
- // directory, or just doesn't exist at all.
- return;
+ if (!s_searchSet) {
+ s_searchSet = new Common::SearchSet();
+ g_system->addSysArchivesToSearchSet(*s_searchSet);
}
- if (!_defaultDirectories)
- _defaultDirectories = new StringIntMap;
-
- // Do not add directories multiple times, unless this time they are added
- // with a bigger depth.
- const String &directory(dir.getPath());
- if (_defaultDirectories->contains(directory) && (*_defaultDirectories)[directory] >= level)
- return;
- (*_defaultDirectories)[directory] = level;
-
- if (!_filesMap)
- _filesMap = new StringMap;
-
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory()) {
- addDefaultDirectoryRecursive(file->getPath(), level - 1, prefix + file->getName() + "/");
- } else {
- String lfn(prefix);
- lfn += file->getName();
- lfn.toLowercase();
- if (!_filesMap->contains(lfn)) {
- (*_filesMap)[lfn] = file->getPath();
- }
- }
- }
+ Common::ArchivePtr dataArchive(new Common::FSDirectory(dir, level));
+ s_searchSet->add(dir.getPath(), dataArchive, 1);
}
void File::resetDefaultDirectories() {
- delete _defaultDirectories;
- delete _filesMap;
-
- _defaultDirectories = 0;
- _filesMap = 0;
+ delete s_searchSet;
+ s_searchSet = 0;
}
File::File()
- : _handle(0), _ioFailed(false) {
+ : _handle(0) {
}
File::~File() {
@@ -285,51 +82,21 @@ bool File::open(const String &filename) {
_name.clear();
clearIOFailed();
- String fname(filename);
- fname.toLowercase();
-
- if (_filesMap && _filesMap->contains(fname)) {
- fname = (*_filesMap)[fname];
- debug(3, "Opening hashed: %s", fname.c_str());
- _handle = fopen(fname.c_str(), "rb");
- } else if (_filesMap && _filesMap->contains(fname + ".")) {
+ if (s_searchSet && s_searchSet->hasFile(filename)) {
+ debug(3, "Opening hashed: %s", filename.c_str());
+ _handle = s_searchSet->openFile(filename);
+ } else if (s_searchSet && s_searchSet->hasFile(filename + ".")) {
// WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails"
// sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot)
- fname = (*_filesMap)[fname + "."];
- debug(3, "Opening hashed: %s", fname.c_str());
- _handle = fopen(fname.c_str(), "rb");
+ debug(3, "Opening hashed: %s.", filename.c_str());
+ _handle = s_searchSet->openFile(filename);
} else {
-
- if (_defaultDirectories) {
- // Try all default directories
- StringIntMap::const_iterator x(_defaultDirectories->begin());
- for (; _handle == NULL && x != _defaultDirectories->end(); ++x) {
- _handle = fopenNoCase(filename, x->_key, "rb");
- }
- }
-
// Last resort: try the current directory
- if (_handle == NULL)
- _handle = fopenNoCase(filename, "", "rb");
-
- // Last last (really) resort: try looking inside the application bundle on Mac OS X for the lowercase file.
-#if defined(MACOSX) || defined(IPHONE)
- if (!_handle) {
- CFStringRef cfFileName = CFStringCreateWithBytes(NULL, (const UInt8 *)filename.c_str(), filename.size(), kCFStringEncodingASCII, false);
- CFURLRef fileUrl = CFBundleCopyResourceURL(CFBundleGetMainBundle(), cfFileName, NULL, NULL);
- if (fileUrl) {
- UInt8 buf[256];
- if (CFURLGetFileSystemRepresentation(fileUrl, false, (UInt8 *)buf, 256)) {
- _handle = fopen((char *)buf, "rb");
- }
- CFRelease(fileUrl);
- }
- CFRelease(cfFileName);
- }
-#endif
-
+ FilesystemNode file(filename);
+ if (file.exists() && !file.isDirectory())
+ _handle = file.openForReading();
}
-
+
if (_handle == NULL)
debug(2, "File %s not opened", filename.c_str());
else
@@ -341,18 +108,12 @@ bool File::open(const String &filename) {
bool File::open(const FilesystemNode &node) {
if (!node.exists()) {
- warning("File::open: Trying to open a FilesystemNode which does not exist");
+ warning("File::open: FilesystemNode does not exist");
return false;
} else if (node.isDirectory()) {
- warning("File::open: Trying to open a FilesystemNode which is a directory");
+ warning("File::open: FilesystemNode is a directory");
return false;
- } /*else if (!node.isReadable() && mode == kFileReadMode) {
- warning("File::open: Trying to open an unreadable FilesystemNode object for reading");
- return false;
- } else if (!node.isWritable() && mode == kFileWriteMode) {
- warning("File::open: Trying to open an unwritable FilesystemNode object for writing");
- return false;
- }*/
+ }
String filename(node.getName());
@@ -363,7 +124,7 @@ bool File::open(const FilesystemNode &node) {
clearIOFailed();
_name.clear();
- _handle = fopen(node.getPath().c_str(), "rb");
+ _handle = node.openForReading();
if (_handle == NULL)
debug(2, "File %s not found", filename.c_str());
@@ -374,39 +135,24 @@ bool File::open(const FilesystemNode &node) {
}
bool File::exists(const String &filename) {
- // First try to find the file via a FilesystemNode (in case an absolute
- // path was passed). This is only used to filter out directories.
- FilesystemNode file(filename);
- if (file.exists())
- return !file.isDirectory();
-
- // See if the file is already mapped
- if (_filesMap && _filesMap->contains(filename)) {
- FilesystemNode file2((*_filesMap)[filename]);
-
- if (file2.exists())
- return !file2.isDirectory();
- }
-
- // Try all default directories
- if (_defaultDirectories) {
- StringIntMap::const_iterator i(_defaultDirectories->begin());
- for (; i != _defaultDirectories->end(); ++i) {
- FilesystemNode file2(i->_key + filename);
-
- if(file2.exists())
- return !file2.isDirectory();
- }
+ if (s_searchSet && s_searchSet->hasFile(filename)) {
+ return true;
+ } else if (s_searchSet && s_searchSet->hasFile(filename + ".")) {
+ // WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails"
+ // sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot)
+ return true;
+ } else {
+ // Last resort: try the current directory
+ FilesystemNode file(filename);
+ if (file.exists() && !file.isDirectory())
+ return true;
}
-
- //Try opening the file inside the local directory as a last resort
- File tmp;
- return tmp.open(filename);
+
+ return false;
}
void File::close() {
- if (_handle)
- fclose((FILE *)_handle);
+ delete _handle;
_handle = NULL;
}
@@ -416,59 +162,47 @@ bool File::isOpen() const {
bool File::ioFailed() const {
// TODO/FIXME: Just use ferror() here?
- return _ioFailed != 0;
+ return !_handle || _handle->ioFailed();
}
void File::clearIOFailed() {
- // TODO/FIXME: Just use clearerr() here?
- _ioFailed = false;
+ if (_handle)
+ _handle->clearIOFailed();
}
-bool File::eof() const {
+bool File::err() const {
assert(_handle);
-
- return feof((FILE *)_handle) != 0;
+ return _handle->err();
}
-uint32 File::pos() const {
+void File::clearErr() {
assert(_handle);
-
- return ftell((FILE *)_handle);
+ _handle->clearErr();
}
-uint32 File::size() const {
+bool File::eos() const {
assert(_handle);
+ return _handle->eos();
+}
- uint32 oldPos = ftell((FILE *)_handle);
- fseek((FILE *)_handle, 0, SEEK_END);
- uint32 length = ftell((FILE *)_handle);
- fseek((FILE *)_handle, oldPos, SEEK_SET);
-
- return length;
+int32 File::pos() const {
+ assert(_handle);
+ return _handle->pos();
}
-void File::seek(int32 offs, int whence) {
+int32 File::size() const {
assert(_handle);
+ return _handle->size();
+}
- if (fseek((FILE *)_handle, offs, whence) != 0)
- clearerr((FILE *)_handle);
+bool File::seek(int32 offs, int whence) {
+ assert(_handle);
+ return _handle->seek(offs, whence);
}
uint32 File::read(void *ptr, uint32 len) {
- byte *ptr2 = (byte *)ptr;
- uint32 real_len;
-
assert(_handle);
-
- if (len == 0)
- return 0;
-
- real_len = fread(ptr2, 1, len, (FILE *)_handle);
- if (real_len < len) {
- _ioFailed = true;
- }
-
- return real_len;
+ return _handle->read(ptr, len);
}
@@ -483,32 +217,19 @@ bool DumpFile::open(const String &filename) {
assert(!filename.empty());
assert(!_handle);
- String fname(filename);
- fname.toLowercase();
-
- _handle = fopenNoCase(filename, "", "wb");
-
- if (_handle == NULL)
- debug(2, "Failed to open '%s' for writing", filename.c_str());
-
- return _handle != NULL;
+ FilesystemNode node(filename);
+ return open(node);
}
bool DumpFile::open(const FilesystemNode &node) {
assert(!_handle);
if (node.isDirectory()) {
- warning("File::open: Trying to open a FilesystemNode which is a directory");
- return false;
- } /*else if (!node.isReadable() && mode == kFileReadMode) {
- warning("File::open: Trying to open an unreadable FilesystemNode object for reading");
+ warning("DumpFile::open: FilesystemNode is a directory");
return false;
- } else if (!node.isWritable() && mode == kFileWriteMode) {
- warning("File::open: Trying to open an unwritable FilesystemNode object for writing");
- return false;
- }*/
+ }
- _handle = fopen(node.getPath().c_str(), "wb");
+ _handle = node.openForWriting();
if (_handle == NULL)
debug(2, "File %s not found", node.getName().c_str());
@@ -517,8 +238,7 @@ bool DumpFile::open(const FilesystemNode &node) {
}
void DumpFile::close() {
- if (_handle)
- fclose((FILE *)_handle);
+ delete _handle;
_handle = NULL;
}
@@ -526,36 +246,24 @@ bool DumpFile::isOpen() const {
return _handle != NULL;
}
-bool DumpFile::ioFailed() const {
- assert(_handle);
- return ferror((FILE *)_handle) != 0;
-}
-
-void DumpFile::clearIOFailed() {
+bool DumpFile::err() const {
assert(_handle);
- clearerr((FILE *)_handle);
+ return _handle->ioFailed();
}
-bool DumpFile::eof() const {
+void DumpFile::clearErr() {
assert(_handle);
- return feof((FILE *)_handle) != 0;
+ _handle->clearIOFailed();
}
uint32 DumpFile::write(const void *ptr, uint32 len) {
assert(_handle);
-
- if (len == 0)
- return 0;
-
- return (uint32)fwrite(ptr, 1, len, (FILE *)_handle);
+ return _handle->write(ptr, len);
}
-void DumpFile::flush() {
+bool DumpFile::flush() {
assert(_handle);
- // TODO: Should check the return value of fflush, and if it is non-zero,
- // check errno and set an error flag.
- fflush((FILE *)_handle);
+ return _handle->flush();
}
-
} // End of namespace Common
diff --git a/common/file.h b/common/file.h
index 3adeb6ff36..a2739f795f 100644
--- a/common/file.h
+++ b/common/file.h
@@ -31,20 +31,17 @@
#include "common/str.h"
#include "common/stream.h"
-class FilesystemNode;
-
namespace Common {
+class FilesystemNode;
+
/**
* TODO: vital to document this core class properly!!! For both users and implementors
*/
class File : public SeekableReadStream, public NonCopyable {
protected:
/** File handle to the actual file; 0 if no file is open. */
- void *_handle;
-
- /** Status flag which tells about recent I/O failures. */
- bool _ioFailed;
+ SeekableReadStream *_handle;
/** The name of this file, for debugging. */
String _name;
@@ -52,10 +49,10 @@ protected:
public:
static void addDefaultDirectory(const String &directory);
- static void addDefaultDirectoryRecursive(const String &directory, int level = 4, const String &prefix = "");
+ static void addDefaultDirectoryRecursive(const String &directory, int level = 4);
static void addDefaultDirectory(const FilesystemNode &directory);
- static void addDefaultDirectoryRecursive(const FilesystemNode &directory, int level = 4, const String &prefix = "");
+ static void addDefaultDirectoryRecursive(const FilesystemNode &directory, int level = 4);
static void resetDefaultDirectories();
@@ -93,18 +90,13 @@ public:
bool ioFailed() const;
void clearIOFailed();
- bool eos() const { return eof(); }
-
- /**
- * Checks for end of file.
- *
- * @return: true if the end of file is reached, false otherwise.
- */
- virtual bool eof() const;
+ bool err() const;
+ void clearErr();
+ bool eos() const;
- virtual uint32 pos() const;
- virtual uint32 size() const;
- void seek(int32 offs, int whence = SEEK_SET);
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ bool seek(int32 offs, int whence = SEEK_SET);
uint32 read(void *dataPtr, uint32 dataSize);
};
@@ -118,7 +110,7 @@ public:
class DumpFile : public WriteStream, public NonCopyable {
protected:
/** File handle to the actual file; 0 if no file is open. */
- void *_handle;
+ WriteStream *_handle;
public:
DumpFile();
@@ -136,24 +128,14 @@ public:
*/
bool isOpen() const;
-
- bool ioFailed() const;
- void clearIOFailed();
- bool eos() const { return eof(); }
-
- /**
- * Checks for end of file.
- *
- * @return: true if the end of file is reached, false otherwise.
- */
- virtual bool eof() const;
+ bool err() const;
+ void clearErr();
virtual uint32 write(const void *dataPtr, uint32 dataSize);
- virtual void flush();
+ virtual bool flush();
};
-
} // End of namespace Common
#endif
diff --git a/common/fs.cpp b/common/fs.cpp
index 3f585c6038..4d31ac09fa 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -23,12 +23,11 @@
*/
#include "common/util.h"
-#include "common/file.h"
#include "common/system.h"
#include "backends/fs/abstract-fs.h"
#include "backends/fs/fs-factory.h"
-//namespace Common {
+namespace Common {
FilesystemNode::FilesystemNode() {
}
@@ -52,7 +51,7 @@ bool FilesystemNode::operator<(const FilesystemNode& node) const {
if (isDirectory() != node.isDirectory())
return isDirectory();
- return scumm_stricmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0;
+ return getDisplayName().compareToIgnoreCase(node.getDisplayName()) < 0;
}
bool FilesystemNode::exists() const {
@@ -63,10 +62,10 @@ bool FilesystemNode::exists() const {
}
FilesystemNode FilesystemNode::getChild(const Common::String &n) const {
- if (_realNode == 0)
- return *this;
+ // If this node is invalid or not a directory, return an invalid node
+ if (_realNode == 0 || !_realNode->isDirectory())
+ return FilesystemNode();
- assert(_realNode->isDirectory());
AbstractFilesystemNode *node = _realNode->getChild(n);
return FilesystemNode(node);
}
@@ -155,7 +154,7 @@ bool FilesystemNode::lookupFile(FSList &results, const Common::String &p, bool h
} else {
Common::String filename = entry->getName();
filename.toUppercase();
- if (Common::matchString(filename.c_str(), pattern.c_str())) {
+ if (filename.matchString(pattern)) {
results.push_back(*entry);
if (!exhaustive)
@@ -174,40 +173,31 @@ bool FilesystemNode::lookupFile(FSList &results, const Common::String &p, bool h
return !results.empty();
}
-Common::SeekableReadStream *FilesystemNode::openForReading() {
+Common::SeekableReadStream *FilesystemNode::openForReading() const {
if (_realNode == 0)
return 0;
-#if 0
- return _realNode->openForReading();
-#else
- // FIXME: Until we support openForReading in AbstractFilesystemNode,
- // we just use Common::File.
- Common::File *confFile = new Common::File();
- assert(confFile);
- if (!confFile->open(*this)) {
- delete confFile;
- confFile = 0;
+
+ if (!_realNode->exists()) {
+ warning("FilesystemNode::openForReading: FilesystemNode does not exist");
+ return false;
+ } else if (_realNode->isDirectory()) {
+ warning("FilesystemNode::openForReading: FilesystemNode is a directory");
+ return false;
}
- return confFile;
-#endif
+
+ return _realNode->openForReading();
}
-Common::WriteStream *FilesystemNode::openForWriting() {
+Common::WriteStream *FilesystemNode::openForWriting() const {
if (_realNode == 0)
return 0;
-#if 0
- return _realNode->openForWriting();
-#else
- // FIXME: Until we support openForWriting in AbstractFilesystemNode,
- // we just use Common::DumpFile.
- Common::DumpFile *confFile = new Common::DumpFile();
- assert(confFile);
- if (!confFile->open(*this)) {
- delete confFile;
- confFile = 0;
+
+ if (_realNode->isDirectory()) {
+ warning("FilesystemNode::openForWriting: FilesystemNode is a directory");
+ return 0;
}
- return confFile;
-#endif
+
+ return _realNode->openForWriting();
}
-//} // End of namespace Common
+} // End of namespace Common
diff --git a/common/fs.h b/common/fs.h
index 972e0d86af..c5f7ca6b4c 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -32,15 +32,10 @@
class AbstractFilesystemNode;
namespace Common {
- class SeekableReadStream;
- class WriteStream;
-}
-
-//namespace Common {
class FilesystemNode;
-//class SeekableReadStream;
-//class WriteStream;
+class SeekableReadStream;
+class WriteStream;
/**
* List of multiple file system nodes. E.g. the contents of a given directory.
@@ -107,17 +102,29 @@ public:
virtual bool exists() const;
/**
- * Fetch a child node of this node, with the given name. Only valid for
- * directory nodes (an assertion is triggered otherwise).
- * If no child node with the given name exists, an invalid node is returned.
+ * Create a new node referring to a child node of the current node, which
+ * must be a directory node (otherwise an invalid node is returned).
+ * If a child matching the name exists, a normal node for it is returned.
+ * If no child with the name exists, a node for it is still returned,
+ * but exists() will return 'false' for it. This node can however be used
+ * to create a new file using the openForWriting() method.
+ *
+ * @todo If openForWriting() (or a hypothetical future mkdir() method) is used,
+ * this should affect what exists/isDirectory/isReadable/isWritable return
+ * for existing nodes. However, this is not the case for many existing
+ * FSNode implementations. Either fix those, or document that FSNodes
+ * can become 'stale'...
+ *
+ * @param name the name of a child of this directory
+ * @return the node referring to the child with the given name
*/
FilesystemNode getChild(const Common::String &name) const;
/**
- * Return a list of child nodes of this directory node. If called on a node
+ * Return a list of all child nodes of this directory node. If called on a node
* that does not represent a directory, false is returned.
*
- * @return true if succesful, false otherwise (e.g. when the directory does not exist).
+ * @return true if successful, false otherwise (e.g. when the directory does not exist).
*/
virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const;
@@ -141,10 +148,11 @@ public:
virtual Common::String getName() const;
/**
- * Return a string representation of the file which can be passed to fopen(),
- * and is suitable for archiving (i.e. writing to the config file).
- * This will usually be a 'path' (hence the name of the method), but can
- * be anything that fulfills the above criterions.
+ * Return a string representation of the file which is suitable for
+ * archiving (i.e. writing to the config file). This will usually be a
+ * 'path' (hence the name of the method), but can be anything that meets
+ * the above criterions. What a 'path' is differs greatly from system to
+ * system anyway.
*
* @note Do not assume that this string contains (back)slashes or any
* other kind of 'path separators'.
@@ -222,7 +230,7 @@ public:
*
* @return pointer to the stream object, 0 in case of a failure
*/
- virtual Common::SeekableReadStream *openForReading();
+ virtual Common::SeekableReadStream *openForReading() const;
/**
* Creates a WriteStream instance corresponding to the file
@@ -231,9 +239,9 @@ public:
*
* @return pointer to the stream object, 0 in case of a failure
*/
- virtual Common::WriteStream *openForWriting();
+ virtual Common::WriteStream *openForWriting() const;
};
-//} // End of namespace Common
+} // End of namespace Common
#endif //COMMON_FS_H
diff --git a/common/hash-str.h b/common/hash-str.h
index f64b62daed..40557037e7 100644
--- a/common/hash-str.h
+++ b/common/hash-str.h
@@ -39,7 +39,7 @@ inline uint hashit_lower(const String &str) { return hashit_lower(str.c_str());
// FIXME: The following functors obviously are not consistently named
struct CaseSensitiveString_EqualTo {
- bool operator()(const String& x, const String& y) const { return strcmp(x.c_str(), y.c_str()) == 0; }
+ bool operator()(const String& x, const String& y) const { return x.equals(y); }
};
struct CaseSensitiveString_Hash {
@@ -48,7 +48,7 @@ struct CaseSensitiveString_Hash {
struct IgnoreCase_EqualTo {
- bool operator()(const String& x, const String& y) const { return scumm_stricmp(x.c_str(), y.c_str()) == 0; }
+ bool operator()(const String& x, const String& y) const { return x.equalsIgnoreCase(y); }
};
struct IgnoreCase_Hash {
diff --git a/common/hashmap.cpp b/common/hashmap.cpp
index 4749234740..b8f2608901 100644
--- a/common/hashmap.cpp
+++ b/common/hashmap.cpp
@@ -24,70 +24,86 @@
*/
// The hash map (associative array) implementation in this file is
-// based on code by Andrew Y. Ng, 1996:
-
-/*
- * Copyright (c) 1998-2003 Massachusetts Institute of Technology.
- * This code was developed as part of the Haystack research project
- * (http://haystack.lcs.mit.edu/). Permission is hereby granted,
- * free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit
- * persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
+// based on the PyDict implementation of CPython. The erase() method
+// is based on example code in the Wikipedia article on Hash tables.
#include "common/hashmap.h"
namespace Common {
-// const char *:
+// Hash function for strings, taken from CPython.
uint hashit(const char *p) {
- uint hash = 0;
+ uint hash = *p << 7;
byte c;
- while ((c = *p++))
- hash = (hash * 31 + c);
- return hash;
+ int size = 0;
+ while ((c = *p++)) {
+ hash = (1000003 * hash) ^ c;
+ size++;
+ }
+ return hash ^ size;
}
+// Like hashit, but converts every char to lowercase before hashing.
uint hashit_lower(const char *p) {
- uint hash = 0;
+ uint hash = tolower(*p) << 7;
byte c;
- while ((c = *p++))
- hash = (hash * 31 + tolower(c));
- return hash;
+ int size = 0;
+ while ((c = *p++)) {
+ hash = (1000003 * hash) ^ tolower(c);
+ size++;
+ }
+ return hash ^ size;
}
-// The following table is taken from the GNU ISO C++ Library's hashtable.h file.
-static const uint primes[] = {
- 53ul, 97ul, 193ul, 389ul, 769ul,
- 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
- 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
- 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
- 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
- 1610612741ul, 3221225473ul, 4294967291ul
-};
+#ifdef DEBUG_HASH_COLLISIONS
+static double
+ g_collisions = 0,
+ g_lookups = 0,
+ g_collPerLook = 0,
+ g_capacity = 0,
+ g_size = 0;
+static int g_max_capacity = 0, g_max_size = 0;
+static int g_totalHashmaps = 0;
+static int g_stats[4] = {0,0,0,0};
-uint nextTableSize(uint x) {
- int i = 0;
- while (x >= primes[i])
- i++;
- return primes[i];
-}
+void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele) {
+ g_collisions += collisions;
+ g_lookups += lookups;
+ if (lookups)
+ g_collPerLook += (double)collisions / (double)lookups;
+ g_capacity += arrsize;
+ g_size += nele;
+ g_totalHashmaps++;
+
+ if (3*nele <= 2*8)
+ g_stats[0]++;
+ if (3*nele <= 2*16)
+ g_stats[1]++;
+ if (3*nele <= 2*32)
+ g_stats[2]++;
+ if (3*nele <= 2*64)
+ g_stats[3]++;
+
+ g_max_capacity = MAX(g_max_capacity, arrsize);
+ g_max_size = MAX(g_max_size, nele);
+ fprintf(stdout, "%d hashmaps: colls %.1f; lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n",
+ g_totalHashmaps,
+ g_collisions / g_totalHashmaps,
+ g_lookups / g_totalHashmaps,
+ 100 * g_collPerLook / g_totalHashmaps,
+ g_size / g_totalHashmaps, g_max_size,
+ g_capacity / g_totalHashmaps, g_max_capacity);
+ fprintf(stdout, " %d less than %d; %d less than %d; %d less than %d; %d less than %d\n",
+ g_stats[0], 2*8/3,
+ g_stats[1],2*16/3,
+ g_stats[2],2*32/3,
+ g_stats[3],2*64/3);
+
+ // TODO:
+ // * Should record the maximal size of the map during its lifetime, not that at its death
+ // * Should do some statistics: how many maps are less than 2/3*8, 2/3*16, 2/3*32, ...
+}
+#endif
} // End of namespace Common
diff --git a/common/hashmap.h b/common/hashmap.h
index 69f367de97..81f5ee84b4 100644
--- a/common/hashmap.h
+++ b/common/hashmap.h
@@ -24,32 +24,8 @@
*/
// The hash map (associative array) implementation in this file is
-// based on code by Andrew Y. Ng, 1996:
-
-/*
- * Copyright (c) 1998-2003 Massachusetts Institute of Technology.
- * This code was developed as part of the Haystack research project
- * (http://haystack.lcs.mit.edu/). Permission is hereby granted,
- * free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit
- * persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
+// based on the PyDict implementation of CPython. The erase() method
+// is based on example code in the Wikipedia article on Hash tables.
#ifndef COMMON_HASHMAP_H
#define COMMON_HASHMAP_H
@@ -74,11 +50,6 @@
namespace Common {
-// The table sizes ideally are primes. We use a helper function to find
-// suitable table sizes.
-uint nextTableSize(uint x);
-
-
// Enable the following #define if you want to check how many collisions the
// code produces (many collisions indicate either a bad hash function, or a
// hash table that is too small).
@@ -113,9 +84,24 @@ public:
Node(const Key &key) : _key(key), _value() {}
};
+ enum {
+ HASHMAP_PERTURB_SHIFT = 5,
+ HASHMAP_MIN_CAPACITY = 16,
+
+ // The quotient of the next two constants controls how much the
+ // internal storage of the hashmap may fill up before being
+ // increased automatically.
+ // Note: the quotient of these two must be between and different
+ // from 0 and 1.
+ HASHMAP_LOADFACTOR_NUMERATOR = 2,
+ HASHMAP_LOADFACTOR_DENOMINATOR = 3,
+
+ HASHMAP_MEMORYPOOL_SIZE = HASHMAP_MIN_CAPACITY * HASHMAP_LOADFACTOR_NUMERATOR / HASHMAP_LOADFACTOR_DENOMINATOR
+ };
+
#ifdef USE_HASHMAP_MEMORY_POOL
- MemoryPool _nodePool;
+ FixedSizeMemoryPool<sizeof(Node), HASHMAP_MEMORYPOOL_SIZE> _nodePool;
Node *allocNode(const Key &key) {
void* mem = _nodePool.malloc();
@@ -136,8 +122,9 @@ public:
}
#endif
- Node **_arr; // hashtable of size arrsize.
- uint _arrsize, _nele;
+ Node **_storage; // hashtable of size arrsize.
+ uint _mask; /**< Capacity of the HashMap minus one; must be a power of two of minus one */
+ uint _size;
HashFunc _hash;
EqualFunc _equal;
@@ -152,7 +139,7 @@ public:
void assign(const HM_t &map);
int lookup(const Key &key) const;
int lookupAndCreateIfMissing(const Key &key);
- void expand_array(uint newsize);
+ void expandStorage(uint newCapacity);
template<class T> friend class IteratorImpl;
@@ -174,8 +161,8 @@ public:
NodeType *deref() const {
assert(_hashmap != 0);
- assert(_idx < _hashmap->_arrsize);
- Node *node = _hashmap->_arr[_idx];
+ assert(_idx <= _hashmap->_mask);
+ Node *node = _hashmap->_storage[_idx];
assert(node != 0);
return node;
}
@@ -195,8 +182,8 @@ public:
assert(_hashmap);
do {
_idx++;
- } while (_idx < _hashmap->_arrsize && _hashmap->_arr[_idx] == 0);
- if (_idx >= _hashmap->_arrsize)
+ } while (_idx <= _hashmap->_mask && _hashmap->_storage[_idx] == 0);
+ if (_idx > _hashmap->_mask)
_idx = (uint)-1;
return *this;
@@ -223,7 +210,7 @@ public:
// Remove the previous content and ...
clear();
- delete[] _arr;
+ delete[] _storage;
// ... copy the new stuff.
assign(map);
return *this;
@@ -242,12 +229,12 @@ public:
void erase(const Key &key);
- uint size() const { return _nele; }
+ uint size() const { return _size; }
iterator begin() {
// Find and return the _key non-empty entry
- for (uint ctr = 0; ctr < _arrsize; ++ctr) {
- if (_arr[ctr])
+ for (uint ctr = 0; ctr <= _mask; ++ctr) {
+ if (_storage[ctr])
return iterator(ctr, this);
}
return end();
@@ -258,8 +245,8 @@ public:
const_iterator begin() const {
// Find and return the first non-empty entry
- for (uint ctr = 0; ctr < _arrsize; ++ctr) {
- if (_arr[ctr])
+ for (uint ctr = 0; ctr <= _mask; ++ctr) {
+ if (_storage[ctr])
return const_iterator(ctr, this);
}
return end();
@@ -270,14 +257,14 @@ public:
iterator find(const Key &key) {
uint ctr = lookup(key);
- if (_arr[ctr])
+ if (_storage[ctr])
return iterator(ctr, this);
return end();
}
const_iterator find(const Key &key) const {
uint ctr = lookup(key);
- if (_arr[ctr])
+ if (_storage[ctr])
return const_iterator(ctr, this);
return end();
}
@@ -285,7 +272,7 @@ public:
// TODO: insert() method?
bool empty() const {
- return (_nele == 0);
+ return (_size == 0);
}
};
@@ -297,16 +284,13 @@ public:
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() :
-#ifdef USE_HASHMAP_MEMORY_POOL
- _nodePool(sizeof(Node)),
-#endif
_defaultVal() {
- _arrsize = nextTableSize(0);
- _arr = new Node *[_arrsize];
- assert(_arr != NULL);
- memset(_arr, 0, _arrsize * sizeof(Node *));
+ _mask = HASHMAP_MIN_CAPACITY - 1;
+ _storage = new Node *[HASHMAP_MIN_CAPACITY];
+ assert(_storage != NULL);
+ memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
- _nele = 0;
+ _size = 0;
#ifdef DEBUG_HASH_COLLISIONS
_collisions = 0;
@@ -321,9 +305,6 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() :
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
-#ifdef USE_HASHMAP_MEMORY_POOL
- _nodePool(sizeof(Node)),
-#endif
_defaultVal() {
assign(map);
}
@@ -333,11 +314,15 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
- for (uint ctr = 0; ctr < _arrsize; ++ctr)
- if (_arr[ctr] != NULL)
- freeNode(_arr[ctr]);
+ for (uint ctr = 0; ctr <= _mask; ++ctr)
+ if (_storage[ctr] != NULL)
+ freeNode(_storage[ctr]);
- delete[] _arr;
+ delete[] _storage;
+#ifdef DEBUG_HASH_COLLISIONS
+ extern void updateHashCollisionStats(int, int, int, int);
+ updateHashCollisionStats(_collisions, _lookups, _mask+1, _size);
+#endif
}
/**
@@ -349,95 +334,102 @@ HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
- _arrsize = map._arrsize;
- _arr = new Node *[_arrsize];
- assert(_arr != NULL);
- memset(_arr, 0, _arrsize * sizeof(Node *));
+ _mask = map._mask;
+ _storage = new Node *[_mask+1];
+ assert(_storage != NULL);
+ memset(_storage, 0, (_mask+1) * sizeof(Node *));
// Simply clone the map given to us, one by one.
- _nele = 0;
- for (uint ctr = 0; ctr < _arrsize; ++ctr) {
- if (map._arr[ctr] != NULL) {
- _arr[ctr] = allocNode(map._arr[ctr]->_key);
- _arr[ctr]->_value = map._arr[ctr]->_value;
- _nele++;
+ _size = 0;
+ for (uint ctr = 0; ctr <= _mask; ++ctr) {
+ if (map._storage[ctr] != NULL) {
+ _storage[ctr] = allocNode(map._storage[ctr]->_key);
+ _storage[ctr]->_value = map._storage[ctr]->_value;
+ _size++;
}
}
// Perform a sanity check (to help track down hashmap corruption)
- assert(_nele == map._nele);
+ assert(_size == map._size);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
- for (uint ctr = 0; ctr < _arrsize; ++ctr) {
- if (_arr[ctr] != NULL) {
- freeNode(_arr[ctr]);
- _arr[ctr] = NULL;
+ for (uint ctr = 0; ctr <= _mask; ++ctr) {
+ if (_storage[ctr] != NULL) {
+ freeNode(_storage[ctr]);
+ _storage[ctr] = NULL;
}
}
- if (shrinkArray && _arrsize > nextTableSize(0)) {
- delete[] _arr;
+#ifdef USE_HASHMAP_MEMORY_POOL
+ _nodePool.freeUnusedPages();
+#endif
+
+ if (shrinkArray && _mask >= HASHMAP_MIN_CAPACITY) {
+ delete[] _storage;
- _arrsize = nextTableSize(0);
- _arr = new Node *[_arrsize];
- assert(_arr != NULL);
- memset(_arr, 0, _arrsize * sizeof(Node *));
+ _mask = HASHMAP_MIN_CAPACITY;
+ _storage = new Node *[HASHMAP_MIN_CAPACITY];
+ assert(_storage != NULL);
+ memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
}
- _nele = 0;
+ _size = 0;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
-void HashMap<Key, Val, HashFunc, EqualFunc>::expand_array(uint newsize) {
- assert(newsize > _arrsize);
- uint ctr, dex;
+void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
+ assert(newCapacity > _mask+1);
- const uint old_nele = _nele;
- const uint old_arrsize = _arrsize;
- Node **old_arr = _arr;
+ const uint old_size = _size;
+ const uint old_mask = _mask;
+ Node **old_storage = _storage;
// allocate a new array
- _nele = 0;
- _arrsize = newsize;
- _arr = new Node *[_arrsize];
- assert(_arr != NULL);
- memset(_arr, 0, _arrsize * sizeof(Node *));
+ _size = 0;
+ _mask = newCapacity - 1;
+ _storage = new Node *[newCapacity];
+ assert(_storage != NULL);
+ memset(_storage, 0, newCapacity * sizeof(Node *));
// rehash all the old elements
- for (ctr = 0; ctr < old_arrsize; ++ctr) {
- if (old_arr[ctr] == NULL)
+ for (uint ctr = 0; ctr <= old_mask; ++ctr) {
+ if (old_storage[ctr] == NULL)
continue;
// Insert the element from the old table into the new table.
// Since we know that no key exists twice in the old table, we
// can do this slightly better than by calling lookup, since we
// don't have to call _equal().
- dex = _hash(old_arr[ctr]->_key) % _arrsize;
- while (_arr[dex] != NULL) {
- dex = (dex + 1) % _arrsize;
+ const uint hash = _hash(old_storage[ctr]->_key);
+ uint idx = hash & _mask;
+ for (uint perturb = hash; _storage[idx] != NULL; perturb >>= HASHMAP_PERTURB_SHIFT) {
+ idx = (5 * idx + perturb + 1) & _mask;
}
- _arr[dex] = old_arr[ctr];
- _nele++;
+ _storage[idx] = old_storage[ctr];
+ _size++;
}
// Perform a sanity check: Old number of elements should match the new one!
// This check will fail if some previous operation corrupted this hashmap.
- assert(_nele == old_nele);
+ assert(_size == old_size);
- delete[] old_arr;
+ delete[] old_storage;
return;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
- uint ctr = _hash(key) % _arrsize;
+ const uint hash = _hash(key);
+ uint ctr = hash & _mask;
+ for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
+ if (_storage[ctr] == NULL || _equal(_storage[ctr]->_key, key))
+ break;
- while (_arr[ctr] != NULL && !_equal(_arr[ctr]->_key, key)) {
- ctr = (ctr + 1) % _arrsize;
+ ctr = (5 * ctr + perturb + 1) & _mask;
#ifdef DEBUG_HASH_COLLISIONS
_collisions++;
@@ -448,7 +440,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
_lookups++;
fprintf(stderr, "collisions %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n",
_collisions, _lookups, ((double) _collisions / (double)_lookups),
- (const void *)this, _arrsize, _nele);
+ (const void *)this, _mask+1, _size);
#endif
return ctr;
@@ -458,13 +450,15 @@ template<class Key, class Val, class HashFunc, class EqualFunc>
int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) {
uint ctr = lookup(key);
- if (_arr[ctr] == NULL) {
- _arr[ctr] = allocNode(key);
- _nele++;
+ if (_storage[ctr] == NULL) {
+ _storage[ctr] = allocNode(key);
+ _size++;
- // Keep the load factor below 75%.
- if (_nele > _arrsize * 75 / 100) {
- expand_array(nextTableSize(_arrsize));
+ // Keep the load factor below a certain threshold.
+ uint capacity = _mask + 1;
+ if (_size * HASHMAP_LOADFACTOR_DENOMINATOR > capacity * HASHMAP_LOADFACTOR_NUMERATOR) {
+ capacity = capacity < 500 ? (capacity * 4) : (capacity * 2);
+ expandStorage(capacity);
ctr = lookup(key);
}
}
@@ -476,7 +470,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &
template<class Key, class Val, class HashFunc, class EqualFunc>
bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const {
uint ctr = lookup(key);
- return (_arr[ctr] != NULL);
+ return (_storage[ctr] != NULL);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
@@ -492,15 +486,15 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) co
template<class Key, class Val, class HashFunc, class EqualFunc>
Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) {
uint ctr = lookupAndCreateIfMissing(key);
- assert(_arr[ctr] != NULL);
- return _arr[ctr]->_value;
+ assert(_storage[ctr] != NULL);
+ return _storage[ctr]->_value;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const {
uint ctr = lookup(key);
- if (_arr[ctr] != NULL)
- return _arr[ctr]->_value;
+ if (_storage[ctr] != NULL)
+ return _storage[ctr]->_value;
else
return _defaultVal;
}
@@ -508,38 +502,50 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) {
uint ctr = lookupAndCreateIfMissing(key);
- assert(_arr[ctr] != NULL);
- _arr[ctr]->_value = val;
+ assert(_storage[ctr] != NULL);
+ _storage[ctr]->_value = val;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) {
// This is based on code in the Wikipedia article on Hash tables.
- uint i = lookup(key);
- if (_arr[i] == NULL)
+
+ const uint hash = _hash(key);
+ uint i = hash & _mask;
+ uint perturb;
+
+ for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
+ if (_storage[i] == NULL || _equal(_storage[i]->_key, key))
+ break;
+
+ i = (5 * i + perturb + 1) & _mask;
+ }
+
+ if (_storage[i] == NULL)
return; // key wasn't present, so no work has to be done
+
// If we remove a key, we must check all subsequent keys and possibly
// reinsert them.
uint j = i;
- freeNode(_arr[i]);
- _arr[i] = NULL;
- while (true) {
+ freeNode(_storage[i]);
+ _storage[i] = NULL;
+ for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
// Look at the next table slot
- j = (j + 1) % _arrsize;
+ j = (5 * j + perturb + 1) & _mask;
// If the next slot is empty, we are done
- if (_arr[j] == NULL)
+ if (_storage[j] == NULL)
break;
// Compute the slot where the content of the next slot should normally be,
// assuming an empty table, and check whether we have to move it.
- uint k = _hash(_arr[j]->_key) % _arrsize;
+ uint k = _hash(_storage[j]->_key) & _mask;
if ((j > i && (k <= i || k > j)) ||
(j < i && (k <= i && k > j)) ) {
- _arr[i] = _arr[j];
+ _storage[i] = _storage[j];
i = j;
}
}
- _arr[i] = NULL;
- _nele--;
+ _storage[i] = NULL;
+ _size--;
return;
}
diff --git a/common/iff_container.h b/common/iff_container.h
index 9d477276fc..a70548abd4 100644
--- a/common/iff_container.h
+++ b/common/iff_container.h
@@ -162,7 +162,7 @@ public:
void incBytesRead(uint32 inc) {
bytesRead += inc;
if (bytesRead > size) {
- error("Chunk overead");
+ error("Chunk overread");
}
}
@@ -172,19 +172,23 @@ public:
bytesRead = 0;
}
+ bool hasReadAll() const {
+ return (size - bytesRead) == 0;
+ }
+
void feed() {
if (size % 2) {
size++;
}
- while (!_input->eos() && !eos()) {
+ while (!hasReadAll()) {
readByte();
}
}
// Common::ReadStream implementation
- bool eos() const {
- return (size - bytesRead) == 0;
- }
+ bool eos() const { return _input->eos(); }
+ bool err() const { return _input->err(); }
+ void clearErr() { _input->clearErr(); }
uint32 read(void *dataPtr, uint32 dataSize) {
incBytesRead(dataSize);
@@ -209,7 +213,7 @@ public:
_chunk.feed();
_formChunk.incBytesRead(_chunk.size);
- if (_formChunk.eos())
+ if (_formChunk.hasReadAll())
return 0;
_formChunk.incBytesRead(8);
diff --git a/common/keyboard.h b/common/keyboard.h
index 93579cbed6..9b6558dbff 100644
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -182,7 +182,7 @@ enum KeyCode {
};
/**
- * List of certan special and some fake 'ascii' values used in keyboard events.
+ * List of certain special and some fake 'ascii' values used in keyboard events.
* The values for the function keys listed here are based on what certain SCUMM
* games expect in their scripts.
* @todo Get rid of the function key values, and instead enforce that engines use
diff --git a/common/list.h b/common/list.h
index c4e7b47644..0372d217b7 100644
--- a/common/list.h
+++ b/common/list.h
@@ -209,6 +209,11 @@ public:
++i;
}
+ void pop_front() {
+ iterator i = begin();
+ i = erase(i);
+ }
+
List<t_T> &operator=(const List<t_T> &list) {
if (this != &list) {
diff --git a/common/md5.cpp b/common/md5.cpp
index edce9d8e4e..4eeb3d9a39 100644
--- a/common/md5.cpp
+++ b/common/md5.cpp
@@ -29,6 +29,7 @@
*/
#include "common/file.h"
+#include "common/fs.h"
#include "common/md5.h"
#include "common/util.h"
#include "common/endian.h"
@@ -256,8 +257,16 @@ bool md5_file(const FilesystemNode &file, uint8 digest[16], uint32 length) {
warning("md5_file: using a directory FilesystemNode");
return false;
}
+
+ ReadStream *stream = file.openForReading();
+ if (!stream) {
+ warning("md5_file: failed to open '%s'", file.getPath().c_str());
+ return false;
+ }
- return md5_file(file.getPath().c_str(), digest, length);
+ bool result = md5_file(*stream, digest, length);
+ delete stream;
+ return result;
}
bool md5_file(const char *name, uint8 digest[16], uint32 length) {
diff --git a/common/md5.h b/common/md5.h
index e7879dc6df..a8642b1322 100644
--- a/common/md5.h
+++ b/common/md5.h
@@ -26,11 +26,12 @@
#define COMMON_MD5_H
#include "common/scummsys.h"
-#include "common/fs.h"
-#include "common/stream.h"
namespace Common {
+class FilesystemNode;
+class ReadStream;
+
bool md5_file(const char *name, uint8 digest[16], uint32 length = 0);
bool md5_file(const FilesystemNode &file, uint8 digest[16], uint32 length = 0);
bool md5_file(ReadStream &stream, uint8 digest[16], uint32 length = 0);
diff --git a/common/memorypool.cpp b/common/memorypool.cpp
index f3dfb7975f..12307ba5d6 100644
--- a/common/memorypool.cpp
+++ b/common/memorypool.cpp
@@ -28,22 +28,6 @@
namespace Common {
-static const size_t CHUNK_PAGE_SIZE = 32;
-
-void* MemoryPool::allocPage() {
- void* result = ::malloc(CHUNK_PAGE_SIZE * _chunkSize);
- _pages.push_back(result);
- void* current = result;
- for (size_t i = 1; i < CHUNK_PAGE_SIZE; ++i) {
- void* next = ((char*)current + _chunkSize);
- *(void**)current = next;
-
- current = next;
- }
- *(void**)current = NULL;
- return result;
-}
-
MemoryPool::MemoryPool(size_t chunkSize) {
// You must at least fit the pointer in the node (technically unneeded considering the next rounding statement)
_chunkSize = MAX(chunkSize, sizeof(void*));
@@ -52,38 +36,68 @@ MemoryPool::MemoryPool(size_t chunkSize) {
_chunkSize = (_chunkSize + sizeof(void*) - 1) & (~(sizeof(void*) - 1));
_next = NULL;
+
+ _chunksPerPage = 8;
}
MemoryPool::~MemoryPool() {
- for (size_t i = 0; i<_pages.size(); ++i)
- ::free(_pages[i]);
+ for (size_t i = 0; i < _pages.size(); ++i)
+ ::free(_pages[i].start);
+}
+
+void MemoryPool::allocPage() {
+ Page page;
+
+ // Allocate a new page
+ page.numChunks = _chunksPerPage;
+ page.start = ::malloc(page.numChunks * _chunkSize);
+ assert(page.start);
+ _pages.push_back(page);
+
+ // Next time, we'll alocate a page twice as big as this one.
+ _chunksPerPage *= 2;
+
+ // Add the page to the pool of free chunk
+ addPageToPool(page);
+}
+
+void MemoryPool::addPageToPool(const Page &page) {
+
+ // Add all chunks of the new page to the linked list (pool) of free chunks
+ void *current = page.start;
+ for (size_t i = 1; i < page.numChunks; ++i) {
+ void *next = ((char*)current + _chunkSize);
+ *(void **)current = next;
+
+ current = next;
+ }
+
+ // Last chunk points to the old _next
+ *(void**)current = _next;
+
+ // From now on, the first free chunk is the first chunk of the new page
+ _next = page.start;
}
-void* MemoryPool::malloc() {
-#if 1
- if (!_next)
- _next = allocPage();
+void *MemoryPool::malloc() {
+ if (!_next) // No free chunks left? Allocate a new page
+ allocPage();
- void* result = _next;
+ assert(_next);
+ void *result = _next;
_next = *(void**)result;
return result;
-#else
- return ::malloc(_chunkSize);
-#endif
}
void MemoryPool::free(void* ptr) {
-#if 1
+ // Add the chunk back to (the start of) the list of free chunks
*(void**)ptr = _next;
_next = ptr;
-#else
- ::free(ptr);
-#endif
}
// Technically not compliant C++ to compare unrelated pointers. In practice...
-bool MemoryPool::isPointerInPage(void* ptr, void* page) {
- return (ptr >= page) && (ptr < (char*)page + CHUNK_PAGE_SIZE * _chunkSize);
+bool MemoryPool::isPointerInPage(void *ptr, const Page &page) {
+ return (ptr >= page.start) && (ptr < (char*)page.start + page.numChunks * _chunkSize);
}
void MemoryPool::freeUnusedPages() {
@@ -94,9 +108,10 @@ void MemoryPool::freeUnusedPages() {
numberOfFreeChunksPerPage[i] = 0;
}
- void* iterator = _next;
+ // Compute for each page how many chunks in it are still in use.
+ void *iterator = _next;
while (iterator) {
- // This should be a binary search
+ // TODO: This should be a binary search (requiring us to keep _pages sorted)
for (size_t i = 0; i < _pages.size(); ++i) {
if (isPointerInPage(iterator, _pages[i])) {
++numberOfFreeChunksPerPage[i];
@@ -106,12 +121,32 @@ void MemoryPool::freeUnusedPages() {
iterator = *(void**)iterator;
}
+ // Free all pages which are not in use.
+ // TODO: Might want to reset _chunksPerPage here (e.g. to the largest
+ // _pages[i].numChunks value still in use).
size_t freedPagesCount = 0;
- for (size_t i = 0; i < _pages.size(); ++i) {
- if (numberOfFreeChunksPerPage[i] == CHUNK_PAGE_SIZE) {
- ::free(_pages[i]);
- _pages[i] = NULL; // TODO : Remove NULL values
+ for (size_t i = 0; i < _pages.size(); ++i) {
+ if (numberOfFreeChunksPerPage[i] == _pages[i].numChunks) {
+ // Remove all chunks of this page from the list of free chunks
+ void **iter2 = &_next;
+ while (*iter2) {
+ if (isPointerInPage(*iter2, _pages[i]))
+ *iter2 = **(void***)iter2;
+ else
+ iter2 = *(void***)iter2;
+ }
+ ::free(_pages[i].start);
++freedPagesCount;
+ _pages[i].start = NULL;
+ }
+ }
+
+ for (size_t i = 0; i < _pages.size(); ) {
+ if (_pages[i].start == NULL) {
+ _pages.remove_at(i);
+ // We just removed an entry, so we do not advance "i"
+ } else {
+ ++i;
}
}
diff --git a/common/memorypool.h b/common/memorypool.h
index fcbacabc5c..dd2e8f13a4 100644
--- a/common/memorypool.h
+++ b/common/memorypool.h
@@ -32,26 +32,57 @@
namespace Common {
class MemoryPool {
-private:
+protected:
MemoryPool(const MemoryPool&);
MemoryPool& operator=(const MemoryPool&);
+
+ struct Page {
+ void *start;
+ size_t numChunks;
+ };
size_t _chunkSize;
- Array<void*> _pages;
- void* _next;
+ Array<Page> _pages;
+ void *_next;
+ size_t _chunksPerPage;
+
+ void allocPage();
+ void addPageToPool(const Page &page);
+ bool isPointerInPage(void *ptr, const Page &page);
- void* allocPage();
- bool isPointerInPage(void* ptr, void* page);
public:
MemoryPool(size_t chunkSize);
~MemoryPool();
- void* malloc();
- void free(void* ptr);
+ void *malloc();
+ void free(void *ptr);
void freeUnusedPages();
};
+template<size_t CHUNK_SIZE, size_t NUM_INTERNAL_CHUNKS = 32>
+class FixedSizeMemoryPool : public MemoryPool {
+private:
+ enum {
+ REAL_CHUNK_SIZE = (CHUNK_SIZE + sizeof(void*) - 1) & (~(sizeof(void*) - 1))
+ };
+
+ byte _storage[NUM_INTERNAL_CHUNKS * REAL_CHUNK_SIZE];
+public:
+ FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) {
+ assert(REAL_CHUNK_SIZE == _chunkSize);
+ // Insert some static storage
+ Page internalPage = { _storage, NUM_INTERNAL_CHUNKS };
+ addPageToPool(internalPage);
+ }
+};
+
+template<size_t CHUNK_SIZE>
+class FixedSizeMemoryPool<CHUNK_SIZE,0> : public MemoryPool {
+public:
+ FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) {}
+};
+
} // End of namespace Common
#endif
diff --git a/common/module.mk b/common/module.mk
index ed15bf75ea..e04af5270b 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -2,6 +2,7 @@ MODULE := common
MODULE_OBJS := \
advancedDetector.o \
+ archive.o \
config-file.o \
config-manager.o \
file.o \
diff --git a/common/ptr.h b/common/ptr.h
index c6fcaa4f75..99bc82a2d3 100644
--- a/common/ptr.h
+++ b/common/ptr.h
@@ -218,8 +218,4 @@ bool operator!=(const Common::SharedPtr<T1> &l, const Common::SharedPtr<T2> &r)
return l.get() != r.get();
}
-
#endif
-
-
-
diff --git a/common/queue.h b/common/queue.h
new file mode 100644
index 0000000000..f1881345e8
--- /dev/null
+++ b/common/queue.h
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2008-rtl/common/stack.h $
+ * $Id$
+ */
+
+#ifndef COMMON_QUEUE_H
+#define COMMON_QUEUE_H
+
+#include "common/scummsys.h"
+#include "common/list.h"
+
+namespace Common {
+
+/**
+ * Variable size Queue class, implemented using our List class.
+ */
+template<class T>
+class Queue {
+public:
+ typedef T value_type;
+
+public:
+ Queue<T>() : _impl() {}
+ Queue<T>(const Queue<T> &queue) : _impl(queue._impl) {}
+
+ Queue<T> &operator=(const Queue<T> &queue) {
+ _impl = queue._impl;
+ return *this;
+ }
+
+ bool empty() const {
+ return _impl.empty();
+ }
+
+ void clear() {
+ _impl.clear();
+ }
+
+ void push(const T &x) {
+ _impl.push_back(x);
+ }
+
+ T &front() {
+ return *_impl.begin();
+ }
+
+ const T &front() const {
+ return *_impl.begin();
+ }
+
+ T &back() {
+ return *_impl.reverse_begin();
+ }
+
+ const T &back() const {
+ return *_impl.reverse_begin();
+ }
+
+ T pop() {
+ T tmp = front();
+ _impl.pop_front();
+ return tmp;
+ }
+
+ int size() const {
+ return _impl.size();
+ }
+
+private:
+ List<T> _impl;
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/common/str.cpp b/common/str.cpp
index 5f8d4ffb7e..a415e376c9 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -34,28 +34,24 @@ const String String::emptyString;
const char *String::emptyString = "";
#endif
-static int computeCapacity(int len) {
- // By default, for the capacity we use the nearest multiple of 32
- // that leaves at least 16 chars of extra space (in case the string
- // grows a bit).
- // Finally, we subtract 1 to compensate for the trailing zero byte.
- len += 16;
- return ((len + 32 - 1) & ~0x1F) - 1;
+static uint32 computeCapacity(uint32 len) {
+ // By default, for the capacity we use the next multiple of 32
+ return ((len + 32 - 1) & ~0x1F);
}
-String::String(const char *str) : _len(0), _str(_storage) {
+String::String(const char *str) : _size(0), _str(_storage) {
if (str == 0) {
_storage[0] = 0;
- _len = 0;
+ _size = 0;
} else
initWithCStr(str, strlen(str));
}
-String::String(const char *str, uint32 len) : _len(0), _str(_storage) {
+String::String(const char *str, uint32 len) : _size(0), _str(_storage) {
initWithCStr(str, len);
}
-String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) {
+String::String(const char *beginP, const char *endP) : _size(0), _str(_storage) {
assert(endP >= beginP);
initWithCStr(beginP, endP - beginP);
}
@@ -67,13 +63,13 @@ void String::initWithCStr(const char *str, uint32 len) {
// for GCC 2.95.x compatibility (see also tracker item #1602879).
_storage[0] = 0;
- _len = len;
+ _size = len;
if (len >= _builtinCapacity) {
// Not enough internal storage, so allocate more
- _extern._capacity = computeCapacity(len);
+ _extern._capacity = computeCapacity(len+1);
_extern._refCount = 0;
- _str = (char *)malloc(_extern._capacity+1);
+ _str = (char *)malloc(_extern._capacity);
assert(_str != 0);
}
@@ -83,10 +79,10 @@ void String::initWithCStr(const char *str, uint32 len) {
}
String::String(const String &str)
- : _len(str._len), _str(str.isStorageIntern() ? _storage : str._str) {
+ : _size(str._size), _str(str.isStorageIntern() ? _storage : str._str) {
if (str.isStorageIntern()) {
// String in internal storage: just copy it
- memcpy(_storage, str._storage, _builtinCapacity);
+ memcpy(_storage, str._storage, sizeof(_storage));
} else {
// String in external storage: use refcount mechanism
str.incRefCount();
@@ -97,14 +93,14 @@ String::String(const String &str)
}
String::String(char c)
-: _len(0), _str(_storage) {
+: _size(0), _str(_storage) {
_storage[0] = c;
_storage[1] = 0;
// TODO/FIXME: There is no reason for the following check -- we *do*
// allow strings to contain 0 bytes!
- _len = (c == 0) ? 0 : 1;
+ _size = (c == 0) ? 0 : 1;
}
String::~String() {
@@ -112,16 +108,16 @@ String::~String() {
}
void String::makeUnique() {
- ensureCapacity(_len, true);
+ ensureCapacity(_size, true);
}
/**
- * Ensure that enough storage is available to store at least new_len
+ * Ensure that enough storage is available to store at least new_size
* characters plus a null byte. In addition, if we currently share
* the storage with another string, unshare it, so that we can safely
* write to the storage.
*/
-void String::ensureCapacity(uint32 new_len, bool keep_old) {
+void String::ensureCapacity(uint32 new_size, bool keep_old) {
bool isShared;
uint32 curCapacity, newCapacity;
char *newStorage;
@@ -129,7 +125,7 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) {
if (isStorageIntern()) {
isShared = false;
- curCapacity = _builtinCapacity - 1;
+ curCapacity = _builtinCapacity;
} else {
isShared = (oldRefCount && *oldRefCount > 1);
curCapacity = _extern._capacity;
@@ -137,30 +133,30 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) {
// Special case: If there is enough space, and we do not share
// the storage, then there is nothing to do.
- if (!isShared && new_len <= curCapacity)
+ if (!isShared && new_size < curCapacity)
return;
- if (isShared && new_len <= _builtinCapacity - 1) {
+ if (isShared && new_size < _builtinCapacity) {
// We share the storage, but there is enough internal storage: Use that.
newStorage = _storage;
- newCapacity = _builtinCapacity - 1;
+ newCapacity = _builtinCapacity;
} else {
// We need to allocate storage on the heap!
// Compute a suitable new capacity limit
- newCapacity = computeCapacity(new_len);
+ newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
// Allocate new storage
- newStorage = (char *)malloc(newCapacity+1);
+ newStorage = (char *)malloc(newCapacity);
assert(newStorage);
}
// Copy old data if needed, elsewise reset the new storage.
if (keep_old) {
- assert(_len <= newCapacity);
- memcpy(newStorage, _str, _len + 1);
+ assert(_size < newCapacity);
+ memcpy(newStorage, _str, _size + 1);
} else {
- _len = 0;
+ _size = 0;
newStorage[0] = 0;
}
@@ -210,7 +206,7 @@ void String::decRefCount(int *oldRefCount) {
String& String::operator =(const char *str) {
uint32 len = strlen(str);
ensureCapacity(len, false);
- _len = len;
+ _size = len;
memmove(_str, str, len + 1);
return *this;
}
@@ -221,16 +217,16 @@ String &String::operator =(const String &str) {
if (str.isStorageIntern()) {
decRefCount(_extern._refCount);
- _len = str._len;
+ _size = str._size;
_str = _storage;
- memcpy(_str, str._str, _len + 1);
+ memcpy(_str, str._str, _size + 1);
} else {
str.incRefCount();
decRefCount(_extern._refCount);
_extern._refCount = str._extern._refCount;
_extern._capacity = str._extern._capacity;
- _len = str._len;
+ _size = str._size;
_str = str._str;
}
@@ -240,7 +236,7 @@ String &String::operator =(const String &str) {
String& String::operator =(char c) {
decRefCount(_extern._refCount);
_str = _storage;
- _len = 1;
+ _size = 1;
_str[0] = c;
_str[1] = 0;
return *this;
@@ -249,30 +245,30 @@ String& String::operator =(char c) {
String &String::operator +=(const char *str) {
int len = strlen(str);
if (len > 0) {
- ensureCapacity(_len + len, true);
+ ensureCapacity(_size + len, true);
- memcpy(_str + _len, str, len + 1);
- _len += len;
+ memcpy(_str + _size, str, len + 1);
+ _size += len;
}
return *this;
}
String &String::operator +=(const String &str) {
- int len = str._len;
+ int len = str._size;
if (len > 0) {
- ensureCapacity(_len + len, true);
+ ensureCapacity(_size + len, true);
- memcpy(_str + _len, str._str, len + 1);
- _len += len;
+ memcpy(_str + _size, str._str, len + 1);
+ _size += len;
}
return *this;
}
String &String::operator +=(char c) {
- ensureCapacity(_len + 1, true);
+ ensureCapacity(_size + 1, true);
- _str[_len++] = c;
- _str[_len] = 0;
+ _str[_size++] = c;
+ _str[_size] = 0;
return *this;
}
@@ -293,10 +289,10 @@ bool String::hasPrefix(const char *x) const {
bool String::hasSuffix(const char *x) const {
assert(x != 0);
// Compare x with the end of _str.
- const uint32 x_len = strlen(x);
- if (x_len > _len)
+ const uint32 x_size = strlen(x);
+ if (x_size > _size)
return false;
- const char *y = c_str() + _len - x_len;
+ const char *y = c_str() + _size - x_size;
while (*x && *x == *y) {
++x;
++y;
@@ -315,66 +311,74 @@ bool String::contains(char x) const {
return strchr(c_str(), x) != NULL;
}
+bool String::matchString(const char *pat) const {
+ return Common::matchString(c_str(), pat);
+}
+
+bool String::matchString(const String &pat) const {
+ return Common::matchString(c_str(), pat.c_str());
+}
+
void String::deleteLastChar() {
- deleteChar(_len - 1);
+ deleteChar(_size - 1);
}
void String::deleteChar(uint32 p) {
- assert(p < _len);
+ assert(p < _size);
makeUnique();
- while (p++ < _len)
+ while (p++ < _size)
_str[p-1] = _str[p];
- _len--;
+ _size--;
}
void String::clear() {
decRefCount(_extern._refCount);
- _len = 0;
+ _size = 0;
_str = _storage;
_storage[0] = 0;
}
void String::setChar(char c, uint32 p) {
- assert(p <= _len);
+ assert(p <= _size);
makeUnique();
_str[p] = c;
}
void String::insertChar(char c, uint32 p) {
- assert(p <= _len);
+ assert(p <= _size);
- ensureCapacity(_len + 1, true);
- _len++;
- for (uint32 i = _len; i > p; --i)
+ ensureCapacity(_size + 1, true);
+ _size++;
+ for (uint32 i = _size; i > p; --i)
_str[i] = _str[i-1];
_str[p] = c;
}
void String::toLowercase() {
makeUnique();
- for (uint32 i = 0; i < _len; ++i)
+ for (uint32 i = 0; i < _size; ++i)
_str[i] = tolower(_str[i]);
}
void String::toUppercase() {
makeUnique();
- for (uint32 i = 0; i < _len; ++i)
+ for (uint32 i = 0; i < _size; ++i)
_str[i] = toupper(_str[i]);
}
void String::trim() {
- if (_len == 0)
+ if (_size == 0)
return;
makeUnique();
// Trim trailing whitespace
- while (_len >= 1 && isspace(_str[_len-1]))
- _len--;
- _str[_len] = 0;
+ while (_size >= 1 && isspace(_str[_size-1]))
+ _size--;
+ _str[_size] = 0;
// Trim leading whitespace
char *t = _str;
@@ -382,8 +386,8 @@ void String::trim() {
t++;
if (t != _str) {
- _len -= t - _str;
- memmove(_str, t, _len + 1);
+ _size -= t - _str;
+ memmove(_str, t, _size + 1);
}
}
@@ -524,4 +528,112 @@ char *trim(char *t) {
return rtrim(ltrim(t));
}
+Common::String lastPathComponent(const Common::String &path, const char sep) {
+ const char *str = path.c_str();
+ const char *last = str + path.size();
+
+ // Skip over trailing slashes
+ while (last > str && *(last-1) == sep)
+ --last;
+
+ // Path consisted of only slashes -> return empty string
+ if (last == str)
+ return Common::String();
+
+ // Now scan the whole component
+ const char *first = last - 1;
+ while (first >= str && *first != sep)
+ --first;
+
+ if (*first == sep)
+ first++;
+
+ return Common::String(first, last);
+}
+
+Common::String normalizePath(const Common::String &path, const char sep) {
+ if (path.empty())
+ return path;
+
+ const char *cur = path.c_str();
+ Common::String result;
+
+ // If there is a leading slash, preserve that:
+ if (*cur == sep) {
+ result += sep;
+ while (*cur == sep)
+ ++cur;
+ }
+
+ // Scan till the end of the String
+ while (*cur != 0) {
+ const char *start = cur;
+
+ // Scan till the next path separator resp. the end of the string
+ while (*cur != sep && *cur != 0)
+ cur++;
+
+ const Common::String component(start, cur);
+
+ // Skip empty components and dot components, add all others
+ if (!component.empty() && component != ".") {
+ // Add a separator before the component, unless the result
+ // string already ends with one (which happens only if the
+ // path *starts* with a separator).
+ if (!result.empty() && result.lastChar() != sep)
+ result += sep;
+
+ // Add the component
+ result += component;
+ }
+
+ // Skip over separator chars
+ while (*cur == sep)
+ cur++;
+ }
+
+ return result;
+}
+
+bool matchString(const char *str, const char *pat) {
+ assert(str);
+ assert(pat);
+
+ const char *p = 0;
+ const char *q = 0;
+
+ for (;;) {
+ switch (*pat) {
+ case '*':
+ // Record pattern / string possition for backtracking
+ p = ++pat;
+ q = str;
+ // If pattern ended with * -> match
+ if (!*pat)
+ return true;
+ break;
+
+ default:
+ if (*pat != *str) {
+ if (p) {
+ // No match, oops -> try to backtrack
+ pat = p;
+ str = ++q;
+ if (!*str)
+ return !*pat;
+ break;
+ }
+ else
+ return false;
+ }
+ // fallthrough
+ case '?':
+ if (!*str)
+ return !*pat;
+ pat++;
+ str++;
+ }
+ }
+}
+
} // End of namespace Common
diff --git a/common/str.h b/common/str.h
index 3479fee8e4..20914c1f1f 100644
--- a/common/str.h
+++ b/common/str.h
@@ -61,7 +61,7 @@ protected:
* a lot. Yes, we limit ourselves to strings shorter than 4GB --
* on purpose :-).
*/
- uint32 _len;
+ uint32 _size;
/**
* Pointer to the actual string storage. Either points to _storage,
@@ -97,7 +97,7 @@ public:
#endif
/** Construct a new empty string. */
- String() : _len(0), _str(_storage) { _storage[0] = 0; }
+ String() : _size(0), _str(_storage) { _storage[0] = 0; }
/** Construct a new string from the given NULL-terminated C string. */
String(const char *str);
@@ -149,14 +149,38 @@ public:
bool contains(const char *x) const;
bool contains(char x) const;
+ /**
+ * Simple DOS-style pattern matching function (understands * and ? like used in DOS).
+ * Taken from exult/files/listfiles.cc
+ *
+ * Token meaning:
+ * "*": any character, any amount of times.
+ * "?": any character, only once.
+ *
+ * Example strings/patterns:
+ * String: monkey.s01 Pattern: monkey.s?? => true
+ * String: monkey.s101 Pattern: monkey.s?? => false
+ * String: monkey.s99 Pattern: monkey.s?1 => false
+ * String: monkey.s101 Pattern: monkey.s* => true
+ * String: monkey.s99 Pattern: monkey.s*1 => false
+ *
+ * @param str Text to be matched against the given pattern.
+ * @param pat Glob pattern.
+ *
+ * @return true if str matches the pattern, false otherwise.
+ */
+ bool matchString(const char *pat) const;
+ bool matchString(const String &pat) const;
+
+
inline const char *c_str() const { return _str; }
- inline uint size() const { return _len; }
+ inline uint size() const { return _size; }
- inline bool empty() const { return (_len == 0); }
- char lastChar() const { return (_len > 0) ? _str[_len-1] : 0; }
+ inline bool empty() const { return (_size == 0); }
+ char lastChar() const { return (_size > 0) ? _str[_size-1] : 0; }
char operator [](int idx) const {
- assert(_str && idx >= 0 && idx < (int)_len);
+ assert(_str && idx >= 0 && idx < (int)_size);
return _str[idx];
}
@@ -172,11 +196,19 @@ public:
/** Set character c at position p. */
void insertChar(char c, uint32 p);
+ /** Clears the string, making it empty. */
void clear();
+ /** Convert all characters in the string to lowercase. */
void toLowercase();
+
+ /** Convert all characters in the string to uppercase. */
void toUppercase();
+ /**
+ * Removes trailing and leading whitespaces. Uses isspace() to decide
+ * what is whitespace and what not.
+ */
void trim();
uint hash() const;
@@ -203,7 +235,7 @@ public:
protected:
void makeUnique();
- void ensureCapacity(uint32 new_len, bool keep_old);
+ void ensureCapacity(uint32 new_size, bool keep_old);
void incRefCount() const;
void decRefCount(int *oldRefCount);
void initWithCStr(const char *str, uint32 len);
@@ -218,7 +250,7 @@ String operator +(const String &x, const char *y);
String operator +(const String &x, char y);
String operator +(char x, const String &y);
-// Some useful additional comparision operators for Strings
+// Some useful additional comparison operators for Strings
bool operator == (const char *x, const String &y);
bool operator != (const char *x, const String &y);
@@ -227,16 +259,67 @@ extern char *ltrim(char *t);
extern char *rtrim(char *t);
extern char *trim(char *t);
+
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return 'bar.txt'
+ * /foo/bar/ would return 'bar'
+ * /foo/./bar// would return 'bar'
+ *
+ * @param path the path of which we want to know the last component
+ * @param sep character used to separate path components
+ * @return The last component of the path.
+ */
+Common::String lastPathComponent(const Common::String &path, const char sep);
+
+/**
+ * Normalize a gien path to a canonical form. In particular:
+ * - trailing separators are removed: /foo/bar/ -> /foo/bar
+ * - double separators (= empty components) are removed: /foo//bar -> /foo/bar
+ * - dot components are removed: /foo/./bar -> /foo/bar
+ *
+ * @todo remove double dot components: /foo/baz/../bar -> /foo/bar
+ *
+ * @param path the path to normalize
+ * @param sep the separator token (usually '/' on Unix-style systems, or '\\' on Windows based stuff)
+ * @return the normalized path
+ */
+Common::String normalizePath(const Common::String &path, const char sep);
+
+
+/**
+ * Simple DOS-style pattern matching function (understands * and ? like used in DOS).
+ * Taken from exult/files/listfiles.cc
+ *
+ * Token meaning:
+ * "*": any character, any amount of times.
+ * "?": any character, only once.
+ *
+ * Example strings/patterns:
+ * String: monkey.s01 Pattern: monkey.s?? => true
+ * String: monkey.s101 Pattern: monkey.s?? => false
+ * String: monkey.s99 Pattern: monkey.s?1 => false
+ * String: monkey.s101 Pattern: monkey.s* => true
+ * String: monkey.s99 Pattern: monkey.s*1 => false
+ *
+ * @param str Text to be matched against the given pattern.
+ * @param pat Glob pattern.
+ *
+ * @return true if str matches the pattern, false otherwise.
+ */
+bool matchString(const char *str, const char *pat);
+
+
class StringList : public Array<String> {
public:
void push_back(const char *str) {
- ensureCapacity(_size + 1);
- _data[_size++] = str;
+ Array<String>::push_back(str);
}
void push_back(const String &str) {
- ensureCapacity(_size + 1);
- _data[_size++] = str;
+ Array<String>::push_back(str);
}
};
diff --git a/common/stream.cpp b/common/stream.cpp
index e06cc28415..9bcc29550f 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -43,8 +43,10 @@ MemoryReadStream *ReadStream::readStream(uint32 dataSize) {
uint32 MemoryReadStream::read(void *dataPtr, uint32 dataSize) {
// Read at most as many bytes as are still available...
- if (dataSize > _size - _pos)
+ if (dataSize > _size - _pos) {
dataSize = _size - _pos;
+ _eos = true;
+ }
memcpy(dataPtr, _ptr, dataSize);
if (_encbyte) {
@@ -60,7 +62,7 @@ uint32 MemoryReadStream::read(void *dataPtr, uint32 dataSize) {
return dataSize;
}
-void MemoryReadStream::seek(int32 offs, int whence) {
+bool MemoryReadStream::seek(int32 offs, int whence) {
// Pre-Condition
assert(_pos <= _size);
switch (whence) {
@@ -81,12 +83,16 @@ void MemoryReadStream::seek(int32 offs, int whence) {
}
// Post-Condition
assert(_pos <= _size);
+
+ // Reset end-of-stream flag on a successful seek
+ _eos = false;
+ return true; // FIXME: STREAM REWRITE
}
#define LF 0x0A
#define CR 0x0D
-char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
+char *SeekableReadStream::readLine_OLD(char *buf, size_t bufSize) {
assert(buf && bufSize > 0);
char *p = buf;
size_t len = 0;
@@ -156,19 +162,27 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
// If end-of-file occurs before any characters are read, return NULL
// and the buffer contents remain unchanged.
- if (eos() || ioFailed()) {
+ if (eos() || err()) {
return 0;
}
- // Loop as long as the stream has not ended, there is still free
- // space in the buffer, and the line has not ended
- while (!eos() && len + 1 < bufSize && c != LF) {
+ // Loop as long as there is still free space in the buffer,
+ // and the line has not ended
+ while (len + 1 < bufSize && c != LF) {
c = readByte();
-
- // If end-of-file occurs before any characters are read, return
- // NULL and the buffer contents remain unchanged. If an error
- /// occurs, return NULL and the buffer contents are indeterminate.
- if (ioFailed() || (len == 0 && eos()))
+
+ if (eos()) {
+ // If end-of-file occurs before any characters are read, return
+ // NULL and the buffer contents remain unchanged.
+ if (len == 0)
+ return 0;
+
+ break;
+ }
+
+ // If an error occurs, return NULL and the buffer contents
+ // are indeterminate.
+ if (err())
return 0;
// Check for CR or CR/LF
@@ -178,8 +192,18 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
if (c == CR) {
// Look at the next char -- is it LF? If not, seek back
c = readByte();
- if (c != LF && !eos())
+
+ if (err()) {
+ return 0; // error: the buffer contents are indeterminate
+ }
+ if (eos()) {
+ // The CR was the last character in the file.
+ // Reset the eos() flag since we successfully finished a line
+ clearErr();
+ } else if (c != LF) {
seek(-1, SEEK_CUR);
+ }
+
// Treat CR & CR/LF as plain LF
c = LF;
}
@@ -188,25 +212,37 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
len++;
}
- // FIXME:
- // This should fix a bug while using readLine with Common::File
- // it seems that it sets the eos flag after an invalid read
- // and at the same time the ioFailed flag
- // the config file parser fails out of that reason for the new themes
- if (eos()) {
- clearIOFailed();
- }
-
// We always terminate the buffer if no error occured
*p = 0;
return buf;
}
+String SeekableReadStream::readLine() {
+ // Read a line
+ String line;
+ while (line.lastChar() != '\n') {
+ char buf[256];
+ if (!readLine_NEW(buf, 256))
+ break;
+ line += buf;
+ }
+
+ if (line.lastChar() == '\n')
+ line.deleteLastChar();
+
+ return line;
+}
+
+
uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
- dataSize = MIN(dataSize, _end - _pos);
+ if (dataSize > _end - _pos) {
+ dataSize = _end - _pos;
+ _eos = true;
+ }
dataSize = _parentStream->read(dataPtr, dataSize);
+ _eos |= _parentStream->eos();
_pos += dataSize;
return dataSize;
@@ -219,9 +255,10 @@ SeekableSubReadStream::SeekableSubReadStream(SeekableReadStream *parentStream, u
assert(_begin <= _end);
_pos = _begin;
_parentStream->seek(_pos);
+ _eos = false;
}
-void SeekableSubReadStream::seek(int32 offset, int whence) {
+bool SeekableSubReadStream::seek(int32 offset, int whence) {
assert(_pos >= _begin);
assert(_pos <= _end);
@@ -239,7 +276,10 @@ void SeekableSubReadStream::seek(int32 offset, int whence) {
assert(_pos >= _begin);
assert(_pos <= _end);
- _parentStream->seek(_pos);
+ bool ret = _parentStream->seek(_pos);
+ if (ret) _eos = false; // reset eos on successful seek
+
+ return ret;
}
BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize, bool disposeParentStream)
@@ -304,7 +344,7 @@ BufferedSeekableReadStream::BufferedSeekableReadStream(SeekableReadStream *paren
_parentStream(parentStream) {
}
-void BufferedSeekableReadStream::seek(int32 offset, int whence) {
+bool BufferedSeekableReadStream::seek(int32 offset, int whence) {
// If it is a "local" seek, we may get away with "seeking" around
// in the buffer only.
// Note: We could try to handle SEEK_END and SEEK_SET, too, but
@@ -319,6 +359,8 @@ void BufferedSeekableReadStream::seek(int32 offset, int whence) {
_pos = _bufSize;
_parentStream->seek(offset, whence);
}
+
+ return true; // FIXME: STREAM REWRITE
}
} // End of namespace Common
diff --git a/common/stream.h b/common/stream.h
index 01a946e685..02677e0dbb 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -41,19 +41,30 @@ public:
virtual ~Stream() {}
/**
- * Returns true if any I/O failure occurred.
- * This flag is never cleared automatically. In order to clear it,
- * client code has to call clearIOFailed() explicitly.
- *
- * @todo Instead of returning a plain bool, maybe we should define
- * a list of error codes which can be returned here.
+ * DEPRECATED: Use err() or eos() instead.
+ * Returns true if any I/O failure occurred or the end of the
+ * stream was reached while reading.
*/
- virtual bool ioFailed() const { return false; }
+ virtual bool ioFailed() const { return err(); }
/**
+ * DEPRECATED: Don't use this unless you are still using ioFailed().
* Reset the I/O error status.
*/
- virtual void clearIOFailed() {}
+ virtual void clearIOFailed() { clearErr(); }
+
+ /**
+ * Returns true if an I/O failure occurred.
+ * This flag is never cleared automatically. In order to clear it,
+ * client code has to call clearErr() explicitly.
+ */
+ virtual bool err() const { return false; }
+
+ /**
+ * Reset the I/O error status as returned by err().
+ * For a ReadStream, also reset the end-of-stream status returned by eos().
+ */
+ virtual void clearErr() {}
};
/**
@@ -75,8 +86,10 @@ public:
* Commit any buffered data to the underlying channel or
* storage medium; unbuffered streams can use the default
* implementation.
+ *
+ * @return true on success, false in case of a failure
*/
- virtual void flush() {}
+ virtual bool flush() { return true; }
/**
* Finalize and close this stream. To be called right before this
@@ -85,7 +98,7 @@ public:
* closing (and this flushing, if buffered) the stream.
*
* After this method has been called, no further writes may be
- * peformed on the stream. Calling ioFailed() is allowed.
+ * performed on the stream. Calling err() is allowed.
*
* By default, this just flushes the stream.
*/
@@ -151,7 +164,9 @@ public:
class ReadStream : virtual public Stream {
public:
/**
- * Returns true if the end of the stream has been reached.
+ * Returns true if a read failed because the stream has been reached.
+ * This flag is cleared by clearErr().
+ * For a SeekableReadStream, it is also cleared by a successful seek.
*/
virtual bool eos() const = 0;
@@ -167,13 +182,19 @@ public:
// The remaining methods all have default implementations; subclasses
- // need not (and should not) overload them.
+ // in general should not overload them.
/**
- * Read am unsigned byte from the stream and return it.
+ * DEPRECATED
+ * Default implementation for backward compatibility
+ */
+ virtual bool ioFailed() { return (eos() || err()); }
+
+ /**
+ * Read an unsigned byte from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
byte readByte() {
byte b = 0;
@@ -185,7 +206,7 @@ public:
* Read a signed byte from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
int8 readSByte() {
int8 b = 0;
@@ -198,7 +219,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
uint16 readUint16LE() {
uint16 a = readByte();
@@ -211,7 +232,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
uint32 readUint32LE() {
uint32 a = readUint16LE();
@@ -224,7 +245,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
uint16 readUint16BE() {
uint16 b = readByte();
@@ -237,7 +258,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
uint32 readUint32BE() {
uint32 b = readUint16BE();
@@ -250,7 +271,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
int16 readSint16LE() {
return (int16)readUint16LE();
@@ -261,7 +282,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
int32 readSint32LE() {
return (int32)readUint32LE();
@@ -272,7 +293,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
int16 readSint16BE() {
return (int16)readUint16BE();
@@ -283,7 +304,7 @@ public:
* from the stream and return it.
* Performs no error checking. The return value is undefined
* if a read error occurred (for which client code can check by
- * calling ioFailed()).
+ * calling err() and eos() ).
*/
int32 readSint32BE() {
return (int32)readUint32BE();
@@ -293,7 +314,9 @@ public:
* Read the specified amount of data into a malloc'ed buffer
* which then is wrapped into a MemoryReadStream.
* The returned stream might contain less data than requested,
- * if reading more failed.
+ * if reading more failed, because of an I/O error or because
+ * the end of the stream was reached. Which can be determined by
+ * calling err() and eos().
*/
MemoryReadStream *readStream(uint32 dataSize);
@@ -303,57 +326,89 @@ public:
/**
* Interface for a seekable & readable data stream.
*
- * @todo We really need better error handling here!
- * Like seek should somehow indicate whether it failed.
+ * @todo Get rid of SEEK_SET, SEEK_CUR, or SEEK_END, use our own constants
*/
class SeekableReadStream : virtual public ReadStream {
public:
- virtual uint32 pos() const = 0;
- virtual uint32 size() const = 0;
-
- virtual void seek(int32 offset, int whence = SEEK_SET) = 0;
-
- void skip(uint32 offset) { seek(offset, SEEK_CUR); }
-
/**
- * Read one line of text from a CR or CR/LF terminated plain text file.
- * This method is a rough analog of the (f)gets function.
+ * Obtains the current value of the stream position indicator of the
+ * stream.
*
- * @bug A main difference (and flaw) in this function is that there is no
- * way to detect that a line exceeeds the length of the buffer.
- * Code which needs this should use the new readLine_NEW() method instead.
+ * @return the current position indicator, or -1 if an error occurred.
+ */
+ virtual int32 pos() const = 0;
+
+ /**
+ * Obtains the total size of the stream, measured in bytes.
+ * If this value is unknown or can not be computed, -1 is returned.
*
- * @param buf the buffer to store into
- * @param bufSize the size of the buffer
- * @return a pointer to the read string, or NULL if an error occurred
+ * @return the size of the stream, or -1 if an error occurred
+ */
+ virtual int32 size() const = 0;
+
+ /**
+ * Sets the stream position indicator for the stream. The new position,
+ * measured in bytes, is obtained by adding offset bytes to the position
+ * specified by whence. If whence is set to SEEK_SET, SEEK_CUR, or
+ * SEEK_END, the offset is relative to the start of the file, the current
+ * position indicator, or end-of-file, respectively. A successful call
+ * to the seek() method clears the end-of-file indicator for the stream.
*
- * @note The line terminator (CR or CR/LF) is stripped and not inserted
- * into the buffer.
+ * @param offset the relative offset in bytes
+ * @param whence the seek reference: SEEK_SET, SEEK_CUR, or SEEK_END
+ * @return true on success, false in case of a failure
+ */
+ virtual bool seek(int32 offset, int whence = SEEK_SET) = 0;
+
+ /**
+ * TODO: Get rid of this??? Or keep it and document it
+ * @return true on success, false in case of a failure
+ */
+ virtual bool skip(uint32 offset) { return seek(offset, SEEK_CUR); }
+
+ /**
+ * DEPRECATED: Do not use this method! Instead use readLine_NEW() or readline().
*/
- virtual char *readLine(char *buf, size_t bufSize);
+ virtual char *readLine_OLD(char *buf, size_t bufSize);
/**
* Reads at most one less than the number of characters specified
* by bufSize from the and stores them in the string buf. Reading
- * stops when the end of a line is reached (CR, CR/LF or LF), at
- * end-of-file or error. The newline, if any, is retained (CR and
- * CR/LF are translated to LF = 0xA = '\n'). If any characters are
- * read and there is no error, a `\0' character is appended to end
- * the string.
+ * stops when the end of a line is reached (CR, CR/LF or LF), and
+ * at end-of-file or error. The newline, if any, is retained (CR
+ * and CR/LF are translated to LF = 0xA = '\n'). If any characters
+ * are read and there is no error, a `\0' character is appended
+ * to end the string.
*
* Upon successful completion, return a pointer to the string. If
* end-of-file occurs before any characters are read, returns NULL
* and the buffer contents remain unchanged. If an error occurs,
* returns NULL and the buffer contents are indeterminate.
* This method does not distinguish between end-of-file and error;
- * callers muse use ioFailed() or eos() to determine which occurred.
+ * callers must use err() or eos() to determine which occurred.
+ *
+ * @note This methods is closely modeled after the standard fgets()
+ * function from stdio.h.
*
* @param buf the buffer to store into
* @param bufSize the size of the buffer
* @return a pointer to the read string, or NULL if an error occurred
*/
virtual char *readLine_NEW(char *s, size_t bufSize);
+
+
+ /**
+ * Reads a full line and returns it as a Common::String. Reading
+ * stops when the end of a line is reached (CR, CR/LF or LF), and
+ * at end-of-file or error.
+ *
+ * Upon successful completion, return a string with the content
+ * of the line, *without* the end of a line marker. This method
+ * does not indicate whether an error occured. Callers muse use
+ * ioFailed() or eos() to determine whether an exception occurred.
+ */
+ virtual String readLine();
};
/**
@@ -369,19 +424,23 @@ protected:
bool _disposeParentStream;
uint32 _pos;
uint32 _end;
+ bool _eos;
public:
SubReadStream(ReadStream *parentStream, uint32 end, bool disposeParentStream = false)
: _parentStream(parentStream),
_disposeParentStream(disposeParentStream),
_pos(0),
- _end(end) {
+ _end(end),
+ _eos(false) {
assert(parentStream);
}
~SubReadStream() {
if (_disposeParentStream) delete _parentStream;
}
- virtual bool eos() const { return _pos == _end; }
+ virtual bool eos() const { return _eos; }
+ virtual bool err() const { return _parentStream->err(); }
+ virtual void clearErr() { _eos = false; _parentStream->clearErr(); }
virtual uint32 read(void *dataPtr, uint32 dataSize);
};
@@ -397,10 +456,10 @@ protected:
public:
SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool disposeParentStream = false);
- virtual uint32 pos() const { return _pos - _begin; }
- virtual uint32 size() const { return _end - _begin; }
+ virtual int32 pos() const { return _pos - _begin; }
+ virtual int32 size() const { return _end - _begin; }
- virtual void seek(int32 offset, int whence = SEEK_SET);
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
};
/**
@@ -453,6 +512,8 @@ public:
virtual bool eos() const { return (_pos == _bufSize) && _parentStream->eos(); }
virtual bool ioFailed() const { return _parentStream->ioFailed(); }
virtual void clearIOFailed() { _parentStream->clearIOFailed(); }
+ virtual bool err() const { return _parentStream->err(); }
+ virtual void clearErr() { _parentStream->clearErr(); }
virtual uint32 read(void *dataPtr, uint32 dataSize);
};
@@ -467,10 +528,10 @@ protected:
public:
BufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, bool disposeParentStream = false);
- virtual uint32 pos() const { return _parentStream->pos() - (_bufSize - _pos); }
- virtual uint32 size() const { return _parentStream->size(); }
+ virtual int32 pos() const { return _parentStream->pos() - (_bufSize - _pos); }
+ virtual int32 size() const { return _parentStream->size(); }
- virtual void seek(int32 offset, int whence = SEEK_SET);
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
};
@@ -487,6 +548,7 @@ private:
uint32 _pos;
byte _encbyte;
bool _disposeMemory;
+ bool _eos;
public:
@@ -501,7 +563,8 @@ public:
_size(dataSize),
_pos(0),
_encbyte(0),
- _disposeMemory(disposeMemory) {}
+ _disposeMemory(disposeMemory),
+ _eos(false) {}
~MemoryReadStream() {
if (_disposeMemory)
@@ -512,11 +575,13 @@ public:
uint32 read(void *dataPtr, uint32 dataSize);
- bool eos() const { return _pos == _size; }
- uint32 pos() const { return _pos; }
- uint32 size() const { return _size; }
+ bool eos() const { return _eos; }
+ void clearErr() { _eos = false; }
+
+ int32 pos() const { return _pos; }
+ int32 size() const { return _size; }
- void seek(int32 offs, int whence = SEEK_SET);
+ bool seek(int32 offs, int whence = SEEK_SET);
};
@@ -569,7 +634,6 @@ public:
return dataSize;
}
- bool eos() const { return _pos == _bufSize; }
uint32 pos() const { return _pos; }
uint32 size() const { return _bufSize; }
};
@@ -623,7 +687,6 @@ public:
return dataSize;
}
- bool eos() const { return false; }
uint32 pos() const { return _pos; }
uint32 size() const { return _size; }
diff --git a/common/system.cpp b/common/system.cpp
index d0548cdd2d..d9bc027e91 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -115,7 +115,8 @@ Common::EventManager *OSystem::getEventManager() {
void OSystem::clearScreen() {
Graphics::Surface *screen = lockScreen();
- memset(screen->pixels, 0, screen->h * screen->pitch);
+ if (screen && screen->pixels)
+ memset(screen->pixels, 0, screen->h * screen->pitch);
unlockScreen();
}
@@ -125,10 +126,9 @@ FIXME: The config file loading code below needs to be cleaned up.
Port specific variants should be pushed into the respective ports.
Ideally, the default OSystem::openConfigFileForReading/Writing methods
- should be removed completely.
+ should be removed completely.
*/
-#include "common/file.h"
#ifdef __PLAYSTATION2__
#include "backends/platform/ps2/systemps2.h"
@@ -163,7 +163,7 @@ static Common::String getDefaultConfigFileName() {
}
Common::SeekableReadStream *OSystem::openConfigFileForReading() {
- FilesystemNode file(getDefaultConfigFileName());
+ Common::FilesystemNode file(getDefaultConfigFileName());
return file.openForReading();
}
@@ -171,7 +171,7 @@ Common::WriteStream *OSystem::openConfigFileForWriting() {
#ifdef __DC__
return 0;
#else
- FilesystemNode file(getDefaultConfigFileName());
+ Common::FilesystemNode file(getDefaultConfigFileName());
return file.openForWriting();
#endif
}
diff --git a/common/system.h b/common/system.h
index 501d0802fd..cb9dbedad7 100644
--- a/common/system.h
+++ b/common/system.h
@@ -43,6 +43,7 @@ namespace Common {
struct Event;
class EventManager;
class SaveFileManager;
+ class SearchSet;
class TimerManager;
class SeekableReadStream;
class WriteStream;
@@ -907,6 +908,18 @@ public:
virtual FilesystemFactory *getFilesystemFactory() = 0;
/**
+ * Add system specific Common::Archive objects to the given SearchSet.
+ * E.g. on Unix the dir corresponding to DATA_PATH (if set), or on
+ * Mac OS X the 'Resource' dir in the app bundle.
+ *
+ * @todo Come up with a better name. This one sucks.
+ *
+ * @param s the SearchSet to which the system specific dirs, if any, are added
+ * @param priority the priority with which those dirs are added
+ */
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s, uint priority = 0) {}
+
+ /**
* Open the default config file for reading, by returning a suitable
* ReadStream instance. It is the callers responsiblity to delete
* the stream after use.
diff --git a/common/unarj.cpp b/common/unarj.cpp
index 9a7766a41f..244a296efb 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -23,28 +23,9 @@
*
*/
-// Heavily based on Unarj 2.65
-
-/* UNARJ.C, UNARJ, R JUNG, 06/05/02
- * Main Extractor routine
- * Copyright (c) 1991-2002 by ARJ Software, Inc. All rights reserved.
- *
- * This code may be freely used in programs that are NOT ARJ archivers
- * (both compress and extract ARJ archives).
- *
- * If you wish to distribute a modified version of this program, you
- * MUST indicate that it is a modified version both in the program and
- * source code.
- *
- * We are holding the copyright on the source code, so please do not
- * delete our name from the program files or from the documentation.
- *
- * We wish to give credit to Haruhiko Okumura for providing the
- * basic ideas for ARJ and UNARJ in his program AR. Please note
- * that UNARJ is significantly different from AR from an archive
- * structural point of view.
- *
- */
+//
+// This file is heavily based on the arj code available under the GPL
+// from http://arj.sourceforge.net/ , version 3.10.22 .
#include "common/scummsys.h"
#include "common/util.h"
@@ -52,18 +33,38 @@
namespace Common {
+#define HEADER_ID 0xEA60
+#define HEADER_ID_HI 0xEA
+#define HEADER_ID_LO 0x60
+
+#define FIRST_HDR_SIZE 30
+#define HEADERSIZE_MAX (FIRST_HDR_SIZE + 10 + ARJ_FILENAME_MAX + ARJ_COMMENT_MAX)
+#define CRC_MASK 0xFFFFFFFFL
+#define HSLIMIT_ARJ 524288L
+
+#define CBIT 9
+#define PBIT 5
+#define TBIT 5
+
+//
+// Source for InitCRC, GetCRC: crc32.c
+//
+
static uint32 CRCtable[256];
static void InitCRC(void) {
const uint32 poly = 0xEDB88320;
int i, j;
- uint32 n;
+ uint32 r;
for (i = 0; i < 256; i++) {
- n = i;
+ r = i;
for (j = 0; j < 8; j++)
- n = (n & 1) ? ((n >> 1) ^ poly) : (n >> 1);
- CRCtable[i] = n;
+ if (r & 1)
+ r = (r >> 1) ^ poly;
+ else
+ r >>= 1;
+ CRCtable[i] = r;
}
}
@@ -124,41 +125,47 @@ void ArjFile::registerArchive(const String &filename) {
debug(0, "ArjFile::registerArchive(%s): Located %d files", filename.c_str(), _headers.size());
}
+//
+// Source for findHeader and readHeader: arj_arcv.c
+//
+
int32 ArjFile::findHeader(void) {
- long arcpos, lastpos;
- int c;
+ long end_pos, tmp_pos;
+ int id;
byte header[HEADERSIZE_MAX];
uint32 crc;
- uint16 headersize;
+ uint16 basic_hdr_size;
- arcpos = _currArchive.pos();
+ tmp_pos = _currArchive.pos();
_currArchive.seek(0L, SEEK_END);
- lastpos = _currArchive.pos() - 2;
- if (lastpos > MAXSFX)
- lastpos = MAXSFX;
-
- for ( ; arcpos < lastpos; arcpos++) {
- _currArchive.seek(arcpos, SEEK_SET);
- c = _currArchive.readByte();
- while (arcpos < lastpos) {
- if (c != HEADER_ID_LO) // low order first
- c = _currArchive.readByte();
- else if ((c = _currArchive.readByte()) == HEADER_ID_HI)
- break;
- arcpos++;
+ end_pos = _currArchive.pos() - 2;
+ if (end_pos >= tmp_pos + HSLIMIT_ARJ)
+ end_pos = tmp_pos + HSLIMIT_ARJ;
+
+ while (tmp_pos < end_pos) {
+ _currArchive.seek(tmp_pos, SEEK_SET);
+ id = _currArchive.readByte();
+ while (tmp_pos < end_pos) {
+ if (id == HEADER_ID_LO)
+ if ((id = _currArchive.readByte()) == HEADER_ID_HI)
+ break;
+ else
+ id = _currArchive.readByte();
+ tmp_pos++;
}
- if (arcpos >= lastpos)
- break;
- if ((headersize = _currArchive.readUint16LE()) <= HEADERSIZE_MAX) {
- _currArchive.read(header, headersize);
- crc = GetCRC(header, headersize);
+ if (tmp_pos >= end_pos)
+ return -1;
+ if ((basic_hdr_size = _currArchive.readUint16LE()) <= HEADERSIZE_MAX) {
+ _currArchive.read(header, basic_hdr_size);
+ crc = GetCRC(header, basic_hdr_size);
if (crc == _currArchive.readUint32LE()) {
- _currArchive.seek(arcpos, SEEK_SET);
- return arcpos;
+ _currArchive.seek(tmp_pos, SEEK_SET);
+ return tmp_pos;
}
}
+ tmp_pos++;
}
- return -1; // could not find a valid header
+ return -1;
}
ArjHeader *ArjFile::readHeader() {
@@ -166,6 +173,7 @@ ArjHeader *ArjFile::readHeader() {
ArjHeader *head;
byte headData[HEADERSIZE_MAX];
+ // Strictly check the header ID
header.id = _currArchive.readUint16LE();
if (header.id != HEADER_ID) {
warning("ArjFile::readHeader(): Bad header ID (%x)", header.id);
@@ -199,7 +207,7 @@ ArjHeader *ArjFile::readHeader() {
header.flags = readS.readByte();
header.method = readS.readByte();
header.fileType = readS.readByte();
- (void)readS.readByte();
+ (void)readS.readByte(); // password_modifier
header.timeStamp = readS.readUint32LE();
header.compSize = readS.readSint32LE();
header.origSize = readS.readSint32LE();
@@ -208,20 +216,20 @@ ArjHeader *ArjFile::readHeader() {
header.fileMode = readS.readUint16LE();
header.hostData = readS.readUint16LE();
+ // static int check_file_size()
if (header.origSize < 0 || header.compSize < 0) {
warning("ArjFile::readHeader(): Wrong file size");
return NULL;
}
- strncpy(header.filename, (const char *)&headData[header.firstHdrSize], FNAME_MAX);
+ strncpy(header.filename, (const char *)&headData[header.firstHdrSize], ARJ_FILENAME_MAX);
- strncpy(header.comment, (const char *)&headData[header.firstHdrSize + strlen(header.filename) + 1], COMMENT_MAX);
+ strncpy(header.comment, (const char *)&headData[header.firstHdrSize + strlen(header.filename) + 1], ARJ_COMMENT_MAX);
- /* if extheadersize == 0 then no CRC */
- /* otherwise read extheader data and read 4 bytes for CRC */
-
- while ((header.extHeaderSize = _currArchive.readUint16LE()) != 0)
- _currArchive.seek((long)(header.extHeaderSize + 4), SEEK_CUR);
+ // Process extended headers, if any
+ uint16 extHeaderSize;
+ while ((extHeaderSize = _currArchive.readUint16LE()) != 0)
+ _currArchive.seek((long)(extHeaderSize + 4), SEEK_CUR);
header.pos = _currArchive.pos();
@@ -320,53 +328,70 @@ bool ArjFile::eos() {
return _uncompressed->eos();
}
-uint32 ArjFile::pos() {
+int32 ArjFile::pos() {
return _uncompressed->pos();
}
-uint32 ArjFile::size() {
+int32 ArjFile::size() {
return _uncompressed->size();
}
-void ArjFile::seek(int32 offset, int whence) {
- _uncompressed->seek(offset, whence);
+bool ArjFile::seek(int32 offset, int whence) {
+ return _uncompressed->seek(offset, whence);
}
+//
+// Source for init_getbits: arj_file.c (decode_start_stub)
+//
+
void ArjFile::init_getbits() {
_bitbuf = 0;
- _subbitbuf = 0;
+ _bytebuf = 0;
_bitcount = 0;
- fillbuf(2 * CHAR_BIT);
+ fillbuf(ARJ_CHAR_BIT * 2);
}
-void ArjFile::fillbuf(int n) { // Shift bitbuf n bits left, read n bits
- _bitbuf = (_bitbuf << n) & 0xFFFF; /* lose the first n bits */
- while (n > _bitcount) {
- _bitbuf |= _subbitbuf << (n -= _bitcount);
- if (_compsize != 0) {
+//
+// Source for fillbuf, getbits: decode.c
+//
+
+void ArjFile::fillbuf(int n) {
+ while (_bitcount < n) {
+ _bitbuf = (_bitbuf << _bitcount) | (_bytebuf >> (8 - _bitcount));
+ n -= _bitcount;
+ if (_compsize > 0) {
_compsize--;
- _subbitbuf = _compressed->readByte();
- } else
- _subbitbuf = 0;
- _bitcount = CHAR_BIT;
+ _bytebuf = _compressed->readByte();
+ } else {
+ _bytebuf = 0;
+ }
+ _bitcount = 8;
}
- _bitbuf |= _subbitbuf >> (_bitcount -= n);
+ _bitcount -= n;
+ _bitbuf = ( _bitbuf << n) | (_bytebuf >> (8-n));
+ _bytebuf <<= n;
}
+// Reads a series of bits into the input buffer */
uint16 ArjFile::getbits(int n) {
- uint16 x;
+ uint16 rc;
- x = _bitbuf >> (2 * CHAR_BIT - n);
+ rc = _bitbuf >> (ARJ_CODE_BIT - n);
fillbuf(n);
- return x;
+ return rc;
}
-/* Huffman decode routines */
+//
+// Huffman decode routines
+// Source: decode.c
+//
+// Creates a table for decoding
void ArjFile::make_table(int nchar, byte *bitlen, int tablebits, uint16 *table, int tablesize) {
- uint16 count[17], weight[17], start[18], *p;
+ uint16 count[17], weight[17], start[18];
+ uint16 *p;
uint i, k, len, ch, jutbits, avail, nextcode, mask;
for (i = 1; i <= 16; i++)
@@ -415,7 +440,8 @@ void ArjFile::make_table(int nchar, byte *bitlen, int tablebits, uint16 *table,
while (i != 0) {
if (*p == 0) {
_right[avail] = _left[avail] = 0;
- *p = avail++;
+ *p = avail;
+ avail++;
}
if (k & mask)
p = &_right[*p];
@@ -430,6 +456,7 @@ void ArjFile::make_table(int nchar, byte *bitlen, int tablebits, uint16 *table,
}
}
+// Reads length of data pending
void ArjFile::read_pt_len(int nn, int nbit, int i_special) {
int i, n;
int16 c;
@@ -445,9 +472,9 @@ void ArjFile::read_pt_len(int nn, int nbit, int i_special) {
} else {
i = 0;
while (i < n) {
- c = _bitbuf >> (13);
+ c = _bitbuf >> 13;
if (c == 7) {
- mask = 1 << (12);
+ mask = 1 << 12;
while (mask & _bitbuf) {
mask >>= 1;
c++;
@@ -463,10 +490,11 @@ void ArjFile::read_pt_len(int nn, int nbit, int i_special) {
}
while (i < nn)
_pt_len[i++] = 0;
- make_table(nn, _pt_len, 8, _pt_table, PTABLESIZE); // replaced sizeof
+ make_table(nn, _pt_len, 8, _pt_table, ARJ_PTABLESIZE);
}
}
+// Reads a character table
void ArjFile::read_c_len() {
int16 i, c, n;
uint16 mask;
@@ -474,82 +502,87 @@ void ArjFile::read_c_len() {
n = getbits(CBIT);
if (n == 0) {
c = getbits(CBIT);
- for (i = 0; i < NC; i++)
+ for (i = 0; i < ARJ_NC; i++)
_c_len[i] = 0;
- for (i = 0; i < CTABLESIZE; i++)
+ for (i = 0; i < ARJ_CTABLESIZE; i++)
_c_table[i] = c;
} else {
i = 0;
while (i < n) {
c = _pt_table[_bitbuf >> (8)];
- if (c >= NT) {
- mask = 1 << (7);
+ if (c >= ARJ_NT) {
+ mask = 1 << 7;
do {
if (_bitbuf & mask)
c = _right[c];
else
c = _left[c];
mask >>= 1;
- } while (c >= NT);
+ } while (c >= ARJ_NT);
}
fillbuf((int)(_pt_len[c]));
if (c <= 2) {
if (c == 0)
c = 1;
- else if (c == 1)
- c = getbits(4) + 3;
- else
- c = getbits(CBIT) + 20;
+ else if (c == 1) {
+ c = getbits(4);
+ c += 3;
+ } else {
+ c = getbits(CBIT);
+ c += 20;
+ }
while (--c >= 0)
_c_len[i++] = 0;
}
else
_c_len[i++] = (byte)(c - 2);
}
- while (i < NC)
+ while (i < ARJ_NC)
_c_len[i++] = 0;
- make_table(NC, _c_len, 12, _c_table, CTABLESIZE); // replaced sizeof
+ make_table(ARJ_NC, _c_len, 12, _c_table, ARJ_CTABLESIZE);
}
}
+// Decodes a single character
uint16 ArjFile::decode_c() {
uint16 j, mask;
if (_blocksize == 0) {
- _blocksize = getbits(16);
- read_pt_len(NT, TBIT, 3);
+ _blocksize = getbits(ARJ_CODE_BIT);
+ read_pt_len(ARJ_NT, TBIT, 3);
read_c_len();
- read_pt_len(NP, PBIT, -1);
+ read_pt_len(ARJ_NP, PBIT, -1);
}
_blocksize--;
j = _c_table[_bitbuf >> 4];
- if (j >= NC) {
- mask = 1 << (3);
+ if (j >= ARJ_NC) {
+ mask = 1 << 3;
do {
if (_bitbuf & mask)
j = _right[j];
else
j = _left[j];
mask >>= 1;
- } while (j >= NC);
+ } while (j >= ARJ_NC);
}
fillbuf((int)(_c_len[j]));
return j;
}
+// Decodes a control character
uint16 ArjFile::decode_p() {
uint16 j, mask;
- j = _pt_table[_bitbuf >> (8)];
- if (j >= NP) {
- mask = 1 << (7);
+ j = _pt_table[_bitbuf >> 8];
+ if (j >= ARJ_NP) {
+ mask = 1 << 7;
do {
if (_bitbuf & mask)
j = _right[j];
else
j = _left[j];
mask >>= 1;
- } while (j >= NP);
+ } while (j >= ARJ_NP);
}
fillbuf((int)(_pt_len[j]));
if (j != 0) {
@@ -559,63 +592,59 @@ uint16 ArjFile::decode_p() {
return j;
}
+// Initializes memory for decoding
void ArjFile::decode_start() {
_blocksize = 0;
init_getbits();
}
+// Decodes the entire file
void ArjFile::decode() {
int16 i;
- int16 j;
- int16 c;
int16 r;
+ int16 c;
+ int16 j;
int32 count;
decode_start();
- count = 0;
+ count = _origsize;
r = 0;
- while (count < _origsize) {
+ while (count > 0) {
if ((c = decode_c()) <= ARJ_UCHAR_MAX) {
- _text[r] = (byte) c;
- count++;
- if (++r >= DDICSIZ) {
+ _ntext[r] = (byte) c;
+ count--;
+ if (++r >= ARJ_DICSIZ) {
r = 0;
- _outstream->write(_text, DDICSIZ);
+ _outstream->write(_ntext, ARJ_DICSIZ);
}
} else {
- j = c - (ARJ_UCHAR_MAX + 1 - THRESHOLD);
- count += j;
- i = decode_p();
- if ((i = r - i - 1) < 0)
- i += DDICSIZ;
- if (r > i && r < DDICSIZ - MAXMATCH - 1) {
+ j = c - (ARJ_UCHAR_MAX + 1 - ARJ_THRESHOLD);
+ count -= j;
+ i = r - decode_p() - 1;
+ if (i < 0)
+ i += ARJ_DICSIZ;
+ if (r > i && r < ARJ_DICSIZ - ARJ_MAXMATCH - 1) {
while (--j >= 0)
- _text[r++] = _text[i++];
+ _ntext[r++] = _ntext[i++];
} else {
while (--j >= 0) {
- _text[r] = _text[i];
- if (++r >= DDICSIZ) {
+ _ntext[r] = _ntext[i];
+ if (++r >= ARJ_DICSIZ) {
r = 0;
- _outstream->write(_text, DDICSIZ);
+ _outstream->write(_ntext, ARJ_DICSIZ);
}
- if (++i >= DDICSIZ)
+ if (++i >= ARJ_DICSIZ)
i = 0;
}
}
}
}
- if (r != 0)
- _outstream->write(_text, r);
+ if (r > 0)
+ _outstream->write(_ntext, r);
}
-/* Macros */
-
-#define BFIL {_getbuf|=_bitbuf>>_getlen;fillbuf(CODE_BIT-_getlen);_getlen=CODE_BIT;}
-#define GETBIT(c) {if(_getlen<=0)BFIL c=(_getbuf&0x8000)!=0;_getbuf<<=1;_getlen--;}
-#define BPUL(l) {_getbuf<<=l;_getlen-=l;}
-#define GETBITS(c,l) {if(_getlen<l)BFIL c=(uint16)_getbuf>>(CODE_BIT-l);BPUL(l)}
-
+// Backward pointer decoding
int16 ArjFile::decode_ptr() {
int16 c = 0;
int16 width;
@@ -623,20 +652,21 @@ int16 ArjFile::decode_ptr() {
int16 pwr;
plus = 0;
- pwr = 1 << (STRTP);
- for (width = (STRTP); width < (STOPP); width++) {
- GETBIT(c);
+ pwr = 1 << 9;
+ for (width = 9; width < 13; width++) {
+ c = getbits(1);
if (c == 0)
break;
plus += pwr;
pwr <<= 1;
}
if (width != 0)
- GETBITS(c, width);
+ c = getbits(width);
c += plus;
return c;
}
+// Reference length decoding
int16 ArjFile::decode_len() {
int16 c = 0;
int16 width;
@@ -644,62 +674,60 @@ int16 ArjFile::decode_len() {
int16 pwr;
plus = 0;
- pwr = 1 << (STRTL);
- for (width = (STRTL); width < (STOPL); width++) {
- GETBIT(c);
+ pwr = 1;
+ for (width = 0; width < 7; width++) {
+ c = getbits(1);
if (c == 0)
break;
plus += pwr;
pwr <<= 1;
}
if (width != 0)
- GETBITS(c, width);
+ c = getbits(width);
c += plus;
return c;
}
+// Decodes the entire file, using method 4
void ArjFile::decode_f() {
int16 i;
int16 j;
int16 c;
int16 r;
- int16 pos1;
- int32 count;
+ uint32 ncount;
init_getbits();
+ ncount = 0;
_getlen = _getbuf = 0;
- count = 0;
r = 0;
- while (count < _origsize) {
+ while (ncount < (uint32)_origsize) {
c = decode_len();
if (c == 0) {
- GETBITS(c, CHAR_BIT);
- _text[r] = (byte)c;
- count++;
- if (++r >= DDICSIZ) {
+ ncount++;
+ _ntext[r] = (byte)getbits(8);
+ if (++r >= ARJ_FDICSIZ) {
r = 0;
- _outstream->write(_text, DDICSIZ);
+ _outstream->write(_ntext, ARJ_FDICSIZ);
}
} else {
- j = c - 1 + THRESHOLD;
- count += j;
- pos1 = decode_ptr();
- if ((i = r - pos1 - 1) < 0)
- i += DDICSIZ;
+ j = c - 1 + ARJ_THRESHOLD;
+ ncount += j;
+ if ((i = r - decode_ptr() - 1) < 0)
+ i += ARJ_FDICSIZ;
while (j-- > 0) {
- _text[r] = _text[i];
- if (++r >= DDICSIZ) {
+ _ntext[r] = _ntext[i];
+ if (++r >= ARJ_FDICSIZ) {
r = 0;
- _outstream->write(_text, DDICSIZ);
+ _outstream->write(_ntext, ARJ_FDICSIZ);
}
- if (++i >= DDICSIZ)
+ if (++i >= ARJ_FDICSIZ)
i = 0;
}
}
}
if (r != 0)
- _outstream->write(_text, r);
+ _outstream->write(_ntext, r);
}
diff --git a/common/unarj.h b/common/unarj.h
index c8965968f6..52e0d13948 100644
--- a/common/unarj.h
+++ b/common/unarj.h
@@ -31,46 +31,31 @@
namespace Common {
-#define HEADER_ID 0xEA60
-#define HEADER_ID_HI 0xEA
-#define HEADER_ID_LO 0x60
-#define FIRST_HDR_SIZE 30
-#define FIRST_HDR_SIZE_V 34
-#define COMMENT_MAX 2048
-#define FNAME_MAX 512
-#define HEADERSIZE_MAX (FIRST_HDR_SIZE + 10 + FNAME_MAX + COMMENT_MAX)
-#define CRC_MASK 0xFFFFFFFFL
-#define MAXSFX 25000L
-
-#define CODE_BIT 16
-#define CHAR_BIT 8
-#define ARJ_UCHAR_MAX 255 // UCHAR_MAX is defined in limits.h in MSVC
-#define THRESHOLD 3
-#define DDICSIZ 26624
-#define MAXDICBIT 16
-#define MATCHBIT 8
-#define MAXMATCH 256
-#define NC (ARJ_UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
-#define NP (MAXDICBIT + 1)
-#define CBIT 9
-#define NT (CODE_BIT + 3)
-#define PBIT 5
-#define TBIT 5
-
-#if NT > NP
-#define NPT NT
+#define ARJ_UCHAR_MAX 255
+#define ARJ_CHAR_BIT 8
+
+#define ARJ_COMMENT_MAX 2048
+#define ARJ_FILENAME_MAX 512
+
+#define ARJ_CODE_BIT 16
+#define ARJ_THRESHOLD 3
+#define ARJ_DICSIZ 26624
+#define ARJ_FDICSIZ ARJ_DICSIZ
+#define ARJ_MAXDICBIT 16
+#define ARJ_MAXMATCH 256
+#define ARJ_NC (ARJ_UCHAR_MAX + ARJ_MAXMATCH + 2 - ARJ_THRESHOLD)
+#define ARJ_NP (ARJ_MAXDICBIT + 1)
+#define ARJ_NT (ARJ_CODE_BIT + 3)
+
+#if ARJ_NT > ARJ_NP
+#define ARJ_NPT ARJ_NT
#else
-#define NPT NP
+#define ARJ_NPT ARJ_NP
#endif
-#define CTABLESIZE 4096
-#define PTABLESIZE 256
+#define ARJ_CTABLESIZE 4096
+#define ARJ_PTABLESIZE 256
-#define STRTP 9
-#define STOPP 13
-
-#define STRTL 0
-#define STOPL 7
struct ArjHeader {
int32 pos;
@@ -92,9 +77,8 @@ struct ArjHeader {
uint16 entryPos;
uint16 fileMode;
uint16 hostData;
- char filename[FNAME_MAX];
- char comment[COMMENT_MAX];
- uint16 extHeaderSize;
+ char filename[ARJ_FILENAME_MAX];
+ char comment[ARJ_COMMENT_MAX];
uint32 headerCrc;
};
@@ -115,9 +99,9 @@ public:
uint32 read(void *dataPtr, uint32 dataSize);
bool eos();
- uint32 pos();
- uint32 size();
- void seek(int32 offset, int whence = SEEK_SET);
+ int32 pos();
+ int32 size();
+ bool seek(int32 offset, int whence = SEEK_SET);
bool isOpen() { return _isOpen; }
private:
@@ -143,6 +127,7 @@ private:
void decode_f();
uint16 _bitbuf;
+ uint16 _bytebuf;
int32 _compsize;
int32 _origsize;
byte _subbitbuf;
@@ -163,18 +148,18 @@ private:
int16 decode_len(void);
private:
- byte _text[DDICSIZ];
+ byte _ntext[ARJ_FDICSIZ];
int16 _getlen;
int16 _getbuf;
- uint16 _left[2 * NC - 1];
- uint16 _right[2 * NC - 1];
- byte _c_len[NC];
- byte _pt_len[NPT];
+ uint16 _left[2 * ARJ_NC - 1];
+ uint16 _right[2 * ARJ_NC - 1];
+ byte _c_len[ARJ_NC];
+ byte _pt_len[ARJ_NPT];
- uint16 _c_table[CTABLESIZE];
- uint16 _pt_table[PTABLESIZE];
+ uint16 _c_table[ARJ_CTABLESIZE];
+ uint16 _pt_table[ARJ_PTABLESIZE];
uint16 _blocksize;
diff --git a/common/unzip.h b/common/unzip.h
index 2d888fe5b1..43faaf4a74 100644
--- a/common/unzip.h
+++ b/common/unzip.h
@@ -65,9 +65,12 @@
#ifndef _unz_H
#define _unz_H
+#ifdef USE_ZLIB
+
#include "common/scummsys.h"
+#include "common/archive.h"
+#include "common/stream.h"
-#ifdef USE_ZLIB
#ifdef __cplusplus
extern "C" {
@@ -302,6 +305,49 @@ extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
}
#endif
-#endif
+
+class ZipArchive : Common::Archive {
+ unzFile _zipFile;
+
+public:
+ ZipArchive(const Common::String &name) {
+ _zipFile = unzOpen(name.c_str());
+ }
+ ~ZipArchive() {
+ unzClose(_zipFile);
+ }
+
+ virtual bool hasFile(const Common::String &name) {
+ return (_zipFile && unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK);
+ }
+
+ virtual int getAllNames(Common::StringList &list) {
+ // TODO
+ return 0;
+ }
+
+ virtual Common::SeekableReadStream *openFile(const Common::String &name) {
+ if (!_zipFile)
+ return 0;
+
+ unzLocateFile(_zipFile, name.c_str(), 2);
+
+ unz_file_info fileInfo;
+ unzOpenCurrentFile(_zipFile);
+ unzGetCurrentFileInfo(_zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
+ byte *buffer = (byte *)calloc(fileInfo.uncompressed_size+1, 1);
+ assert(buffer);
+ unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size);
+ unzCloseCurrentFile(_zipFile);
+ return new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true);
+
+ // FIXME: instead of reading all into a memory stream, we could
+ // instead create a new ZipStream class. But then we have to be
+ // careful to handle the case where the client code opens multiple
+ // files in the archive and tries to use them indepenendtly.
+ }
+};
+
+#endif // USE_ZLIB
#endif /* _unz_H */
diff --git a/common/util.cpp b/common/util.cpp
index 6f0fdcb233..f68d253ec3 100644
--- a/common/util.cpp
+++ b/common/util.cpp
@@ -63,39 +63,6 @@ extern bool isSmartphone(void);
namespace Common {
-bool matchString(const char *str, const char *pat) {
- const char *p = 0;
- const char *q = 0;
-
- for (;;) {
- switch (*pat) {
- case '*':
- p = ++pat;
- q = str;
- break;
-
- default:
- if (*pat != *str) {
- if (p) {
- pat = p;
- str = ++q;
- if (!*str)
- return !*pat;
- break;
- }
- else
- return false;
- }
- // fallthrough
- case '?':
- if (!*str)
- return !*pat;
- pat++;
- str++;
- }
- }
-}
-
StringTokenizer::StringTokenizer(const String &str, const String &delimiters) : _str(str), _delimiters(delimiters) {
reset();
}
@@ -237,10 +204,9 @@ Language parseLanguage(const String &str) {
if (str.empty())
return UNK_LANG;
- const char *s = str.c_str();
const LanguageDescription *l = g_languages;
for (; l->code; ++l) {
- if (!scumm_stricmp(l->code, s))
+ if (str.equalsIgnoreCase(l->code))
return l->id;
}
@@ -278,6 +244,7 @@ const PlatformDescription g_platforms[] = {
{"c64", "c64", "c64", "Commodore 64", kPlatformC64},
{"pc", "dos", "ibm", "DOS", kPlatformPC},
{"pc98", "pc98", "pc98", "PC-98", kPlatformPC98},
+ {"wii", "wii", "wii", "Nintendo Wii", kPlatformWii},
// The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo).
// However, on the net many variations can be seen, like "FMTOWNS",
@@ -299,20 +266,18 @@ Platform parsePlatform(const String &str) {
if (str.empty())
return kPlatformUnknown;
- const char *s = str.c_str();
-
// Handle some special case separately, for compatibility with old config
// files.
- if (!strcmp(s, "1"))
+ if (str == "1")
return kPlatformAmiga;
- else if (!strcmp(s, "2"))
+ else if (str == "2")
return kPlatformAtariST;
- else if (!strcmp(s, "3"))
+ else if (str == "3")
return kPlatformMacintosh;
const PlatformDescription *l = g_platforms;
for (; l->code; ++l) {
- if (!scumm_stricmp(l->code, s) || !scumm_stricmp(l->code2, s) || !scumm_stricmp(l->abbrev, s))
+ if (str.equalsIgnoreCase(l->code) || str.equalsIgnoreCase(l->code2) || str.equalsIgnoreCase(l->abbrev))
return l->id;
}
@@ -364,10 +329,9 @@ RenderMode parseRenderMode(const String &str) {
if (str.empty())
return kRenderDefault;
- const char *s = str.c_str();
const RenderModeDescription *l = g_renderModes;
for (; l->code; ++l) {
- if (!scumm_stricmp(l->code, s))
+ if (str.equalsIgnoreCase(l->code))
return l->id;
}
diff --git a/common/util.h b/common/util.h
index c23513596c..32f07181c4 100644
--- a/common/util.h
+++ b/common/util.h
@@ -53,28 +53,6 @@ template<typename T> inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; }
namespace Common {
/**
- * Simple DOS-style pattern matching function (understands * and ? like used in DOS).
- * Taken from exult/files/listfiles.cc
- *
- * Token meaning:
- * "*": any character, any amount of times.
- * "?": any character, only once.
- *
- * Example strings/patterns:
- * String: monkey.s?? Pattern: monkey.s01 => true
- * String: monkey.s?? Pattern: monkey.s101 => false
- * String: monkey.s?1 Pattern: monkey.s99 => false
- * String: monkey.s* Pattern: monkey.s101 => true
- * String: monkey.s*1 Pattern: monkey.s99 => false
- *
- * @param str Text to be matched against the given pattern.
- * @param pat Glob pattern.
- *
- * @return true if str matches the pattern, false otherwise.
- */
-bool matchString(const char *str, const char *pat);
-
-/**
* A simple non-optimized string tokenizer.
*
* Example of use:
@@ -210,6 +188,7 @@ enum Platform {
kPlatformApple2GS,
kPlatformPC98,
+ kPlatformWii,
kPlatformUnknown = -1
};
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index 44bf03336e..b93a5205be 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -61,7 +61,7 @@ bool XMLParser::parserError(const char *errorString, ...) {
char lineStr[70];
_stream->seek(original_pos - 35, SEEK_SET);
- _stream->readLine(lineStr, 70);
+ _stream->readLine_NEW(lineStr, 70);
for (int i = 0; i < 70; ++i)
if (lineStr[i] == '\n')
@@ -106,15 +106,16 @@ bool XMLParser::parseActiveKey(bool closed) {
key->layout = layout->children[key->name];
Common::StringMap localMap = key->values;
+ int keyCount = localMap.size();
for (Common::List<XMLKeyLayout::XMLKeyProperty>::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) {
- if (localMap.contains(i->name))
- localMap.erase(i->name);
- else if (i->required)
+ if (i->required && !localMap.contains(i->name))
return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str());
+ else if (localMap.contains(i->name))
+ keyCount--;
}
- if (localMap.empty() == false)
+ if (keyCount > 0)
return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str());
} else {
diff --git a/common/zlib.cpp b/common/zlib.cpp
index 7e14a9e3ab..4ed233b4b0 100644
--- a/common/zlib.cpp
+++ b/common/zlib.cpp
@@ -8,37 +8,327 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public 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/zlib.h"
+#include "common/util.h"
#if defined(USE_ZLIB)
+ #ifdef __SYMBIAN32__
+ #include <zlib\zlib.h>
+ #else
+ #include <zlib.h>
+ #endif
-#ifdef __SYMBIAN32__
-#include <zlib\zlib.h>
-#else
-#include <zlib.h>
+ #if ZLIB_VERNUM < 0x1204
+ #error Version 1.2.0.4 or newer of zlib is required for this code
+ #endif
#endif
+
namespace Common {
-int uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen) {
- return ::uncompress(dst, dstLen, src, srcLen);
+#if defined(USE_ZLIB)
+
+bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen) {
+ return Z_OK == ::uncompress(dst, dstLen, src, srcLen);
}
-} // end of namespace Common
+/**
+ * A simple wrapper class which can be used to wrap around an arbitrary
+ * other SeekableReadStream and will then provide on-the-fly decompression support.
+ * Assumes the compressed data to be in gzip format.
+ */
+class GZipReadStream : public Common::SeekableReadStream {
+protected:
+ enum {
+ BUFSIZE = 16384 // 1 << MAX_WBITS
+ };
+
+ byte _buf[BUFSIZE];
+
+ Common::SeekableReadStream *_wrapped;
+ z_stream _stream;
+ int _zlibErr;
+ uint32 _pos;
+ uint32 _origSize;
+ bool _eos;
+
+public:
+
+ GZipReadStream(Common::SeekableReadStream *w) : _wrapped(w) {
+ assert(w != 0);
+
+ _stream.zalloc = Z_NULL;
+ _stream.zfree = Z_NULL;
+ _stream.opaque = Z_NULL;
+
+ // Verify file header is correct
+ w->seek(0, SEEK_SET);
+ uint16 header = w->readUint16BE();
+ assert(header == 0x1F8B ||
+ ((header & 0x0F00) == 0x0800 && header % 31 == 0));
+
+ if (header == 0x1F8B) {
+ // Retrieve the original file size
+ w->seek(-4, SEEK_END);
+ _origSize = w->readUint32LE();
+ } else {
+ // Original size not available in zlib format
+ _origSize = 0;
+ }
+ _pos = 0;
+ w->seek(0, SEEK_SET);
+ _eos = false;
+
+ // Adding 32 to windowBits indicates to zlib that it is supposed to
+ // automatically detect whether gzip or zlib headers are used for
+ // the compressed file. This feature was added in zlib 1.2.0.4,
+ // released 10 August 2003.
+ // Note: This is *crucial* for savegame compatibility, do *not* remove!
+ _zlibErr = inflateInit2(&_stream, MAX_WBITS + 32);
+ if (_zlibErr != Z_OK)
+ return;
+
+ // Setup input buffer
+ _stream.next_in = _buf;
+ _stream.avail_in = 0;
+ }
+
+ ~GZipReadStream() {
+ inflateEnd(&_stream);
+ delete _wrapped;
+ }
+
+ bool err() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); }
+ void clearErr() {
+ // only reset _eos; I/O errors are not recoverable
+ _eos = false;
+ }
+
+ uint32 read(void *dataPtr, uint32 dataSize) {
+ _stream.next_out = (byte *)dataPtr;
+ _stream.avail_out = dataSize;
+
+ // Keep going while we get no error
+ while (_zlibErr == Z_OK && _stream.avail_out) {
+ if (_stream.avail_in == 0 && !_wrapped->eos()) {
+ // If we are out of input data: Read more data, if available.
+ _stream.next_in = _buf;
+ _stream.avail_in = _wrapped->read(_buf, BUFSIZE);
+ }
+ _zlibErr = inflate(&_stream, Z_NO_FLUSH);
+ }
+
+ // Update the position counter
+ _pos += dataSize - _stream.avail_out;
+
+ if (_zlibErr == Z_STREAM_END && _stream.avail_out > 0)
+ _eos = true;
+
+ return dataSize - _stream.avail_out;
+ }
+
+ bool eos() const {
+ return _eos;
+ }
+ int32 pos() const {
+ return _pos;
+ }
+ int32 size() const {
+ return _origSize;
+ }
+ bool seek(int32 offset, int whence = SEEK_SET) {
+ int32 newPos = 0;
+ assert(whence != SEEK_END); // SEEK_END not supported
+ switch(whence) {
+ case SEEK_SET:
+ newPos = offset;
+ break;
+ case SEEK_CUR:
+ newPos = _pos + offset;
+ }
+
+ assert(newPos >= 0);
+
+ if ((uint32)newPos < _pos) {
+ // To search backward, we have to restart the whole decompression
+ // from the start of the file. A rather wasteful operation, best
+ // to avoid it. :/
+#if DEBUG
+ warning("Backward seeking in GZipReadStream detected");
+#endif
+ _pos = 0;
+ _wrapped->seek(0, SEEK_SET);
+ _zlibErr = inflateReset(&_stream);
+ if (_zlibErr != Z_OK)
+ return false; // FIXME: STREAM REWRITE
+ _stream.next_in = _buf;
+ _stream.avail_in = 0;
+ }
+
+ offset = newPos - _pos;
+
+ // Skip the given amount of data (very inefficient if one tries to skip
+ // huge amounts of data, but usually client code will only skip a few
+ // bytes, so this should be fine.
+ byte tmpBuf[1024];
+ while (!err() && offset > 0) {
+ offset -= read(tmpBuf, MIN((int32)sizeof(tmpBuf), offset));
+ }
+
+ _eos = false;
+ return true; // FIXME: STREAM REWRITE
+ }
+};
+
+/**
+ * A simple wrapper class which can be used to wrap around an arbitrary
+ * other WriteStream and will then provide on-the-fly compression support.
+ * The compressed data is written in the gzip format.
+ */
+class GZipWriteStream : public Common::WriteStream {
+protected:
+ enum {
+ BUFSIZE = 16384 // 1 << MAX_WBITS
+ };
+
+ byte _buf[BUFSIZE];
+ Common::WriteStream *_wrapped;
+ z_stream _stream;
+ int _zlibErr;
+
+ void processData(int flushType) {
+ // This function is called by both write() and finalize().
+ while (_zlibErr == Z_OK && (_stream.avail_in || flushType == Z_FINISH)) {
+ if (_stream.avail_out == 0) {
+ if (_wrapped->write(_buf, BUFSIZE) != BUFSIZE) {
+ _zlibErr = Z_ERRNO;
+ break;
+ }
+ _stream.next_out = _buf;
+ _stream.avail_out = BUFSIZE;
+ }
+ _zlibErr = deflate(&_stream, flushType);
+ }
+ }
+
+public:
+ GZipWriteStream(Common::WriteStream *w) : _wrapped(w) {
+ assert(w != 0);
+ _stream.zalloc = Z_NULL;
+ _stream.zfree = Z_NULL;
+ _stream.opaque = Z_NULL;
+
+ // Adding 16 to windowBits indicates to zlib that it is supposed to
+ // write gzip headers. This feature was added in zlib 1.2.0.4,
+ // released 10 August 2003.
+ // Note: This is *crucial* for savegame compatibility, do *not* remove!
+ _zlibErr = deflateInit2(&_stream,
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ MAX_WBITS + 16,
+ 8,
+ Z_DEFAULT_STRATEGY);
+ assert(_zlibErr == Z_OK);
+
+ _stream.next_out = _buf;
+ _stream.avail_out = BUFSIZE;
+ _stream.avail_in = 0;
+ _stream.next_in = 0;
+ }
+
+ ~GZipWriteStream() {
+ finalize();
+ deflateEnd(&_stream);
+ delete _wrapped;
+ }
+
+ bool err() const {
+ // CHECKME: does Z_STREAM_END make sense here?
+ return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->err();
+ }
+
+ void clearErr() {
+ // Note: we don't reset the _zlibErr here, as it is not
+ // clear in general how
+ _wrapped->clearErr();
+ }
+
+ void finalize() {
+ if (_zlibErr != Z_OK)
+ return;
+
+ // Process whatever remaining data there is.
+ processData(Z_FINISH);
+ // Since processData only writes out blocks of size BUFSIZE,
+ // we may have to flush some stragglers.
+ uint remainder = BUFSIZE - _stream.avail_out;
+ if (remainder > 0) {
+ if (_wrapped->write(_buf, remainder) != remainder) {
+ _zlibErr = Z_ERRNO;
+ }
+ }
+
+ // Finalize the wrapped savefile, too
+ _wrapped->finalize();
+ }
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ if (err())
+ return 0;
+
+ // Hook in the new data ...
+ // Note: We need to make a const_cast here, as zlib is not aware
+ // of the const keyword.
+ _stream.next_in = const_cast<byte *>((const byte *)dataPtr);
+ _stream.avail_in = dataSize;
+
+ // ... and flush it to disk
+ processData(Z_NO_FLUSH);
+
+ return dataSize - _stream.avail_in;
+ }
+};
+
+#endif // USE_ZLIB
+
+Common::SeekableReadStream *wrapCompressedReadStream(Common::SeekableReadStream *toBeWrapped) {
+#if defined(USE_ZLIB)
+ if (toBeWrapped) {
+ uint16 header = toBeWrapped->readUint16BE();
+ bool isCompressed = (header == 0x1F8B ||
+ ((header & 0x0F00) == 0x0800 &&
+ header % 31 == 0));
+ toBeWrapped->seek(-2, SEEK_CUR);
+ if (isCompressed)
+ return new GZipReadStream(toBeWrapped);
+ }
#endif
+ return toBeWrapped;
+}
+
+Common::WriteStream *wrapCompressedWriteStream(Common::WriteStream *toBeWrapped) {
+#if defined(USE_ZLIB)
+ if (toBeWrapped)
+ return new GZipWriteStream(toBeWrapped);
+#endif
+ return toBeWrapped;
+}
+
+} // End of namespace Common
diff --git a/common/zlib.h b/common/zlib.h
index 62e9f98c01..5fd13e842d 100644
--- a/common/zlib.h
+++ b/common/zlib.h
@@ -8,44 +8,65 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public 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(USE_ZLIB)
-
#ifndef COMMON_ZLIB_H
#define COMMON_ZLIB_H
-#ifdef __SYMBIAN32__
-#include <zlib\zlib.h>
-#else
-#include <zlib.h>
-#endif
+#include "common/scummsys.h"
+#include "common/stream.h"
namespace Common {
-enum {
- ZLIB_OK = Z_OK
-};
-
-int uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen);
+#if defined(USE_ZLIB)
-} // end of namespace Common
+/**
+ * Thin wrapper around zlib's uncompress() function. This wrapper makes
+ * it possible to uncompress data in engines without being forced to link
+ * them against zlib, thus simplifying the build system.
+ *
+ * @return true on success (i.e. Z_OK), false otherwise
+ */
+bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen);
#endif
-#endif
+/**
+ * Take an arbitrary SeekableReadStream and wrap it in a custom stream which
+ * provides transparent on-the-fly decompression. Assumes the data it
+ * retrieves from the wrapped stream to be either uncompressed or in gzip
+ * format. In the former case, the original stream is returned unmodified
+ * (and in particular, not wrapped).
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ */
+Common::SeekableReadStream *wrapCompressedReadStream(Common::SeekableReadStream *toBeWrapped);
+/**
+ * Take an arbitrary WriteStream and wrap it in a custom stream which provides
+ * transparent on-the-fly compression. The compressed data is written in the
+ * gzip format, unless ZLIB support has been disabled, in which case the given
+ * stream is returned unmodified (and in particular, not wrapped).
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ */
+Common::WriteStream *wrapCompressedWriteStream(Common::WriteStream *toBeWrapped);
+
+} // End of namespace Common
+
+#endif
diff --git a/configure b/configure
index 037c0bf786..c54a955deb 100755
--- a/configure
+++ b/configure
@@ -904,7 +904,7 @@ if test "$?" -gt 0; then
fi
case $cxx_version in
- 2.95.[2-9]|2.95.[2-9][-.]*|3.[0-9]|3.[0-9].[0-9]|3.[0-9].[0-9][-.]*|4.[0-9].[0-9]|4.[0-9].[0-9][-.]*)
+ 2.95.[2-9]|2.95.[2-9][-.]*|3.[0-9]|3.[0-9].[0-9]|3.[0-9].[0-9][-.]*|4.[0-9]|4.[0-9].[0-9]|4.[0-9].[0-9][-.]*)
_cxx_major=`echo $cxx_version | cut -d '.' -f 1`
_cxx_minor=`echo $cxx_version | cut -d '.' -f 2`
cxx_version="$cxx_version, ok"
@@ -1030,7 +1030,6 @@ echo "$_have_x86"
#
# Determine build settings
#
-# TODO - also add an command line option to override this?!?
echo_n "Checking hosttype... "
echo $_host_os
case $_host_os in
@@ -1046,7 +1045,7 @@ case $_host_os in
type_4_byte='long'
;;
solaris*)
- DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
+ DEFINES="$DEFINES -DUNIX -DSOLARIS -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lbind -lsocket for the timidity MIDI driver
LIBS="$LIBS -lnsl -lsocket"
;;
@@ -1060,12 +1059,12 @@ case $_host_os in
LIBS="$LIBS -framework QuickTime -framework AudioUnit -framework AudioToolbox -framework Carbon -framework CoreMIDI"
;;
mingw*)
- DEFINES="$DEFINES -DWIN32"
+ DEFINES="$DEFINES -DWIN32 -D__USE_MINGW_ANSI_STDIO=0"
LIBS="$LIBS -lmingw32 -lwinmm"
OBJS="$OBJS scummvmico.o"
;;
cygwin*)
- DEFINES="$DEFINES -mno-cygwin -DWIN32"
+ DEFINES="$DEFINES -mno-cygwin -DWIN32 -D__USE_MINGW_ANSI_STDIO=0"
LIBS="$LIBS -mno-cygwin -lmingw32 -lwinmm"
OBJS="$OBJS scummvmico.o"
;;
@@ -1074,7 +1073,6 @@ case $_host_os in
;;
mint*)
DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
- LIBS="$LIBS -lsocket"
;;
amigaos*)
# TODO: anything to be added here?
diff --git a/dists/engine-data/drascula.dat b/dists/engine-data/drascula.dat
index 321e63c277..1602a42490 100644
--- a/dists/engine-data/drascula.dat
+++ b/dists/engine-data/drascula.dat
Binary files differ
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 5cb5373f45..572106f4a4 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/dists/macosx/Info.plist.in b/dists/macosx/Info.plist.in
index 9074acc876..b87e9501e5 100644
--- a/dists/macosx/Info.plist.in
+++ b/dists/macosx/Info.plist.in
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>scummvm</string>
<key>CFBundleGetInfoString</key>
- <string>@VERSION@, Copyright 2001-2007 The ScummVM team</string>
+ <string>@VERSION@, Copyright 2001-2008 The ScummVM team</string>
<key>CFBundleIconFile</key>
<string>scummvm.icns</string>
<key>CFBundleIdentifier</key>
@@ -27,6 +27,6 @@
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright 2001-2007 The ScummVM team</string>
+ <string>Copyright 2001-2008 The ScummVM team</string>
</dict>
</plist>
diff --git a/dists/msvc7/agi.vcproj b/dists/msvc7/agi.vcproj
index d8154d907a..7da2e9397d 100644
--- a/dists/msvc7/agi.vcproj
+++ b/dists/msvc7/agi.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="agi_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/agos.vcproj b/dists/msvc7/agos.vcproj
index 4a64e17d34..5aad20fa99 100644
--- a/dists/msvc7/agos.vcproj
+++ b/dists/msvc7/agos.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="agos_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/cine.vcproj b/dists/msvc7/cine.vcproj
index fe0abd0f27..16d0e6161f 100644
--- a/dists/msvc7/cine.vcproj
+++ b/dists/msvc7/cine.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="cine_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/cruise.vcproj b/dists/msvc7/cruise.vcproj
index bac134e02c..24a423e737 100644
--- a/dists/msvc7/cruise.vcproj
+++ b/dists/msvc7/cruise.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="cruise_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -145,9 +152,6 @@
RelativePath="..\..\engines\cruise\dataLoader.h">
</File>
<File
- RelativePath="..\..\engines\cruise\decompiler.cpp">
- </File>
- <File
RelativePath="..\..\engines\cruise\delphine-unpack.cpp">
</File>
<File
diff --git a/dists/msvc7/drascula.vcproj b/dists/msvc7/drascula.vcproj
index 2d23296dbc..7d4d55b00c 100644
--- a/dists/msvc7/drascula.vcproj
+++ b/dists/msvc7/drascula.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="drascula_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/gob.vcproj b/dists/msvc7/gob.vcproj
index bb7eac35e0..99edd6deb2 100644
--- a/dists/msvc7/gob.vcproj
+++ b/dists/msvc7/gob.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="gob_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -268,6 +275,12 @@
RelativePath="..\..\engines\gob\inter_v4.cpp">
</File>
<File
+ RelativePath="..\..\engines\gob\inter_v5.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\gob\inter_v6.cpp">
+ </File>
+ <File
RelativePath="..\..\engines\gob\map.cpp">
</File>
<File
@@ -364,6 +377,9 @@
RelativePath="..\..\engines\gob\video_v2.cpp">
</File>
<File
+ RelativePath="..\..\engines\gob\video_v6.cpp">
+ </File>
+ <File
RelativePath="..\..\engines\gob\videoplayer.cpp">
</File>
<File
diff --git a/dists/msvc7/igor.vcproj b/dists/msvc7/igor.vcproj
index cbc5c9b7ec..46af401294 100644
--- a/dists/msvc7/igor.vcproj
+++ b/dists/msvc7/igor.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="igor_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/kyra.vcproj b/dists/msvc7/kyra.vcproj
index 2e0e8669e9..18b42878bf 100644
--- a/dists/msvc7/kyra.vcproj
+++ b/dists/msvc7/kyra.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="kyra_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -205,6 +212,12 @@
RelativePath="..\..\engines\kyra\resource.h">
</File>
<File
+ RelativePath="..\..\engines\kyra\resource_intern.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\kyra\resource_intern.h">
+ </File>
+ <File
RelativePath="..\..\engines\kyra\saveload.cpp">
</File>
<File
diff --git a/dists/msvc7/lure.vcproj b/dists/msvc7/lure.vcproj
index 7a1696f509..3e772218bc 100644
--- a/dists/msvc7/lure.vcproj
+++ b/dists/msvc7/lure.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="lure_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/m4.vcproj b/dists/msvc7/m4.vcproj
index 11b2169ccb..43a563abae 100644
--- a/dists/msvc7/m4.vcproj
+++ b/dists/msvc7/m4.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="m4_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/made.vcproj b/dists/msvc7/made.vcproj
index 757d46aa23..f0bec886ca 100644
--- a/dists/msvc7/made.vcproj
+++ b/dists/msvc7/made.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="made_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/parallaction.vcproj b/dists/msvc7/parallaction.vcproj
index 2dac8737c2..6547c6ccf6 100644
--- a/dists/msvc7/parallaction.vcproj
+++ b/dists/msvc7/parallaction.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="parallaction_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -205,6 +212,9 @@
RelativePath="..\..\engines\parallaction\saveload.cpp">
</File>
<File
+ RelativePath="..\..\engines\parallaction\saveload.h">
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\sound.cpp">
</File>
<File
diff --git a/dists/msvc7/queen.vcproj b/dists/msvc7/queen.vcproj
index 499a048660..bc8987ec9d 100644
--- a/dists/msvc7/queen.vcproj
+++ b/dists/msvc7/queen.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="queen_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/saga.vcproj b/dists/msvc7/saga.vcproj
index 1a1cb29555..6b19ea2503 100644
--- a/dists/msvc7/saga.vcproj
+++ b/dists/msvc7/saga.vcproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="Windows-1252"?>
+<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="saga_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/scumm.vcproj b/dists/msvc7/scumm.vcproj
index 56f78692cc..397d6ef68b 100644
--- a/dists/msvc7/scumm.vcproj
+++ b/dists/msvc7/scumm.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="scumm_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -105,12 +112,6 @@
RelativePath="..\..\engines\scumm\smush\channel.h">
</File>
<File
- RelativePath="..\..\engines\scumm\smush\chunk.cpp">
- </File>
- <File
- RelativePath="..\..\engines\scumm\smush\chunk.h">
- </File>
- <File
RelativePath="..\..\engines\scumm\smush\chunk_type.h">
</File>
<File
@@ -553,9 +554,6 @@
RelativePath="..\..\engines\scumm\string.cpp">
</File>
<File
- RelativePath="..\..\engines\scumm\thumbnail.cpp">
- </File>
- <File
RelativePath="..\..\engines\scumm\usage_bits.cpp">
</File>
<File
diff --git a/dists/msvc7/scummvm.vcproj b/dists/msvc7/scummvm.vcproj
index 884cd58a5a..dd982dea23 100644
--- a/dists/msvc7/scummvm.vcproj
+++ b/dists/msvc7/scummvm.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_NASM;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,11 +29,14 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -68,14 +72,16 @@
IntermediateDirectory="scummvm_Release"
ConfigurationType="1"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
StringPooling="TRUE"
MinimalRebuild="FALSE"
@@ -88,12 +94,13 @@
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib"
+ AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib tinsel_release/tinsel.lib"
OutputFile="$(OutDir)/scummvm.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@@ -130,12 +137,6 @@
RelativePath="..\..\base\commandLine.h">
</File>
<File
- RelativePath="..\..\base\game.cpp">
- </File>
- <File
- RelativePath="..\..\base\game.h">
- </File>
- <File
RelativePath="..\..\base\internal_version.h">
</File>
<File
@@ -169,6 +170,12 @@
RelativePath="..\..\common\algorithm.h">
</File>
<File
+ RelativePath="..\..\common\archive.cpp">
+ </File>
+ <File
+ RelativePath="..\..\common\archive.h">
+ </File>
+ <File
RelativePath="..\..\common\array.h">
</File>
<File
@@ -259,6 +266,9 @@
RelativePath="..\..\common\ptr.h">
</File>
<File
+ RelativePath="..\..\common\queue.h">
+ </File>
+ <File
RelativePath="..\..\common\rect.h">
</File>
<File
@@ -642,9 +652,6 @@
</Filter>
<Filter
Name="backends">
- <File
- RelativePath="..\..\backends\intern.h">
- </File>
<Filter
Name="sdl">
<File
@@ -680,11 +687,20 @@
<Filter
Name="fs">
<File
+ RelativePath="..\..\backends\fs\abstract-fs.cpp">
+ </File>
+ <File
RelativePath="..\..\backends\fs\abstract-fs.h">
</File>
<File
RelativePath="..\..\backends\fs\fs-factory.h">
</File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.cpp">
+ </File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.h">
+ </File>
<Filter
Name="windows">
<File
@@ -965,6 +981,12 @@
<File
RelativePath="..\..\graphics\surface.h">
</File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.cpp">
+ </File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.h">
+ </File>
<Filter
Name="scaler">
<File
@@ -1041,7 +1063,7 @@
RelativePath="..\..\graphics\scaler\scalebit.h">
</File>
<File
- RelativePath="..\..\graphics\scaler\thumbnail.cpp">
+ RelativePath="..\..\graphics\scaler\thumbnail_intern.cpp">
</File>
</Filter>
<Filter
@@ -1063,12 +1085,24 @@
<Filter
Name="engines">
<File
+ RelativePath="..\..\engines\dialogs.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\dialogs.h">
+ </File>
+ <File
RelativePath="..\..\engines\engine.cpp">
</File>
<File
RelativePath="..\..\engines\engine.h">
</File>
<File
+ RelativePath="..\..\engines\game.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\game.h">
+ </File>
+ <File
RelativePath="..\..\engines\metaengine.h">
</File>
</Filter>
diff --git a/dists/msvc7/sky.vcproj b/dists/msvc7/sky.vcproj
index 188cdb0505..16a8d000d9 100644
--- a/dists/msvc7/sky.vcproj
+++ b/dists/msvc7/sky.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="sky_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/sword1.vcproj b/dists/msvc7/sword1.vcproj
index 3dd3388328..f312bfd8c0 100644
--- a/dists/msvc7/sword1.vcproj
+++ b/dists/msvc7/sword1.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="sword1_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/sword2.vcproj b/dists/msvc7/sword2.vcproj
index 07382a5c0a..c852510087 100644
--- a/dists/msvc7/sword2.vcproj
+++ b/dists/msvc7/sword2.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,14 +61,16 @@
IntermediateDirectory="sword2_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc7/tinsel.vcproj b/dists/msvc7/tinsel.vcproj
new file mode 100644
index 0000000000..c1709e2b61
--- /dev/null
+++ b/dists/msvc7/tinsel.vcproj
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.00"
+ Name="tinsel"
+ ProjectGUID="{22AA7760-2C91-11DD-BD0B-0800200C9A66}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="tinsel_Debug"
+ IntermediateDirectory="tinsel_Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
+ Optimization="0"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
+ PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
+ MinimalRebuild="TRUE"
+ ExceptionHandling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ BufferSecurityCheck="TRUE"
+ EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
+ ForceConformanceInForLoopScope="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ WarnAsError="TRUE"
+ SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/tinsel.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="tinsel_Release"
+ IntermediateDirectory="tinsel_Release"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="TRUE"
+ AdditionalIncludeDirectories="../../;../../engines"
+ PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
+ StringPooling="TRUE"
+ ExceptionHandling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ EnableFunctionLevelLinking="FALSE"
+ DisableLanguageExtensions="FALSE"
+ ForceConformanceInForLoopScope="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ WarnAsError="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/tinsel.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <Files>
+ <File
+ RelativePath="..\..\engines\tinsel\actors.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\actors.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\anim.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\anim.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\background.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\background.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\bg.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cliprect.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cliprect.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\config.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\config.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\coroutine.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cursor.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cursor.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\debugger.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\debugger.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\detection.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\dw.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\effect.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\events.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\events.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\faders.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\faders.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\film.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\font.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\font.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\graphics.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\graphics.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\handle.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\handle.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\heapmem.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\heapmem.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\inventory.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\inventory.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\mareels.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\move.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\move.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\multiobj.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\multiobj.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\music.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\music.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\object.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\object.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\palette.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\palette.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pcode.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pcode.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pdisplay.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pid.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\play.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\polygons.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\polygons.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\rince.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\rince.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\saveload.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\savescn.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\savescn.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scene.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scene.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sched.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sched.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scn.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scn.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scroll.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scroll.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\serializer.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sound.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sound.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\strres.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\strres.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\text.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\text.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\timers.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\timers.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinlib.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinlib.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinsel.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinsel.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\token.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\token.h">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/dists/msvc7/touche.vcproj b/dists/msvc7/touche.vcproj
index 7b81ab2052..983e848226 100644
--- a/dists/msvc7/touche.vcproj
+++ b/dists/msvc7/touche.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -57,12 +61,14 @@
IntermediateDirectory="touche_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -75,6 +81,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/agi.vcproj b/dists/msvc71/agi.vcproj
index dc4697a4fd..de73c01ff4 100644
--- a/dists/msvc71/agi.vcproj
+++ b/dists/msvc71/agi.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="agi_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/agos.vcproj b/dists/msvc71/agos.vcproj
index 7f01df5f68..3bdde3b847 100644
--- a/dists/msvc71/agos.vcproj
+++ b/dists/msvc71/agos.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="agos_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/cine.vcproj b/dists/msvc71/cine.vcproj
index cdea3e9fb8..8fd43a55a8 100644
--- a/dists/msvc71/cine.vcproj
+++ b/dists/msvc71/cine.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="cine_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/cruise.vcproj b/dists/msvc71/cruise.vcproj
index 53ed72f60e..a03a63ae4d 100644
--- a/dists/msvc71/cruise.vcproj
+++ b/dists/msvc71/cruise.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="cruise_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -159,9 +166,6 @@
RelativePath="..\..\engines\cruise\dataLoader.h">
</File>
<File
- RelativePath="..\..\engines\cruise\decompiler.cpp">
- </File>
- <File
RelativePath="..\..\engines\cruise\delphine-unpack.cpp">
</File>
<File
diff --git a/dists/msvc71/drascula.vcproj b/dists/msvc71/drascula.vcproj
index 9160a02bbf..72eecd1a3f 100644
--- a/dists/msvc71/drascula.vcproj
+++ b/dists/msvc71/drascula.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="drascula_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/gob.vcproj b/dists/msvc71/gob.vcproj
index 3d6408cdf5..972e8ab12e 100644
--- a/dists/msvc71/gob.vcproj
+++ b/dists/msvc71/gob.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="gob_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -282,6 +289,12 @@
RelativePath="..\..\engines\gob\inter_v4.cpp">
</File>
<File
+ RelativePath="..\..\engines\gob\inter_v5.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\gob\inter_v6.cpp">
+ </File>
+ <File
RelativePath="..\..\engines\gob\map.cpp">
</File>
<File
@@ -378,6 +391,9 @@
RelativePath="..\..\engines\gob\video_v2.cpp">
</File>
<File
+ RelativePath="..\..\engines\gob\video_v6.cpp">
+ </File>
+ <File
RelativePath="..\..\engines\gob\videoplayer.cpp">
</File>
<File
diff --git a/dists/msvc71/igor.vcproj b/dists/msvc71/igor.vcproj
index 20324afba4..887cfe0c17 100644
--- a/dists/msvc71/igor.vcproj
+++ b/dists/msvc71/igor.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="igor_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/kyra.vcproj b/dists/msvc71/kyra.vcproj
index efc37c251e..b70f187ae9 100644
--- a/dists/msvc71/kyra.vcproj
+++ b/dists/msvc71/kyra.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="kyra_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -219,6 +226,12 @@
RelativePath="..\..\engines\kyra\resource.h">
</File>
<File
+ RelativePath="..\..\engines\kyra\resource_intern.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\kyra\resource_intern.h">
+ </File>
+ <File
RelativePath="..\..\engines\kyra\saveload.cpp">
</File>
<File
diff --git a/dists/msvc71/lure.vcproj b/dists/msvc71/lure.vcproj
index 3ca3116962..4bda34c098 100644
--- a/dists/msvc71/lure.vcproj
+++ b/dists/msvc71/lure.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="lure_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/m4.vcproj b/dists/msvc71/m4.vcproj
index d7aefaa439..26d18c62a1 100644
--- a/dists/msvc71/m4.vcproj
+++ b/dists/msvc71/m4.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="m4_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/made.vcproj b/dists/msvc71/made.vcproj
index 5d0dd621e8..a21ab9cf62 100644
--- a/dists/msvc71/made.vcproj
+++ b/dists/msvc71/made.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="made_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/parallaction.vcproj b/dists/msvc71/parallaction.vcproj
index c72fb68234..22a564be40 100644
--- a/dists/msvc71/parallaction.vcproj
+++ b/dists/msvc71/parallaction.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="parallaction_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -219,6 +226,9 @@
RelativePath="..\..\engines\parallaction\saveload.cpp">
</File>
<File
+ RelativePath="..\..\engines\parallaction\saveload.h">
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\sound.cpp">
</File>
<File
diff --git a/dists/msvc71/queen.vcproj b/dists/msvc71/queen.vcproj
index eefa686767..063425c52a 100644
--- a/dists/msvc71/queen.vcproj
+++ b/dists/msvc71/queen.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="queen_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/saga.vcproj b/dists/msvc71/saga.vcproj
index 388dd64ff2..588ad2873c 100644
--- a/dists/msvc71/saga.vcproj
+++ b/dists/msvc71/saga.vcproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="Windows-1252"?>
+<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="saga_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/scumm.vcproj b/dists/msvc71/scumm.vcproj
index 661cc1fa19..b70e50bb05 100644
--- a/dists/msvc71/scumm.vcproj
+++ b/dists/msvc71/scumm.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="scumm_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -119,12 +126,6 @@
RelativePath="..\..\engines\scumm\smush\channel.h">
</File>
<File
- RelativePath="..\..\engines\scumm\smush\chunk.cpp">
- </File>
- <File
- RelativePath="..\..\engines\scumm\smush\chunk.h">
- </File>
- <File
RelativePath="..\..\engines\scumm\smush\chunk_type.h">
</File>
<File
@@ -567,9 +568,6 @@
RelativePath="..\..\engines\scumm\string.cpp">
</File>
<File
- RelativePath="..\..\engines\scumm\thumbnail.cpp">
- </File>
- <File
RelativePath="..\..\engines\scumm\usage_bits.cpp">
</File>
<File
diff --git a/dists/msvc71/scummvm.vcproj b/dists/msvc71/scummvm.vcproj
index 6234c89dd5..0648d5a43f 100644
--- a/dists/msvc71/scummvm.vcproj
+++ b/dists/msvc71/scummvm.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_NASM;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,11 +29,14 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -74,14 +78,16 @@
IntermediateDirectory="scummvm_Release"
ConfigurationType="1"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
StringPooling="TRUE"
MinimalRebuild="FALSE"
@@ -94,12 +100,13 @@
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib"
+ AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib tinsel_release/tinsel.lib"
OutputFile="$(OutDir)/scummvm.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@@ -144,12 +151,6 @@
RelativePath="..\..\base\commandLine.h">
</File>
<File
- RelativePath="..\..\base\game.cpp">
- </File>
- <File
- RelativePath="..\..\base\game.h">
- </File>
- <File
RelativePath="..\..\base\internal_version.h">
</File>
<File
@@ -183,6 +184,12 @@
RelativePath="..\..\common\algorithm.h">
</File>
<File
+ RelativePath="..\..\common\archive.cpp">
+ </File>
+ <File
+ RelativePath="..\..\common\archive.h">
+ </File>
+ <File
RelativePath="..\..\common\array.h">
</File>
<File
@@ -273,6 +280,9 @@
RelativePath="..\..\common\ptr.h">
</File>
<File
+ RelativePath="..\..\common\queue.h">
+ </File>
+ <File
RelativePath="..\..\common\rect.h">
</File>
<File
@@ -656,9 +666,6 @@
</Filter>
<Filter
Name="backends">
- <File
- RelativePath="..\..\backends\intern.h">
- </File>
<Filter
Name="sdl">
<File
@@ -694,11 +701,20 @@
<Filter
Name="fs">
<File
+ RelativePath="..\..\backends\fs\abstract-fs.cpp">
+ </File>
+ <File
RelativePath="..\..\backends\fs\abstract-fs.h">
</File>
<File
RelativePath="..\..\backends\fs\fs-factory.h">
</File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.cpp">
+ </File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.h">
+ </File>
<Filter
Name="windows">
<File
@@ -979,6 +995,12 @@
<File
RelativePath="..\..\graphics\surface.h">
</File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.cpp">
+ </File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.h">
+ </File>
<Filter
Name="scaler">
<File
@@ -1055,7 +1077,7 @@
RelativePath="..\..\graphics\scaler\scalebit.h">
</File>
<File
- RelativePath="..\..\graphics\scaler\thumbnail.cpp">
+ RelativePath="..\..\graphics\scaler\thumbnail_intern.cpp">
</File>
</Filter>
<Filter
@@ -1077,12 +1099,24 @@
<Filter
Name="engines">
<File
+ RelativePath="..\..\engines\dialogs.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\dialogs.h">
+ </File>
+ <File
RelativePath="..\..\engines\engine.cpp">
</File>
<File
RelativePath="..\..\engines\engine.h">
</File>
<File
+ RelativePath="..\..\engines\game.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\game.h">
+ </File>
+ <File
RelativePath="..\..\engines\metaengine.h">
</File>
</Filter>
diff --git a/dists/msvc71/sky.vcproj b/dists/msvc71/sky.vcproj
index cb8303a6b2..b49534babb 100644
--- a/dists/msvc71/sky.vcproj
+++ b/dists/msvc71/sky.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="sky_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/sword1.vcproj b/dists/msvc71/sword1.vcproj
index 602a5a9529..953d6ca88f 100644
--- a/dists/msvc71/sword1.vcproj
+++ b/dists/msvc71/sword1.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="sword1_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/sword2.vcproj b/dists/msvc71/sword2.vcproj
index f97da0ea91..d758641d5b 100644
--- a/dists/msvc71/sword2.vcproj
+++ b/dists/msvc71/sword2.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,14 +67,16 @@
IntermediateDirectory="sword2_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="TRUE"
ExceptionHandling="TRUE"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc71/tinsel.vcproj b/dists/msvc71/tinsel.vcproj
new file mode 100644
index 0000000000..b8475b5866
--- /dev/null
+++ b/dists/msvc71/tinsel.vcproj
@@ -0,0 +1,363 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="tinsel"
+ ProjectGUID="{22AA7760-2C91-11DD-BD0B-0800200C9A66}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="tinsel_Debug"
+ IntermediateDirectory="tinsel_Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
+ Optimization="0"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
+ PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
+ MinimalRebuild="TRUE"
+ ExceptionHandling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ BufferSecurityCheck="TRUE"
+ EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
+ ForceConformanceInForLoopScope="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ WarnAsError="TRUE"
+ SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/tinsel.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="tinsel_Release"
+ IntermediateDirectory="tinsel_Release"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="TRUE"
+ AdditionalIncludeDirectories="../../;../../engines"
+ PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
+ StringPooling="TRUE"
+ ExceptionHandling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ EnableFunctionLevelLinking="FALSE"
+ DisableLanguageExtensions="FALSE"
+ ForceConformanceInForLoopScope="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ WarnAsError="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/tinsel.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\engines\tinsel\actors.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\actors.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\anim.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\anim.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\background.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\background.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\bg.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cliprect.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cliprect.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\config.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\config.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\coroutine.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cursor.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\cursor.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\debugger.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\debugger.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\detection.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\dw.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\effect.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\events.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\events.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\faders.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\faders.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\film.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\font.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\font.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\graphics.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\graphics.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\handle.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\handle.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\heapmem.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\heapmem.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\inventory.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\inventory.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\mareels.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\move.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\move.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\multiobj.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\multiobj.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\music.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\music.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\object.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\object.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\palette.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\palette.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pcode.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pcode.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pdisplay.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\pid.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\play.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\polygons.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\polygons.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\rince.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\rince.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\saveload.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\savescn.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\savescn.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scene.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scene.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sched.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sched.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scn.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scn.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scroll.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\scroll.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\serializer.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sound.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\sound.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\strres.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\strres.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\text.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\text.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\timers.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\timers.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinlib.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinlib.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinsel.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\tinsel.h">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\token.cpp">
+ </File>
+ <File
+ RelativePath="..\..\engines\tinsel\token.h">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/dists/msvc71/touche.vcproj b/dists/msvc71/touche.vcproj
index e40e861542..bd309c5ce3 100644
--- a/dists/msvc71/touche.vcproj
+++ b/dists/msvc71/touche.vcproj
@@ -20,7 +20,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
@@ -28,10 +29,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
SuppressStartupBanner="FALSE"
+ Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -63,12 +67,14 @@
IntermediateDirectory="touche_Release"
ConfigurationType="4"
CharacterSet="2"
- WholeProgramOptimization="FALSE">
+ WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -81,6 +87,7 @@
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
+ WarnAsError="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/dists/msvc8/agi.vcproj b/dists/msvc8/agi.vcproj
index 990cf155e0..08d734221b 100644
--- a/dists/msvc8/agi.vcproj
+++ b/dists/msvc8/agi.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/agos.vcproj b/dists/msvc8/agos.vcproj
index 6a7f937676..3fd581a45b 100644
--- a/dists/msvc8/agos.vcproj
+++ b/dists/msvc8/agos.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/cine.vcproj b/dists/msvc8/cine.vcproj
index cd8a6673db..22061d57c0 100644
--- a/dists/msvc8/cine.vcproj
+++ b/dists/msvc8/cine.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/cruise.vcproj b/dists/msvc8/cruise.vcproj
index f183d07ee3..d8c81b2a01 100644
--- a/dists/msvc8/cruise.vcproj
+++ b/dists/msvc8/cruise.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
@@ -225,10 +231,6 @@
>
</File>
<File
- RelativePath="..\..\engines\cruise\decompiler.cpp"
- >
- </File>
- <File
RelativePath="..\..\engines\cruise\delphine-unpack.cpp"
>
</File>
diff --git a/dists/msvc8/drascula.vcproj b/dists/msvc8/drascula.vcproj
index 0867377f31..e096b33239 100644
--- a/dists/msvc8/drascula.vcproj
+++ b/dists/msvc8/drascula.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/gob.vcproj b/dists/msvc8/gob.vcproj
index c178caf8be..982f7e3f0c 100644
--- a/dists/msvc8/gob.vcproj
+++ b/dists/msvc8/gob.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,20 +114,23 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
DebugInformationFormat="0"
/>
<Tool
@@ -389,6 +395,14 @@
>
</File>
<File
+ RelativePath="..\..\engines\gob\inter_v5.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\gob\inter_v6.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\gob\map.cpp"
>
</File>
@@ -517,6 +531,10 @@
>
</File>
<File
+ RelativePath="..\..\engines\gob\video_v6.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\gob\videoplayer.cpp"
>
</File>
diff --git a/dists/msvc8/igor.vcproj b/dists/msvc8/igor.vcproj
index f2470ee633..dbfc5cc6bc 100644
--- a/dists/msvc8/igor.vcproj
+++ b/dists/msvc8/igor.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/kyra.vcproj b/dists/msvc8/kyra.vcproj
index 00f7749f4d..8798677947 100644
--- a/dists/msvc8/kyra.vcproj
+++ b/dists/msvc8/kyra.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
@@ -305,6 +311,14 @@
>
</File>
<File
+ RelativePath="..\..\engines\kyra\resource_intern.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\kyra\resource_intern.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\kyra\saveload.cpp"
>
</File>
diff --git a/dists/msvc8/lure.vcproj b/dists/msvc8/lure.vcproj
index 887a8d4fb0..5102e74117 100644
--- a/dists/msvc8/lure.vcproj
+++ b/dists/msvc8/lure.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/m4.vcproj b/dists/msvc8/m4.vcproj
index a3f286bff3..9d27e60132 100644
--- a/dists/msvc8/m4.vcproj
+++ b/dists/msvc8/m4.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/made.vcproj b/dists/msvc8/made.vcproj
index b3c309b334..13b32b61d5 100644
--- a/dists/msvc8/made.vcproj
+++ b/dists/msvc8/made.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/parallaction.vcproj b/dists/msvc8/parallaction.vcproj
index e268fe1e6b..ddb0a13b46 100644
--- a/dists/msvc8/parallaction.vcproj
+++ b/dists/msvc8/parallaction.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
@@ -305,6 +311,10 @@
>
</File>
<File
+ RelativePath="..\..\engines\parallaction\saveload.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\sound.cpp"
>
</File>
diff --git a/dists/msvc8/queen.vcproj b/dists/msvc8/queen.vcproj
index 6be3251d8c..eec37976bf 100644
--- a/dists/msvc8/queen.vcproj
+++ b/dists/msvc8/queen.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/saga.vcproj b/dists/msvc8/saga.vcproj
index 79f7d35fb5..bd38dbbfca 100644
--- a/dists/msvc8/saga.vcproj
+++ b/dists/msvc8/saga.vcproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="Windows-1252"?>
+<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/scumm.vcproj b/dists/msvc8/scumm.vcproj
index 42a4ff6993..021df227e8 100644
--- a/dists/msvc8/scumm.vcproj
+++ b/dists/msvc8/scumm.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,10 +114,12 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
@@ -173,14 +178,6 @@
>
</File>
<File
- RelativePath="..\..\engines\scumm\smush\chunk.cpp"
- >
- </File>
- <File
- RelativePath="..\..\engines\scumm\smush\chunk.h"
- >
- </File>
- <File
RelativePath="..\..\engines\scumm\smush\chunk_type.h"
>
</File>
@@ -770,10 +767,6 @@
>
</File>
<File
- RelativePath="..\..\engines\scumm\thumbnail.cpp"
- >
- </File>
- <File
RelativePath="..\..\engines\scumm\usage_bits.cpp"
>
</File>
diff --git a/dists/msvc8/scummvm.vcproj b/dists/msvc8/scummvm.vcproj
index 8b10a22eb6..5247336dc0 100644
--- a/dists/msvc8/scummvm.vcproj
+++ b/dists/msvc8/scummvm.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_NASM;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,12 +50,14 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -129,10 +132,12 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
StringPooling="true"
MinimalRebuild="false"
@@ -140,6 +145,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
@@ -158,7 +164,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib"
+ AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib tinsel_release/tinsel.lib"
OutputFile="$(OutDir)/scummvm.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -211,14 +217,6 @@
>
</File>
<File
- RelativePath="..\..\base\game.cpp"
- >
- </File>
- <File
- RelativePath="..\..\base\game.h"
- >
- </File>
- <File
RelativePath="..\..\base\internal_version.h"
>
</File>
@@ -263,6 +261,14 @@
>
</File>
<File
+ RelativePath="..\..\common\archive.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\archive.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\array.h"
>
</File>
@@ -383,6 +389,10 @@
>
</File>
<File
+ RelativePath="..\..\common\queue.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\rect.h"
>
</File>
@@ -891,10 +901,6 @@
<Filter
Name="backends"
>
- <File
- RelativePath="..\..\backends\intern.h"
- >
- </File>
<Filter
Name="sdl"
>
@@ -941,6 +947,10 @@
Name="fs"
>
<File
+ RelativePath="..\..\backends\fs\abstract-fs.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\backends\fs\abstract-fs.h"
>
</File>
@@ -948,6 +958,14 @@
RelativePath="..\..\backends\fs\fs-factory.h"
>
</File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.h"
+ >
+ </File>
<Filter
Name="windows"
>
@@ -1321,6 +1339,14 @@
RelativePath="..\..\graphics\surface.h"
>
</File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.h"
+ >
+ </File>
<Filter
Name="scaler"
>
@@ -1421,7 +1447,7 @@
>
</File>
<File
- RelativePath="..\..\graphics\scaler\thumbnail.cpp"
+ RelativePath="..\..\graphics\scaler\thumbnail_intern.cpp"
>
</File>
</Filter>
@@ -1450,6 +1476,14 @@
Name="engines"
>
<File
+ RelativePath="..\..\engines\dialogs.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\dialogs.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\engine.cpp"
>
</File>
@@ -1458,6 +1492,14 @@
>
</File>
<File
+ RelativePath="..\..\engines\game.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\game.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\metaengine.h"
>
</File>
diff --git a/dists/msvc8/sky.vcproj b/dists/msvc8/sky.vcproj
index b2e77699e0..ffed869c8b 100644
--- a/dists/msvc8/sky.vcproj
+++ b/dists/msvc8/sky.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,10 +114,12 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
diff --git a/dists/msvc8/sword1.vcproj b/dists/msvc8/sword1.vcproj
index 689f6dc1c4..c242a42e70 100644
--- a/dists/msvc8/sword1.vcproj
+++ b/dists/msvc8/sword1.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/sword2.vcproj b/dists/msvc8/sword2.vcproj
index e68a32631e..b90f38be9f 100644
--- a/dists/msvc8/sword2.vcproj
+++ b/dists/msvc8/sword2.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -111,16 +114,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/tinsel.vcproj b/dists/msvc8/tinsel.vcproj
index cb6ba0c2e8..b5397681bb 100644
--- a/dists/msvc8/tinsel.vcproj
+++ b/dists/msvc8/tinsel.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="8,00"
Name="tinsel"
ProjectGUID="{22AA7760-2C91-11DD-BD0B-0800200C9A66}"
RootNamespace="tinsel"
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8/touche.vcproj b/dists/msvc8/touche.vcproj
index 0a517bb40c..d314a910da 100644
--- a/dists/msvc8/touche.vcproj
+++ b/dists/msvc8/touche.vcproj
@@ -41,7 +41,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -49,11 +50,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -113,6 +116,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -121,6 +126,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc8_to_msvc7_71.bat b/dists/msvc8_to_msvc7_71.bat
index 71d04f68a3..020a26172a 100644
--- a/dists/msvc8_to_msvc7_71.bat
+++ b/dists/msvc8_to_msvc7_71.bat
@@ -19,20 +19,14 @@ rpl -e -q "\t\tKeyword=" "\tKeyword=" msvc71\*.vcproj
rpl -e -q "\t<ToolFiles>\n\t</ToolFiles>\n" "" msvc71\*.vcproj
rpl -e -q " /wd4996" "" msvc71\*.vcproj
rpl -e -q "ExceptionHandling=\"1\"" "ExceptionHandling=\"true\"" msvc71\*.vcproj
-rpl -e -q "\t\t\t\tWarnAsError=\"false\"\n" "" msvc71\*.vcproj
rpl -e -q "\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n" "" msvc71\*.vcproj
rpl -e -q "\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n" "" msvc71\*.vcproj
rpl -e -q "\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n" "" msvc71\*.vcproj
rpl -e -q "\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n" "" msvc71\*.vcproj
rpl -e -q "\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t/>\n" "" msvc71\*.vcproj
rpl -e -q "\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n" "" msvc71\*.vcproj
-rpl -e -q "WholeProgramOptimization=\"1\"" "WholeProgramOptimization=\"false\"" msvc71\*.vcproj
-rpl -e -q "Optimization=\"3\"" "Optimization=\"2\"" msvc71\*.vcproj
-rpl -e -q "InlineFunctionExpansion=\"2\"" "InlineFunctionExpansion=\"1\"" msvc71\*.vcproj
+rpl -e -q "WholeProgramOptimization=\"1\"" "WholeProgramOptimization=\"true\"" msvc71\*.vcproj
rpl -e -q "ExceptionHandling=\"1\"" "ExceptionHandling=\"true\"" msvc71\*.vcproj
-rpl -e -q "\t\t\t\tWarnAsError=\"true\"\n" "" msvc71\*.vcproj
-rpl -e -q "\t\t\t\tDisableLanguageExtensions=\"false\"\n" "" msvc71\*.vcproj
-rpl -e -q "\t\t\t\tEnableFunctionLevelLinking=\"false\"\n" "\t\t\t\tEnableFunctionLevelLinking=\"false\"\n\t\t\t\tDisableLanguageExtensions=\"false\"\n" msvc71\*.vcproj
rem Change multi-line XML closing tags to single line
rpl -e -q "\"\n\t\0x3e\n" "\"\0x3e\n" msvc71\*.vcproj
rpl -e -q "\"\n\t/\0x3e\n" "\"/\0x3e\n" msvc71\*.vcproj
diff --git a/dists/msvc9/agi.vcproj b/dists/msvc9/agi.vcproj
index d0d93bb743..de79be933d 100644
--- a/dists/msvc9/agi.vcproj
+++ b/dists/msvc9/agi.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/agos.vcproj b/dists/msvc9/agos.vcproj
index 6cc268c2f8..a584d8719a 100644
--- a/dists/msvc9/agos.vcproj
+++ b/dists/msvc9/agos.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/cine.vcproj b/dists/msvc9/cine.vcproj
index c01508ff9a..194e792dfa 100644
--- a/dists/msvc9/cine.vcproj
+++ b/dists/msvc9/cine.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/cruise.vcproj b/dists/msvc9/cruise.vcproj
index 19a96eb7be..c4cd6195eb 100644
--- a/dists/msvc9/cruise.vcproj
+++ b/dists/msvc9/cruise.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
@@ -226,10 +232,6 @@
>
</File>
<File
- RelativePath="..\..\engines\cruise\decompiler.cpp"
- >
- </File>
- <File
RelativePath="..\..\engines\cruise\delphine-unpack.cpp"
>
</File>
diff --git a/dists/msvc9/drascula.vcproj b/dists/msvc9/drascula.vcproj
index 45a75cb7a2..a0ed0eaa09 100644
--- a/dists/msvc9/drascula.vcproj
+++ b/dists/msvc9/drascula.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/gob.vcproj b/dists/msvc9/gob.vcproj
index e6c55519b0..0ebeb75f20 100644
--- a/dists/msvc9/gob.vcproj
+++ b/dists/msvc9/gob.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,20 +115,23 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
DebugInformationFormat="0"
/>
<Tool
@@ -390,6 +396,14 @@
>
</File>
<File
+ RelativePath="..\..\engines\gob\inter_v5.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\gob\inter_v6.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\gob\map.cpp"
>
</File>
@@ -518,6 +532,10 @@
>
</File>
<File
+ RelativePath="..\..\engines\gob\video_v6.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\gob\videoplayer.cpp"
>
</File>
diff --git a/dists/msvc9/igor.vcproj b/dists/msvc9/igor.vcproj
index ff2579a97d..b812db787c 100644
--- a/dists/msvc9/igor.vcproj
+++ b/dists/msvc9/igor.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/kyra.vcproj b/dists/msvc9/kyra.vcproj
index ba1b9eb949..e65d02f5cd 100644
--- a/dists/msvc9/kyra.vcproj
+++ b/dists/msvc9/kyra.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
@@ -306,6 +312,14 @@
>
</File>
<File
+ RelativePath="..\..\engines\kyra\resource_intern.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\kyra\resource_intern.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\kyra\saveload.cpp"
>
</File>
diff --git a/dists/msvc9/lure.vcproj b/dists/msvc9/lure.vcproj
index 2745b0a2bc..2915a69dbc 100644
--- a/dists/msvc9/lure.vcproj
+++ b/dists/msvc9/lure.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/m4.vcproj b/dists/msvc9/m4.vcproj
index 786b014e90..89cf4cef78 100644
--- a/dists/msvc9/m4.vcproj
+++ b/dists/msvc9/m4.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/made.vcproj b/dists/msvc9/made.vcproj
index a96ae262cb..880b484be3 100644
--- a/dists/msvc9/made.vcproj
+++ b/dists/msvc9/made.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/parallaction.vcproj b/dists/msvc9/parallaction.vcproj
index f901976c37..5c91264919 100644
--- a/dists/msvc9/parallaction.vcproj
+++ b/dists/msvc9/parallaction.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
@@ -306,6 +312,10 @@
>
</File>
<File
+ RelativePath="..\..\engines\parallaction\saveload.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\sound.cpp"
>
</File>
diff --git a/dists/msvc9/queen.vcproj b/dists/msvc9/queen.vcproj
index d8fb96ac0b..384cede45c 100644
--- a/dists/msvc9/queen.vcproj
+++ b/dists/msvc9/queen.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/saga.vcproj b/dists/msvc9/saga.vcproj
index 9675dda2e9..241bd5b498 100644
--- a/dists/msvc9/saga.vcproj
+++ b/dists/msvc9/saga.vcproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="Windows-1252"?>
+<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/scumm.vcproj b/dists/msvc9/scumm.vcproj
index 230102db35..afb79cc3b6 100644
--- a/dists/msvc9/scumm.vcproj
+++ b/dists/msvc9/scumm.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,10 +115,12 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
@@ -174,14 +179,6 @@
>
</File>
<File
- RelativePath="..\..\engines\scumm\smush\chunk.cpp"
- >
- </File>
- <File
- RelativePath="..\..\engines\scumm\smush\chunk.h"
- >
- </File>
- <File
RelativePath="..\..\engines\scumm\smush\chunk_type.h"
>
</File>
@@ -771,10 +768,6 @@
>
</File>
<File
- RelativePath="..\..\engines\scumm\thumbnail.cpp"
- >
- </File>
- <File
RelativePath="..\..\engines\scumm\usage_bits.cpp"
>
</File>
diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj
index fc6713c49f..09b496b087 100644
--- a/dists/msvc9/scummvm.vcproj
+++ b/dists/msvc9/scummvm.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_NASM;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,12 +51,14 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -129,10 +132,12 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL"
StringPooling="true"
MinimalRebuild="false"
@@ -140,6 +145,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
@@ -158,7 +164,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib"
+ AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib libmpeg2.lib saga_release/saga.lib agi_release/agi.lib sword1_release/sword1.lib sword2_release/sword2.lib lure_release/lure.lib cine_release/cine.lib cruise_release/cruise.lib igor_release/igor.lib kyra_release/kyra.lib gob_release/gob.lib queen_release/queen.lib scumm_release/scumm.lib agos_release/agos.lib sky_release/sky.lib drascula_release/drascula.lib parallaction_release/parallaction.lib m4_release/m4.lib made_release/made.lib tinsel_release/tinsel.lib"
OutputFile="$(OutDir)/scummvm.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -210,14 +216,6 @@
>
</File>
<File
- RelativePath="..\..\base\game.cpp"
- >
- </File>
- <File
- RelativePath="..\..\base\game.h"
- >
- </File>
- <File
RelativePath="..\..\base\internal_version.h"
>
</File>
@@ -262,6 +260,14 @@
>
</File>
<File
+ RelativePath="..\..\common\archive.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\archive.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\array.h"
>
</File>
@@ -382,6 +388,10 @@
>
</File>
<File
+ RelativePath="..\..\common\queue.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\rect.h"
>
</File>
@@ -898,10 +908,6 @@
<Filter
Name="backends"
>
- <File
- RelativePath="..\..\backends\intern.h"
- >
- </File>
<Filter
Name="sdl"
>
@@ -948,6 +954,10 @@
Name="fs"
>
<File
+ RelativePath="..\..\backends\fs\abstract-fs.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\backends\fs\abstract-fs.h"
>
</File>
@@ -955,6 +965,14 @@
RelativePath="..\..\backends\fs\fs-factory.h"
>
</File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\backends\fs\stdiostream.h"
+ >
+ </File>
<Filter
Name="windows"
>
@@ -1350,13 +1368,6 @@
<File
RelativePath="..\..\graphics\VectorRenderer.h"
>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- />
- </FileConfiguration>
</File>
<File
RelativePath="..\..\graphics\VectorRendererSpec.cpp"
@@ -1366,6 +1377,14 @@
RelativePath="..\..\graphics\VectorRendererSpec.h"
>
</File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\graphics\thumbnail.h"
+ >
+ </File>
<Filter
Name="scaler"
>
@@ -1466,7 +1485,7 @@
>
</File>
<File
- RelativePath="..\..\graphics\scaler\thumbnail.cpp"
+ RelativePath="..\..\graphics\scaler\thumbnail_intern.cpp"
>
</File>
</Filter>
@@ -1495,6 +1514,14 @@
Name="engines"
>
<File
+ RelativePath="..\..\engines\dialogs.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\dialogs.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\engine.cpp"
>
</File>
@@ -1503,6 +1530,14 @@
>
</File>
<File
+ RelativePath="..\..\engines\game.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\game.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\metaengine.h"
>
</File>
diff --git a/dists/msvc9/sky.vcproj b/dists/msvc9/sky.vcproj
index d908ceb0f5..df74f239c2 100644
--- a/dists/msvc9/sky.vcproj
+++ b/dists/msvc9/sky.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,10 +115,12 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
StringPooling="true"
ExceptionHandling="1"
diff --git a/dists/msvc9/sword1.vcproj b/dists/msvc9/sword1.vcproj
index dc501c3be1..d636e044e4 100644
--- a/dists/msvc9/sword1.vcproj
+++ b/dists/msvc9/sword1.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/sword2.vcproj b/dists/msvc9/sword2.vcproj
index 5f092967d7..fb8c4d8db1 100644
--- a/dists/msvc9/sword2.vcproj
+++ b/dists/msvc9/sword2.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -112,16 +115,19 @@
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
- AdditionalIncludeDirectories="../..;../../engines"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/tinsel.vcproj b/dists/msvc9/tinsel.vcproj
index 7623290e80..cef9683e8b 100644
--- a/dists/msvc9/tinsel.vcproj
+++ b/dists/msvc9/tinsel.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9.00"
+ Version="9,00"
Name="tinsel"
ProjectGUID="{22AA7760-2C91-11DD-BD0B-0800200C9A66}"
RootNamespace="tinsel"
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/msvc9/touche.vcproj b/dists/msvc9/touche.vcproj
index 72b61bc00e..0ff5673c56 100644
--- a/dists/msvc9/touche.vcproj
+++ b/dists/msvc9/touche.vcproj
@@ -42,7 +42,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="0"
- AdditionalIncludeDirectories="../..;../../engines"
+ InlineFunctionExpansion="0"
+ AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
MinimalRebuild="true"
ExceptionHandling="1"
@@ -50,11 +51,13 @@
RuntimeLibrary="1"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
- WarnAsError="false"
+ WarnAsError="true"
SuppressStartupBanner="false"
+ Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
@@ -114,6 +117,8 @@
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
Optimization="3"
InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="../../;../../engines"
PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS"
@@ -122,6 +127,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
+ DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
UsePrecompiledHeader="0"
WarningLevel="4"
diff --git a/dists/redhat/scummvm-tools.spec b/dists/redhat/scummvm-tools.spec
index 5ca5fe9cf8..564fc17274 100644
--- a/dists/redhat/scummvm-tools.spec
+++ b/dists/redhat/scummvm-tools.spec
@@ -19,6 +19,7 @@ Source : %{name}-%{version}.tar.bz2
BuildRoot : %{_tmppath}/%{name}-%{version}-root
BuildRequires : zlib-devel
+BuildRequires : wxGTK-devel
#------------------------------------------------------------------------------
# Description
#------------------------------------------------------------------------------
@@ -36,10 +37,12 @@ make
echo -e "\t\tThis script is installed as\n\t\t"%{_datadir}/scummvm-tools/convert_dxa.sh.sample >> README
%install
-install -m755 -D encode_dxa %{buildroot}%{_bindir}/encode_dxa
+install -m755 -d %{buildroot}%{_bindir}
install -m755 -D compress_{agos,kyra,queen,saga,scumm_bun,scumm_san,scumm_sou,sword1,sword2,touche} %{buildroot}%{_bindir}
-install -m755 -D de{kyra,scumm,sword2} %{buildroot}%{_bindir}
-install -m755 -D extract_{agos,kyra,loom_tg16,mm_apple,mm_c64,mm_nes,scumm_mac,parallaction,zak_c64} %{buildroot}%{_bindir}
+install -m755 -D de{kyra,scumm,sword2,gob} %{buildroot}%{_bindir}
+install -m755 -D encode_dxa %{buildroot}%{_bindir}/encode_dxa
+install -m755 -D extract_{agos,kyra,loom_tg16,mm_apple,mm_c64,mm_nes,scumm_mac,parallaction,zak_c64,gob_stk} %{buildroot}%{_bindir}
+install -m755 -D tools_gui %{buildroot}%{_bindir}/scummvm_tools_gui
install -m644 -D convert_dxa.sh %{buildroot}%{_datadir}/scummvm-tools/convert_dxa.sh.sample
%clean
@@ -54,6 +57,7 @@ rm -Rf ${RPM_BUILD_ROOT}
%attr(0755,root,root)%{_bindir}/de*
%attr(0755,root,root)%{_bindir}/extract_*
%attr(0755,root,root)%{_bindir}/encode_dxa
+%attr(0755,root,root)%{_bindir}/scummvm_tools_gui
%attr(0644,root,root)%{_datadir}/scummvm-tools/convert_dxa.sh.sample
#------------------------------------------------------------------------------
diff --git a/dists/scummvm.6 b/dists/scummvm.6
index 1859dc119a..007e124212 100644
--- a/dists/scummvm.6
+++ b/dists/scummvm.6
@@ -12,7 +12,7 @@
.Sh DESCRIPTION
.Nm
is an interpreter that will play graphic adventure games
-based an a variety of game engines.
+based on a variety of game engines.
.Bl -tag -width Ds
.It Fl F
Force windowed mode.
@@ -172,21 +172,32 @@ Enable copy protection in SCUMM games, when ScummVM disables it
by default.
.It Fl -demo-mode
Start demo mode of Maniac Mansion.
+.It Fl -enable-gs
+Enable Roland GS mode for MIDI playback.
+.It Fl -extrapath= Ns Ar path
+Look for additional game data in
+.Ar path .
.It Fl -joystick= Ns Ar num
Enable input with joystick (default: 0 = first joystick).
.It Fl -multi-midi
Enable combination Adlib and native MIDI.
.It Fl -native-mt32
True Roland MT-32 MIDI (disable GM emulation).
+.It Fl --render-mode= Ns Ar mode
+Enable additional render
+.Ar mode
+(cga, ega, hercGreen, hercAmber, amiga).
+.It Fl -platform= Ns Ar plat
+Specify original platform of game.
.It Fl -output-rate= Ns Ar rate
Set output sample rate in Hz to
.Ar rate
(e.g. 22050).
-.It Fl -platform= Ns Ar plat
-Specify original platform of game.
.It Fl -savepath= Ns Ar path
Look for savegames in
.Ar path .
+.It Fl -soundfont= Ns Ar fILE
+Select the SoundFont for MIDI playback (only supported by some MIDI drivers).
.It Fl -talkspeed= Ns Ar speed
Set talk speed to
.Ar speed
@@ -261,6 +272,4 @@ More information can be found in the README and on the website
.Sh AUTHORS
This manual page written by Jonathan Gray <khalek at scummvm.org>.
ScummVM was written by the ScummVM team.
-See
-.Pa http://www.scummvm.org
-for more information.
+See AUTHORS file for more information.
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 0fb2b87071..75accce341 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -27,7 +27,7 @@ BEGIN
VALUE "FileDescription", "http://www.scummvm.org/\0"
VALUE "FileVersion", "0.13.0svn\0"
VALUE "InternalName", "scummvm\0"
- VALUE "LegalCopyright", "Copyright © 2001-2007 The ScummVM Team\0"
+ VALUE "LegalCopyright", "Copyright © 2001-2008 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"
diff --git a/dists/scummvm.rc.in b/dists/scummvm.rc.in
index 7ef88b0471..80672d54e7 100644
--- a/dists/scummvm.rc.in
+++ b/dists/scummvm.rc.in
@@ -27,7 +27,7 @@ BEGIN
VALUE "FileDescription", "http://www.scummvm.org/\0"
VALUE "FileVersion", "@VERSION@\0"
VALUE "InternalName", "scummvm\0"
- VALUE "LegalCopyright", "Copyright © 2001-2007 The ScummVM Team\0"
+ VALUE "LegalCopyright", "Copyright © 2001-2008 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"
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 9d88dd73ef..a17bdc50cf 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -25,7 +25,6 @@
#include "common/md5.h"
-#include "common/events.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
@@ -61,9 +60,6 @@ void AgiEngine::processEvents() {
while (_eventMan->pollEvent(event)) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _game.quitProgNow = true;
- break;
case Common::EVENT_PREDICTIVE_DIALOG:
if (_predictiveDialogRunning)
break;
@@ -738,6 +734,8 @@ void AgiEngine::initialize() {
_gfx->initVideo();
_sound->initSound();
+ _lastSaveTime = 0;
+
_timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, NULL);
_game.ver = -1; /* Don't display the conf file warning */
@@ -812,4 +810,14 @@ int AgiEngine::go() {
return 0;
}
+void AgiEngine::syncSoundSettings() {
+ int soundVolumeMusic = ConfMan.getInt("music_volume");
+ int soundVolumeSFX = ConfMan.getInt("music_volume");
+ int soundVolumeSpeech = ConfMan.getInt("music_volume");
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
+}
+
} // End of namespace Agi
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 9240d562af..ff2b05ace1 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -530,7 +530,6 @@ struct AgiGame {
/* internal flags */
int playerControl; /**< player is in control */
- int quitProgNow; /**< quit now */
int statusLine; /**< status line on/off */
int clockEnabled; /**< clock is on/off */
int exitAllLogics; /**< break cycle after new.room */
@@ -747,6 +746,8 @@ protected:
int go();
void initialize();
+ uint32 _lastSaveTime;
+
public:
AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc);
virtual ~AgiEngine();
@@ -754,6 +755,8 @@ public:
return _gameId;
}
+ virtual void syncSoundSettings();
+
private:
int _keyQueue[KEY_QUEUE_SIZE];
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index e0babdf926..3d29f45ea5 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -24,7 +24,6 @@
*/
-
#include "agi/agi.h"
#include "agi/sprite.h"
#include "agi/graphics.h"
@@ -116,7 +115,7 @@ void AgiEngine::interpretCycle() {
oldSound = getflag(fSoundOn);
_game.exitAllLogics = false;
- while (runLogic(0) == 0 && !_game.quitProgNow) {
+ while (runLogic(0) == 0 && !quit()) {
_game.vars[vWordNotFound] = 0;
_game.vars[vBorderTouchObj] = 0;
_game.vars[vBorderCode] = 0;
@@ -314,7 +313,6 @@ int AgiEngine::playGame() {
setvar(vTimeDelay, 2); /* "normal" speed */
_game.gfxMode = true;
- _game.quitProgNow = false;
_game.clockEnabled = true;
_game.lineUserInput = 22;
@@ -354,10 +352,16 @@ int AgiEngine::playGame() {
_game.vars[vKey] = 0;
}
- if (_game.quitProgNow == 0xff)
- ec = errRestartGame;
+ // FIXME: This has been broken with the merge of the RTL GSoC project. quit() returns a boolean, and we're trying to
+ // check it against 0xff, which is never going to be true
+ //if (quit() == 0xff)
+ // ec = errRestartGame;
+
+ if (shouldPerformAutoSave(_lastSaveTime)) {
+ saveGame(getSavegameFilename(0), "Autosave");
+ }
- } while (_game.quitProgNow == 0);
+ } while (quit() == 0);
_sound->stopSound();
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index cd6942f9c0..2b2d7e080b 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -2122,11 +2122,23 @@ public:
return "Sierra AGI Engine (C) Sierra On-Line Software";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
-
- const Common::ADGameDescription *fallbackDetect(const FSList *fslist) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
+
+ const Common::ADGameDescription *fallbackDetect(const Common::FSList *fslist) const;
};
+bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
+
bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Agi::AGIGameDescription *gd = (const Agi::AGIGameDescription *)desc;
bool res = true;
@@ -2147,7 +2159,48 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common:
return res;
}
-const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const FSList *fslist) const {
+SaveStateList AgiMetaEngine::listSaves(const char *target) const {
+ const uint32 AGIflag = MKID_BE('AGI:');
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ char saveDesc[31];
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ uint32 type = in->readUint32BE();
+ if (type == AGIflag)
+ in->read(saveDesc, 31);
+ saveList.push_back(SaveStateDescriptor(slotNum, Common::String(saveDesc), *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void AgiMetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".%03d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
+const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSList *fslist) const {
typedef Common::HashMap<Common::String, int32> IntMap;
IntMap allFiles;
bool matchedUsingFilenames = false;
@@ -2156,7 +2209,7 @@ const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const FSList *fsl
WagFileParser wagFileParser;
Common::String wagFilePath;
Common::String description;
- FSList fslistCurrentDir; // Only used if fslist == NULL
+ Common::FSList fslistCurrentDir; // Only used if fslist == NULL
// // Set the defaults for gameid and extra
_gameid = "agi-fanmade";
@@ -2169,8 +2222,8 @@ const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const FSList *fsl
if (path.empty())
path = ".";
- FilesystemNode fsCurrentDir(path);
- fsCurrentDir.getChildren(fslistCurrentDir, FilesystemNode::kListFilesOnly);
+ Common::FilesystemNode fsCurrentDir(path);
+ fsCurrentDir.getChildren(fslistCurrentDir, Common::FilesystemNode::kListFilesOnly);
fslist = &fslistCurrentDir;
}
@@ -2185,7 +2238,7 @@ const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const FSList *fsl
g_fallbackDesc.version = 0x2917;
// First grab all filenames and at the same time count the number of *.wag files
- for (FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) {
+ for (Common::FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) {
if (file->isDirectory()) continue;
Common::String filename = file->getName();
filename.toLowercase();
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index dcf7d83809..656ae232ec 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -47,15 +47,15 @@ int AgiLoader_v3::detectGame() {
int ec = errUnk;
bool found = false;
- FSList fslist;
- FilesystemNode dir(ConfMan.get("path"));
+ Common::FSList fslist;
+ Common::FilesystemNode dir(ConfMan.get("path"));
- if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(fslist, Common::FilesystemNode::kListFilesOnly)) {
warning("AgiEngine: invalid game path '%s'", dir.getPath().c_str());
return errInvalidAGIFile;
}
- for (FSList::const_iterator file = fslist.begin();
+ for (Common::FSList::const_iterator file = fslist.begin();
file != fslist.end() && !found; ++file) {
Common::String f = file->getName();
f.toLowercase();
@@ -230,8 +230,8 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) {
debugC(3, kDebugLevelResources, "offset = %d", agid->offset);
debugC(3, kDebugLevelResources, "x = %x %x", x[0], x[1]);
error("ACK! BAD RESOURCE");
-
- g_system->quit();
+
+ _vm->quitGame();
}
agid->len = READ_LE_UINT16((uint8 *) x + 3); /* uncompressed size */
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 7ecedfbc8c..758bff0cb6 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -1213,11 +1213,11 @@ cmd(quit) {
g_sound->stopSound();
if (p0) {
- game.quitProgNow = true;
+ g_agi->quitGame();
} else {
if (g_agi->selectionBox
(" Quit the game, or continue? \n\n\n", buttons) == 0) {
- game.quitProgNow = true;
+ g_agi->quitGame();
}
}
}
@@ -1231,7 +1231,7 @@ cmd(restart_game) {
g_agi->selectionBox(" Restart game, or continue? \n\n\n", buttons);
if (sel == 0) {
- game.quitProgNow = 0xff;
+ g_agi->quitGame();
g_agi->setflag(fRestartGame, true);
g_agi->_menu->enableAll();
}
@@ -1739,7 +1739,7 @@ int AgiEngine::runLogic(int n) {
curLogic->cIP = curLogic->sIP;
timerHack = 0;
- while (ip < _game.logics[n].size && !_game.quitProgNow) {
+ while (ip < _game.logics[n].size && !quit()) {
if (_debug.enabled) {
if (_debug.steps > 0) {
if (_debug.logic0 || n) {
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index 7ba3e625bf..393057ed9c 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -24,7 +24,6 @@
*/
-
#include "agi/agi.h"
#include "agi/keyboard.h"
#include "agi/opcodes.h"
@@ -232,7 +231,7 @@ int AgiEngine::testIfCode(int lognum) {
uint8 p[16] = { 0 };
bool end_test = false;
- while (retval && !game.quitProgNow && !end_test) {
+ while (retval && !quit() && !end_test) {
if (_debug.enabled && (_debug.logic0 || lognum))
debugConsole(lognum, lTEST_MODE, NULL);
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index f2301e012a..666d1b1b11 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -23,7 +23,6 @@
*
*/
-#include "common/events.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
diff --git a/engines/agi/preagi.h b/engines/agi/preagi.h
index 500f98546b..d95035a073 100644
--- a/engines/agi/preagi.h
+++ b/engines/agi/preagi.h
@@ -73,7 +73,7 @@ public:
// Keyboard
int getSelection(SelectionTypes type);
- int rnd(int hi) { return (_rnd->getRandomNumber(hi) + 1); }
+ int rnd(int hi) { return (_rnd->getRandomNumber(hi - 1) + 1); }
// Text
void drawStr(int row, int col, int attr, const char *buffer);
diff --git a/engines/agi/preagi_common.cpp b/engines/agi/preagi_common.cpp
index 5d99dfa7f9..3cd04351f7 100644
--- a/engines/agi/preagi_common.cpp
+++ b/engines/agi/preagi_common.cpp
@@ -23,8 +23,6 @@
*
*/
-#include "common/events.h"
-
#include "agi/preagi.h"
#include "agi/font.h"
#include "agi/graphics.h"
@@ -122,11 +120,12 @@ void PreAgiEngine::printStrXOR(char *szMsg) {
int PreAgiEngine::getSelection(SelectionTypes type) {
Common::Event event;
- for (;;) {
+ while (!quit()) {
while (_eventMan->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _system->quit();
+ return 0;
case Common::EVENT_RBUTTONUP:
return 0;
case Common::EVENT_LBUTTONUP:
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index 08f8969ca3..f643ab9cfc 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -23,7 +23,6 @@
*
*/
-#include "common/events.h"
#include "common/savefile.h"
#include "common/stream.h"
@@ -343,11 +342,12 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
drawMenu(menu, *sel0, *sel1);
- for (;;) {
+ for(;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- exit(0);
+ return 0;
case Common::EVENT_MOUSEMOVE:
if (iRow < 2) {
x = event.mouse.x / 8;
@@ -640,8 +640,8 @@ void Mickey::playSound(ENUM_MSA_SOUND iSound) {
if (iSound == IDI_MSA_SND_THEME) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->_system->quit();
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
case Common::EVENT_KEYDOWN:
@@ -932,10 +932,17 @@ bool Mickey::loadGame() {
if (_vm->getSelection(kSelAnyKey) == 0)
return false;
} else {
- if (infile->readUint32BE() != MKID_BE('MICK'))
- error("Mickey::loadGame wrong save game format");
+ if (infile->readUint32BE() != MKID_BE('MICK')) {
+ warning("Mickey::loadGame wrong save game format");
+ return false;
+ }
saveVersion = infile->readByte();
+ if (saveVersion < 2) {
+ warning("The planet data in this save game is corrupted. Load aborted");
+ return false;
+ }
+
if (saveVersion != MSA_SAVEGAME_VERSION)
warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, MSA_SAVEGAME_VERSION);
@@ -953,7 +960,7 @@ bool Mickey::loadGame() {
_game.iPlanetXtal[i] = infile->readByte();
for(i = 0; i < IDI_MSA_MAX_PLANET; i++)
- _game.iClue[i] = infile->readByte();
+ _game.iClue[i] = infile->readUint16LE();
infile->read(_game.szAddr, IDI_MSA_MAX_BUTTON + 1);
@@ -1058,7 +1065,7 @@ void Mickey::saveGame() {
outfile->writeByte(_game.iPlanetXtal[i]);
for(i = 0; i < IDI_MSA_MAX_PLANET; i++)
- outfile->writeByte(_game.iClue[i]);
+ outfile->writeUint16LE(_game.iClue[i]);
outfile->write(_game.szAddr, IDI_MSA_MAX_BUTTON + 1);
@@ -1214,7 +1221,7 @@ void Mickey::gameOver() {
}
waitAnyKey();
- exit(0);
+ _vm->quitGame();
}
void Mickey::flipSwitch() {
@@ -2053,8 +2060,8 @@ void Mickey::waitAnyKey(bool anim) {
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->_system->quit();
case Common::EVENT_KEYDOWN:
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
@@ -2153,7 +2160,7 @@ void Mickey::run() {
intro();
// Game loop
- for (;;) {
+ while (!_vm->quit()) {
drawRoom();
if (_game.fIntro) {
diff --git a/engines/agi/preagi_mickey.h b/engines/agi/preagi_mickey.h
index 8d982dc401..f29d2fbccd 100644
--- a/engines/agi/preagi_mickey.h
+++ b/engines/agi/preagi_mickey.h
@@ -30,7 +30,7 @@
namespace Agi {
-#define MSA_SAVEGAME_VERSION 1
+#define MSA_SAVEGAME_VERSION 2
// strings
#define IDS_MSA_PATH_DAT "dat/%s"
@@ -637,7 +637,7 @@ const int IDO_MSA_NEXT_PIECE[IDI_MSA_MAX_PLANET][5] = {
{0x5B78, 0x5BB6, 0x5C29, 0x5C76, 0x5CE1}, // pluto
{0x526B, 0x52DA, 0x5340, 0x53A1, 0x540C}, // jupiter
{0x50F6, 0x512C, 0x5170, 0x51D5, 0x5228}, // mars
- {0x56AA, 0x571C, 0x579E, 0x5807, 0x5875} // uranus
+ {0x56AA, 0x571C, 0x579E, 0x5807, 0x5875} // uranus
};
// message offsets
@@ -697,7 +697,7 @@ struct MSA_GAME {
uint8 nXtals;
uint8 iPlanetXtal[IDI_MSA_MAX_DAT];
- uint8 iClue[IDI_MSA_MAX_PLANET];
+ uint16 iClue[IDI_MSA_MAX_PLANET];
char szAddr[IDI_MSA_MAX_BUTTON + 1];
// Flags
diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp
index 7502c63c6c..beff721fda 100644
--- a/engines/agi/preagi_troll.cpp
+++ b/engines/agi/preagi_troll.cpp
@@ -30,8 +30,6 @@
#include "graphics/cursorman.h"
-#include "common/events.h"
-
namespace Agi {
Troll::Troll(PreAgiEngine* vm) : _vm(vm) {
@@ -58,11 +56,12 @@ bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {
drawMenu(szMenu, *iSel);
- for (;;) {
+ while (!_vm->quit()) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->_system->quit();
+ return 0;
case Common::EVENT_MOUSEMOVE:
y = event.mouse.y / 8;
@@ -205,8 +204,8 @@ void Troll::waitAnyKeyIntro() {
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->_system->quit();
case Common::EVENT_LBUTTONUP:
case Common::EVENT_KEYDOWN:
return;
@@ -269,7 +268,7 @@ void Troll::tutorial() {
int iSel = 0;
//char szTreasure[16] = {0};
- for (;;) {
+ while (!_vm->quit()) {
_vm->clearScreen(0xFF);
_vm->printStr(IDS_TRO_TUTORIAL_0);
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index 87d13bff3d..de8839b7bc 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -29,7 +29,6 @@
#include "graphics/cursorman.h"
-#include "common/events.h"
#include "common/savefile.h"
#include "common/stream.h"
@@ -797,12 +796,12 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
// Show the mouse cursor for the menu
CursorMan.showMouse(true);
- for (;;) {
+ while (!_vm->quit()) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->_system->quit();
- break;
+ return;
case Common::EVENT_MOUSEMOVE:
x = event.mouse.x / 8;
y = event.mouse.y / 8;
@@ -1014,7 +1013,7 @@ phase2:
if (parser(hdr.ofsDesc[iBlock] - _roomOffset, iBlock, roomdata) == IDI_WTP_PAR_BACK)
goto phase1;
}
- for (;;) {
+ while (!_vm->quit()) {
for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) {
switch(parser(hdr.ofsBlock[iBlock] - _roomOffset, iBlock, roomdata)) {
case IDI_WTP_PAR_GOTO:
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index db7bba13e4..0b308bb37b 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -91,7 +91,7 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
out->writeSint16BE((int16)_game.lognum);
out->writeSint16BE((int16)_game.playerControl);
- out->writeSint16BE((int16)_game.quitProgNow);
+ out->writeSint16BE((int16)quit());
out->writeSint16BE((int16)_game.statusLine);
out->writeSint16BE((int16)_game.clockEnabled);
out->writeSint16BE((int16)_game.exitAllLogics);
@@ -214,6 +214,9 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
delete out;
debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Closed %s", fileName);
+
+ _lastSaveTime = _system->getMillis();
+
return result;
}
@@ -281,7 +284,8 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
_game.lognum = in->readSint16BE();
_game.playerControl = in->readSint16BE();
- _game.quitProgNow = in->readSint16BE();
+ if (in->readSint16BE())
+ quitGame();
_game.statusLine = in->readSint16BE();
_game.clockEnabled = in->readSint16BE();
_game.exitAllLogics = in->readSint16BE();
@@ -698,13 +702,18 @@ int AgiEngine::saveGameDialog() {
sprintf(fileName, "%s", getSavegameFilename(slot));
- drawWindow(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);
- printText("Select a slot in which you wish to\nsave the game:",
- 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR);
- slot = selectSlot();
- if (slot < 0)
- return errOK;
+ do {
+ drawWindow(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);
+ printText("Select a slot in which you wish to\nsave the game:",
+ 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ slot = selectSlot();
+ if (slot == 0)
+ messageBox("That slot is for Autosave only.");
+ else if (slot < 0)
+ return errOK;
+ }
+ while (slot == 0);
drawWindow(hp, vp + 5 * CHAR_LINES, GFX_WIDTH - hp,
GFX_HEIGHT - vp - 9 * CHAR_LINES);
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index 9fe8fbf41a..3b28e75c56 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -1013,7 +1013,7 @@ bool IIgsSoundMgr::loadInstrumentHeaders(const Common::String &exePath, const II
// Open the executable file and check that it has correct size
file.open(exePath);
- if (file.size() != exeInfo.exeSize) {
+ if (file.size() != (int32)exeInfo.exeSize) {
debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)",
exePath.c_str(), file.size(), exeInfo.exeSize);
}
@@ -1023,7 +1023,7 @@ bool IIgsSoundMgr::loadInstrumentHeaders(const Common::String &exePath, const II
file.close();
// Check that we got enough data to be able to parse the instruments
- if (data && data->size() >= (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();
@@ -1107,14 +1107,14 @@ bool IIgsSoundMgr::loadWaveFile(const Common::String &wavePath, const IIgsExeInf
}
/**
- * A function object (i.e. a functor) for testing if a FilesystemNode
+ * A function object (i.e. a functor) for testing if a Common::FilesystemNode
* object's name is equal (Ignoring case) to a string or to at least
* one of the strings in a list of strings. Can be used e.g. with find_if().
*/
-struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction<const FilesystemNode&, bool> {
+struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction<const Common::FilesystemNode&, bool> {
fsnodeNameEqualsIgnoreCase(const Common::StringList &str) : _str(str) {}
fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); }
- bool operator()(const FilesystemNode &param) const {
+ bool operator()(const Common::FilesystemNode &param) const {
for (Common::StringList::const_iterator iter = _str.begin(); iter != _str.end(); iter++)
if (param.getName().equalsIgnoreCase(*iter))
return true;
@@ -1139,9 +1139,9 @@ bool SoundMgr::loadInstruments() {
}
// List files in the game path
- FSList fslist;
- FilesystemNode dir(ConfMan.get("path"));
- if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ Common::FSList fslist;
+ Common::FilesystemNode dir(ConfMan.get("path"));
+ if (!dir.getChildren(fslist, Common::FilesystemNode::kListFilesOnly)) {
warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str());
return false;
}
@@ -1157,7 +1157,7 @@ bool SoundMgr::loadInstruments() {
waveNames.push_back("SIERRAST");
// Search for the executable file and the wave file (i.e. check if any of the filenames match)
- FSList::const_iterator exeFsnode, waveFsnode;
+ Common::FSList::const_iterator exeFsnode, waveFsnode;
exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames));
waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames));
diff --git a/engines/agi/wagparser.h b/engines/agi/wagparser.h
index 2f4003315f..827720ac85 100644
--- a/engines/agi/wagparser.h
+++ b/engines/agi/wagparser.h
@@ -201,7 +201,9 @@ protected:
class WagFileParser {
// Constants, type definitions, enumerations etc.
public:
- static const uint WINAGI_VERSION_LENGTH = 16; ///< WinAGI's version string's length (Always 16)
+ enum {
+ WINAGI_VERSION_LENGTH = 16 ///< WinAGI's version string's length (Always 16)
+ };
typedef Common::Array<WagProperty> PropertyList; ///< A type definition for an array of *.wag file properties
public:
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index a9fd204d73..97d84e036c 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -97,8 +97,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_vc_get_out_of_code = 0;
_gameOffsetsPtr = 0;
- _quit = false;
-
_debugger = 0;
_gameFile = 0;
@@ -508,24 +506,24 @@ AGOSEngine::AGOSEngine(OSystem *syst)
// Add default file directories for Acorn version of
// Simon the Sorcerer 1
- File::addDefaultDirectory(_gameDataPath + "execute");
- File::addDefaultDirectory(_gameDataPath + "EXECUTE");
+ File::addDefaultDirectory(_gameDataDir.getChild("execute"));
+ File::addDefaultDirectory(_gameDataDir.getChild("EXECUTE"));
// Add default file directories for Amiga/Macintosh
// verisons of Simon the Sorcerer 2
- File::addDefaultDirectory(_gameDataPath + "voices");
- File::addDefaultDirectory(_gameDataPath + "VOICES");
+ File::addDefaultDirectory(_gameDataDir.getChild("voices"));
+ File::addDefaultDirectory(_gameDataDir.getChild("VOICES"));
// Add default file directories for Amiga & Macintosh
// versions of The Feeble Files
- File::addDefaultDirectory(_gameDataPath + "gfx");
- File::addDefaultDirectory(_gameDataPath + "GFX");
- File::addDefaultDirectory(_gameDataPath + "movies");
- File::addDefaultDirectory(_gameDataPath + "MOVIES");
- File::addDefaultDirectory(_gameDataPath + "sfx");
- File::addDefaultDirectory(_gameDataPath + "SFX");
- File::addDefaultDirectory(_gameDataPath + "speech");
- File::addDefaultDirectory(_gameDataPath + "SPEECH");
+ File::addDefaultDirectory(_gameDataDir.getChild("gfx"));
+ File::addDefaultDirectory(_gameDataDir.getChild("GFX"));
+ File::addDefaultDirectory(_gameDataDir.getChild("movies"));
+ File::addDefaultDirectory(_gameDataDir.getChild("MOVIES"));
+ File::addDefaultDirectory(_gameDataDir.getChild("sfx"));
+ File::addDefaultDirectory(_gameDataDir.getChild("SFX"));
+ File::addDefaultDirectory(_gameDataDir.getChild("speech"));
+ File::addDefaultDirectory(_gameDataDir.getChild("SPEECH"));
syst->getEventManager()->registerRandomSource(_rnd, "agos");
}
@@ -550,6 +548,7 @@ int AGOSEngine::init() {
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
if ((getGameType() == GType_SIMON2 && getPlatform() == Common::kPlatformWindows) ||
(getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformWindows) ||
@@ -574,7 +573,7 @@ int AGOSEngine::init() {
if (ret)
warning("MIDI Player init failed: \"%s\"", _midi.getErrorName (ret));
- _midi.setVolume(ConfMan.getInt("music_volume"));
+ _midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
_midiEnabled = true;
@@ -952,7 +951,7 @@ void AGOSEngine::pauseEngineIntern(bool pauseIt) {
void AGOSEngine::pause() {
pauseEngine(true);
- while (_pause && !_quit) {
+ while (_pause && !quit()) {
delay(1);
if (_keyPressed.keycode == Common::KEYCODE_p)
pauseEngine(false);
@@ -989,7 +988,7 @@ int AGOSEngine::go() {
(getFeatures() & GF_DEMO)) {
int i;
- while (!_quit) {
+ while (!quit()) {
for (i = 0; i < 4; i++) {
setWindowImage(3, 9902 + i);
debug(0, "Displaying image %d", 9902 + i);
@@ -1018,7 +1017,7 @@ int AGOSEngine::go() {
runSubroutine101();
permitInput();
- while (!_quit) {
+ while (!quit()) {
waitForInput();
handleVerbClicked(_verbHitArea);
delay(100);
@@ -1084,4 +1083,12 @@ uint32 AGOSEngine::getTime() const {
return (uint32)time(NULL);
}
+
+void AGOSEngine::syncSoundSettings() {
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
+ _midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
+}
+
} // End of namespace AGOS
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 8ad5487b35..49b4478ec7 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -269,7 +269,6 @@ protected:
uint16 _marks;
- bool _quit;
bool _scriptVar2;
bool _runScriptReturn1;
bool _runScriptCondition[40];
@@ -589,6 +588,8 @@ protected:
void loadSoundFile(const char *filename);
+ virtual void syncSoundSettings();
+
int getUserFlag(Item *item, int a);
int getUserFlag1(Item *item, int a);
int getUserItem(Item *item, int n);
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 3e1b9b0611..f4abf19645 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -26,7 +26,6 @@
#include "common/endian.h"
-#include "common/events.h"
#include "common/system.h"
#include "graphics/cursorman.h"
@@ -151,7 +150,7 @@ void MoviePlayer::play() {
startSound();
- while (_frameNum < _framesCount && !_vm->_quit)
+ while (_frameNum < _framesCount && !_vm->quit())
handleNextFrame();
closeFile();
@@ -279,9 +278,6 @@ void MoviePlayer::handleNextFrame() {
case Common::EVENT_RBUTTONUP:
_rightButtonDown = false;
break;
- case Common::EVENT_QUIT:
- _vm->_quit = true;
- break;
default:
break;
}
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 26d8916ab7..12f281d0dc 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -27,6 +27,7 @@
#include "common/advancedDetector.h"
#include "common/config-manager.h"
+#include "common/savefile.h"
#include "agos/agos.h"
@@ -100,7 +101,7 @@ static const Common::ADParams detectionParams = {
class AgosMetaEngine : public Common::AdvancedMetaEngine {
public:
AgosMetaEngine() : Common::AdvancedMetaEngine(detectionParams) {}
-
+
virtual const char *getName() const {
return "AGOS";
}
@@ -108,10 +109,18 @@ public:
virtual const char *getCopyright() const {
return "AGOS (C) Adventure Soft";
}
-
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
};
+bool AgosMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves);
+}
+
bool AgosMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const AGOS::AGOSGameDescription *gd = (const AGOS::AGOSGameDescription *)desc;
bool res = true;
@@ -149,6 +158,34 @@ bool AgosMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return res;
}
+SaveStateList AgosMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ Common::String saveDesc;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ saveDesc = file->c_str();
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(AGOS)
REGISTER_PLUGIN_DYNAMIC(AGOS, PLUGIN_TYPE_ENGINE, AgosMetaEngine);
#else
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index 010b331cf8..4db3545594 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -142,7 +142,7 @@ bool AGOSEngine::kickoffTimeEvents() {
cur_time = getTime() - _gameStoppedClock;
- while ((te = _firstTimeStruct) != NULL && te->time <= cur_time && !_quit) {
+ while ((te = _firstTimeStruct) != NULL && te->time <= cur_time && !quit()) {
result = true;
_pendingDeleteTimeEvent = te;
invokeTimeEvent(te);
@@ -520,8 +520,8 @@ void AGOSEngine::delay(uint amount) {
setBitFlag(92, false);
_rightButtonDown++;
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _quit = true;
return;
default:
break;
@@ -544,7 +544,7 @@ void AGOSEngine::delay(uint amount) {
_system->delayMillis(this_delay);
cur = _system->getMillis();
- } while (cur < start + amount && !_quit);
+ } while (cur < start + amount && !quit());
}
void AGOSEngine::timer_callback() {
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 9a3962ea21..25a4b919f4 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -1286,7 +1286,7 @@ void AGOSEngine::setWindowImageEx(uint16 mode, uint16 vga_res) {
if (getGameType() == GType_WW && (mode == 6 || mode == 8 || mode == 9)) {
setWindowImage(mode, vga_res);
} else {
- while (_copyScnFlag && !_quit)
+ while (_copyScnFlag && !quit())
delay(1);
setWindowImage(mode, vga_res);
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index 6f4cd09947..4327c2878d 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -123,7 +123,7 @@ void AGOSEngine::setup_cond_c_helper() {
clearName();
_lastNameOn = last;
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = 0;
_leftButtonDown = 0;
@@ -145,7 +145,7 @@ void AGOSEngine::setup_cond_c_helper() {
}
delay(100);
- } while ((_lastHitArea3 == (HitArea *) -1 || _lastHitArea3 == 0) && !_quit);
+ } while ((_lastHitArea3 == (HitArea *) -1 || _lastHitArea3 == 0) && !quit());
if (_lastHitArea == NULL) {
} else if (_lastHitArea->id == 0x7FFB) {
@@ -189,12 +189,12 @@ void AGOSEngine::waitForInput() {
resetVerbs();
}
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
_dragAccept = 1;
- while (!_quit) {
+ while (!quit()) {
if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
_keyPressed.keycode == Common::KEYCODE_F10)
displayBoxStars();
@@ -563,16 +563,18 @@ bool AGOSEngine::processSpecialKeys() {
case Common::KEYCODE_PLUS:
case Common::KEYCODE_KP_PLUS:
if (_midiEnabled) {
- _midi.setVolume(_midi.getVolume() + 16);
+ _midi.setVolume(_midi.getMusicVolume() + 16, _midi.getSFXVolume() + 16);
}
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16);
+ ConfMan.setInt("music_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16);
+ syncSoundSettings();
break;
case Common::KEYCODE_MINUS:
case Common::KEYCODE_KP_MINUS:
if (_midiEnabled) {
- _midi.setVolume(_midi.getVolume() - 16);
+ _midi.setVolume(_midi.getMusicVolume() - 16, _midi.getSFXVolume() - 16);
}
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16);
+ ConfMan.setInt("music_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16);
+ syncSoundSettings();
break;
case Common::KEYCODE_m:
_musicPaused ^= 1;
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 891e9bde95..fd0e4eaa9d 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -49,7 +49,9 @@ MidiPlayer::MidiPlayer() {
_enable_sfx = true;
_current = 0;
- _masterVolume = 255;
+ _musicVolume = 255;
+ _sfxVolume = 255;
+
resetVolumeTable();
_paused = false;
@@ -104,10 +106,13 @@ void MidiPlayer::send(uint32 b) {
byte channel = (byte)(b & 0x0F);
if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume.
+ // Adjust volume changes by master music and master sfx volume.
byte volume = (byte)((b >> 16) & 0x7F);
_current->volume[channel] = volume;
- volume = volume * _masterVolume / 255;
+ if (_current == &_sfx)
+ volume = volume * _sfxVolume / 255;
+ else if (_current == &_music)
+ volume = volume * _musicVolume / 255;
b = (b & 0xFF00FFFF) | (volume << 16);
} else if ((b & 0xF0) == 0xC0 && _map_mt32_to_gm) {
b = (b & 0xFFFF00FF) | (MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8);
@@ -133,8 +138,12 @@ void MidiPlayer::send(uint32 b) {
if (!_current->channel[channel])
_current->channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
if (_current->channel[channel]) {
- if (channel == 9)
- _current->channel[9]->volume(_current->volume[9] * _masterVolume / 255);
+ if (channel == 9) {
+ if (_current == &_sfx)
+ _current->channel[9]->volume(_current->volume[9] * _sfxVolume / 255);
+ else if (_current == &_music)
+ _current->channel[9]->volume(_current->volume[9] * _musicVolume / 255);
+ }
_current->channel[channel]->send(b);
if ((b & 0xFFF0) == 0x79B0) {
// We have received a "Reset All Controllers" message
@@ -143,7 +152,10 @@ void MidiPlayer::send(uint32 b) {
// consistent behaviour, explicitly set the volume to
// what we think it should be.
- _current->channel[channel]->volume(_current->volume[channel] * _masterVolume / 255);
+ if (_current == &_sfx)
+ _current->channel[channel]->volume(_current->volume[channel] * _sfxVolume / 255);
+ else if (_current == &_music)
+ _current->channel[channel]->volume(_current->volume[channel] * _musicVolume / 255);
}
}
}
@@ -255,30 +267,36 @@ void MidiPlayer::pause(bool b) {
Common::StackLock lock(_mutex);
for (int i = 0; i < 16; ++i) {
if (_music.channel[i])
- _music.channel[i]->volume(_paused ? 0 : (_music.volume[i] * _masterVolume / 255));
+ _music.channel[i]->volume(_paused ? 0 : (_music.volume[i] * _musicVolume / 255));
if (_sfx.channel[i])
- _sfx.channel[i]->volume(_paused ? 0 : (_sfx.volume[i] * _masterVolume / 255));
+ _sfx.channel[i]->volume(_paused ? 0 : (_sfx.volume[i] * _sfxVolume / 255));
}
}
-void MidiPlayer::setVolume(int volume) {
- if (volume < 0)
- volume = 0;
- else if (volume > 255)
- volume = 255;
-
- if (_masterVolume == volume)
+void MidiPlayer::setVolume(int musicVol, int sfxVol) {
+ if (musicVol < 0)
+ musicVol = 0;
+ else if (musicVol > 255)
+ musicVol = 255;
+ if (sfxVol < 0)
+ sfxVol = 0;
+ else if (sfxVol > 255)
+ sfxVol = 255;
+
+ if (_musicVolume == musicVol && _sfxVolume == sfxVol)
return;
- _masterVolume = volume;
+
+ _musicVolume = musicVol;
+ _sfxVolume = sfxVol;
// Now tell all the channels this.
Common::StackLock lock(_mutex);
if (_driver && !_paused) {
for (int i = 0; i < 16; ++i) {
if (_music.channel[i])
- _music.channel[i]->volume(_music.volume[i] * _masterVolume / 255);
+ _music.channel[i]->volume(_music.volume[i] * _musicVolume / 255);
if (_sfx.channel[i])
- _sfx.channel[i]->volume(_sfx.volume[i] * _masterVolume / 255);
+ _sfx.channel[i]->volume(_sfx.volume[i] * _sfxVolume / 255);
}
}
}
@@ -354,7 +372,7 @@ void MidiPlayer::resetVolumeTable() {
for (i = 0; i < 16; ++i) {
_music.volume[i] = _sfx.volume[i] = 127;
if (_driver)
- _driver->send(((_masterVolume >> 1) << 16) | 0x7B0 | i);
+ _driver->send(((_musicVolume >> 1) << 16) | 0x7B0 | i);
}
}
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index 2994c49bb6..c004230e5b 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -68,6 +68,8 @@ protected:
// These are maintained for both music and SFX
byte _masterVolume; // 0-255
+ byte _musicVolume;
+ byte _sfxVolume;
bool _paused;
// These are only used for music.
@@ -103,8 +105,9 @@ public:
void stop();
void pause(bool b);
- int getVolume() { return _masterVolume; }
- void setVolume(int volume);
+ int getMusicVolume() { return _musicVolume; }
+ int getSFXVolume() { return _sfxVolume; }
+ void setVolume(int musicVol, int sfxVol);
void setDriver(MidiDriver *md);
public:
diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp
index 2d2feb7b9e..c174362e7c 100644
--- a/engines/agos/oracle.cpp
+++ b/engines/agos/oracle.cpp
@@ -459,7 +459,7 @@ void AGOSEngine_Feeble::saveUserGame(int slot) {
}
windowPutChar(window, 0x7f);
- while (!_quit) {
+ while (!quit()) {
_keyPressed.reset();
delay(1);
diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp
index 4aca390f3b..cd0d8e7ef6 100644
--- a/engines/agos/res.cpp
+++ b/engines/agos/res.cpp
@@ -74,8 +74,7 @@ void AGOSEngine::decompressData(const char *srcName, byte *dst, uint32 offset, u
error("decompressData: Read failed");
unsigned long decompressedSize = dstSize;
- int result = Common::uncompress(dst, &decompressedSize, srcBuffer, srcSize);
- if (result != Common::ZLIB_OK)
+ if (!Common::uncompress(dst, &decompressedSize, srcBuffer, srcSize))
error("decompressData: Zlib uncompress error");
free(srcBuffer);
} else {
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index 9779630d47..c1a4e91c95 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -244,7 +244,7 @@ int16 AGOSEngine::matchSaveGame(const char *name, uint16 max) {
void AGOSEngine::userGame(bool load) {
WindowBlock *window = _windowArray[4];
const char *message1;
- int i, numSaveGames;
+ int i = 0, numSaveGames;
char *name;
char buf[8];
@@ -279,11 +279,11 @@ restart:
name = buf;
_saveGameNameLen = 0;
- while (!_quit) {
+ while (!quit()) {
windowPutChar(window, 128);
_keyPressed.reset();
- while (!_quit) {
+ while (!quit()) {
delay(10);
if (_keyPressed.ascii && _keyPressed.ascii < 128) {
i = _keyPressed.ascii;
@@ -443,7 +443,7 @@ void AGOSEngine_Elvira2::userGame(bool load) {
name = buf + 192;
- while (!_quit) {
+ while (!quit()) {
windowPutChar(window, 128);
_saveLoadEdit = true;
@@ -516,7 +516,7 @@ int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) {
_keyPressed.reset();
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
@@ -526,7 +526,7 @@ int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) {
return _keyPressed.ascii;
}
delay(10);
- } while (_lastHitArea3 == 0 && !_quit);
+ } while (_lastHitArea3 == 0 && !quit());
ha = _lastHitArea;
if (ha == NULL || ha->id < 200) {
@@ -708,7 +708,7 @@ restart:;
_saveGameNameLen++;
}
- while (!_quit) {
+ while (!quit()) {
windowPutChar(window, 127);
_saveLoadEdit = true;
@@ -787,7 +787,7 @@ int AGOSEngine_Simon1::userGameGetKey(bool *b, char *buf, uint maxChar) {
_keyPressed.reset();
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
@@ -797,7 +797,7 @@ int AGOSEngine_Simon1::userGameGetKey(bool *b, char *buf, uint maxChar) {
return _keyPressed.ascii;
}
delay(10);
- } while (_lastHitArea3 == 0 && !_quit);
+ } while (_lastHitArea3 == 0 && !quit());
ha = _lastHitArea;
if (ha == NULL || ha->id < 205) {
@@ -1056,7 +1056,7 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
writeVariable(i, f->readUint16BE());
}
- if (f->ioFailed()) {
+ if (f->err()) {
error("load failed");
}
@@ -1140,7 +1140,7 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) {
}
f->finalize();
- bool result = !f->ioFailed();
+ bool result = !f->err();
delete f;
_lockWord &= ~0x100;
@@ -1331,7 +1331,7 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
_superRoomNumber = f->readUint16BE();
}
- if (f->ioFailed()) {
+ if (f->err()) {
error("load failed");
}
@@ -1503,7 +1503,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
}
f->finalize();
- bool result = !f->ioFailed();
+ bool result = !f->err();
delete f;
_lockWord &= ~0x100;
diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp
index fa132ec26f..39c172be62 100644
--- a/engines/agos/script.cpp
+++ b/engines/agos/script.cpp
@@ -410,7 +410,7 @@ void AGOSEngine::o_msg() {
void AGOSEngine::o_end() {
// 68: exit interpreter
- _quit = true;
+ quitGame();
}
void AGOSEngine::o_done() {
@@ -965,7 +965,7 @@ void AGOSEngine::writeVariable(uint16 variable, uint16 contents) {
int AGOSEngine::runScript() {
bool flag;
- if (_quit)
+ if (quit())
return 1;
do {
@@ -1010,9 +1010,9 @@ int AGOSEngine::runScript() {
error("Invalid opcode '%d' encountered", _opcode);
executeOpcode(_opcode);
- } while (getScriptCondition() != flag && !getScriptReturn() && !_quit);
+ } while (getScriptCondition() != flag && !getScriptReturn() && !quit());
- return (_quit) ? 1 : getScriptReturn();
+ return (quit()) ? 1 : getScriptReturn();
}
Child *nextSub(Child *sub, int16 key) {
@@ -1066,7 +1066,7 @@ void AGOSEngine::waitForSync(uint a) {
_exitCutscene = false;
_rightButtonDown = false;
- while (_vgaWaitFor != 0 && !_quit) {
+ while (_vgaWaitFor != 0 && !quit()) {
if (_rightButtonDown) {
if (_vgaWaitFor == 200 && (getGameType() == GType_FF || !getBitFlag(14))) {
skipSpeech();
diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp
index 9b572e347b..8705755df6 100644
--- a/engines/agos/script_e1.cpp
+++ b/engines/agos/script_e1.cpp
@@ -24,7 +24,6 @@
*/
-
#include "agos/agos.h"
#include "agos/vga.h"
@@ -565,7 +564,7 @@ void AGOSEngine_Elvira1::oe1_look() {
lobjFunc(l, "You can see "); /* Show objects */
}
if (r && (r->flags & 4) && levelOf(i) < 10000) {
- _quit = true;
+ quitGame();
}
}
@@ -944,7 +943,7 @@ restart:
windowPutChar(window, *message2);
if (confirmYesOrNo(120, 62) == 0x7FFF) {
- _quit = true;
+ quitGame();
} else {
goto restart;
}
@@ -1053,11 +1052,11 @@ uint AGOSEngine::confirmYesOrNo(uint16 x, uint16 y) {
ha->priority = 999;
ha->window = 0;
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
- while (!_quit) {
+ while (!quit()) {
if (_lastHitArea3 != 0)
break;
delay(1);
@@ -1102,11 +1101,11 @@ uint AGOSEngine::continueOrQuit() {
ha->priority = 999;
ha->window = 0;
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
- while (!_quit) {
+ while (!quit()) {
if (_lastHitArea3 != 0)
break;
delay(1);
diff --git a/engines/agos/script_e2.cpp b/engines/agos/script_e2.cpp
index 6f6db8efb4..05e457579d 100644
--- a/engines/agos/script_e2.cpp
+++ b/engines/agos/script_e2.cpp
@@ -370,11 +370,11 @@ void AGOSEngine_Elvira2::oe2_pauseGame() {
uint32 pauseTime = getTime();
haltAnimation();
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
- while (!_quit) {
+ while (!quit()) {
if (processSpecialKeys() != 0 || _lastHitArea3 != 0)
break;
delay(1);
diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp
index 6183a3fb20..d07f682937 100644
--- a/engines/agos/script_s1.cpp
+++ b/engines/agos/script_s1.cpp
@@ -24,7 +24,6 @@
*/
-
#include "common/system.h"
#include "agos/agos.h"
@@ -339,10 +338,10 @@ void AGOSEngine_Simon1::os1_pauseGame() {
break;
}
- while (!_quit) {
+ while (!quit()) {
delay(1);
if (_keyPressed.keycode == keyYes)
- _quit = true;
+ quitGame();
else if (_keyPressed.keycode == keyNo)
break;
}
diff --git a/engines/agos/script_ww.cpp b/engines/agos/script_ww.cpp
index 8dc915f6e8..f0da324fbd 100644
--- a/engines/agos/script_ww.cpp
+++ b/engines/agos/script_ww.cpp
@@ -368,11 +368,11 @@ void AGOSEngine_Waxworks::oww_pauseGame() {
uint32 pauseTime = getTime();
haltAnimation();
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
- while (!_quit) {
+ while (!quit()) {
if (_lastHitArea3 != 0)
break;
delay(1);
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index c456c92e60..4d60bbdbed 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -56,10 +56,12 @@ protected:
public:
BaseSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigEndian = false);
BaseSound(Audio::Mixer *mixer, File *file, uint32 *offsets, bool bigEndian = false);
+ virtual ~BaseSound();
+ void close();
+
void playSound(uint sound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0) {
playSound(sound, sound, type, handle, flags, vol);
}
- virtual ~BaseSound();
virtual void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0) = 0;
virtual Audio::AudioStream *makeAudioStream(uint sound) { return NULL; }
};
@@ -184,6 +186,12 @@ BaseSound::BaseSound(Audio::Mixer *mixer, File *file, uint32 *offsets, bool bigE
_freeOffsets = false;
}
+void BaseSound::close() {
+ if (_freeOffsets) {
+ free(_offsets);
+ }
+}
+
BaseSound::~BaseSound() {
if (_freeOffsets)
free(_offsets);
@@ -555,6 +563,9 @@ void Sound::readSfxFile(const char *filename) {
void Sound::loadSfxTable(File *gameFile, uint32 base) {
stopAll();
+
+ if (_effects)
+ _effects->close();
if (_vm->getPlatform() == Common::kPlatformWindows)
_effects = new WavSound(_mixer, gameFile, base);
diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp
index cb71ed7efa..488ebf4edf 100644
--- a/engines/agos/subroutine.cpp
+++ b/engines/agos/subroutine.cpp
@@ -555,7 +555,7 @@ int AGOSEngine::startSubroutine(Subroutine *sub) {
_currentTable = sub;
restart:
- if (_quit)
+ if (quit())
return result;
while ((byte *)sl != (byte *)sub) {
diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp
index c8f6d40f1f..9fd128d764 100644
--- a/engines/agos/verb.cpp
+++ b/engines/agos/verb.cpp
@@ -343,7 +343,7 @@ void AGOSEngine::handleVerbClicked(uint verb) {
Subroutine *sub;
int result;
- if (_quit)
+ if (quit())
return;
_objectItem = _hitAreaObjectItem;
diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp
index e1f986b92e..87db49e46b 100644
--- a/engines/agos/window.cpp
+++ b/engines/agos/window.cpp
@@ -298,11 +298,11 @@ void AGOSEngine::waitWindow(WindowBlock *window) {
ha->id = 0x7FFF;
ha->priority = 999;
- while (!_quit) {
+ while (!quit()) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
- for (;;) {
+ while (!quit()) {
if (_lastHitArea3 != 0)
break;
delay(1);
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index a670328c12..f5cde579e6 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -53,7 +53,6 @@ Common::Array<AnimData> animDataTable;
static const AnimDataEntry transparencyData[] = {
{"ALPHA", 0xF},
- {"TITRE", 0xF},
{"TITRE2", 0xF},
{"ET", 0xC},
{"L311", 0x3},
@@ -586,6 +585,14 @@ int loadAni(const char *resourceName, int16 idx) {
transparentColor = getAnimTransparentColor(resourceName);
+ // TODO: Merge this special case hack into getAnimTransparentColor somehow.
+ // HACK: Versions of TITRE.ANI with height 37 use color 0xF for transparency.
+ // Versions of TITRE.ANI with height 57 use color 0x0 for transparency.
+ // Fixes bug #2057619: FW: Glitches in title display of demo (regression).
+ if (scumm_stricmp(resourceName, "TITRE.ANI") == 0 && animHeader.frameHeight == 37) {
+ transparentColor = 0xF;
+ }
+
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
@@ -761,7 +768,7 @@ int loadResource(const char *resourceName, int16 idx) {
} else if (strstr(resourceName, ".AMI")) {
warning("loadResource: Ignoring file '%s' (Load at %d)", resourceName, idx);
} else if (strstr(resourceName, "ECHEC")) { // Echec (French) means failure
- exitEngine = 1;
+ g_cine->quitGame();
} else {
error("loadResource: Cannot determine type for '%s'", resourceName);
}
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index 45bfae7925..cc7e843c2b 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -41,10 +41,18 @@ byte loadCtFW(const char *ctName) {
uint16 header[32];
byte *ptr, *dataPtr;
+ int16 foundFileIdx = findFileInBundle(ctName);
+ if (foundFileIdx == -1) {
+ warning("loadCtFW: Unable to find collision data file '%s'", ctName);
+ // FIXME: Rework this function's return value policy and return an appropriate value here.
+ // The return value isn't yet used for anything so currently it doesn't really matter.
+ return 0;
+ }
+
if (currentCtName != ctName)
strcpy(currentCtName, ctName);
- ptr = dataPtr = readBundleFile(findFileInBundle(ctName));
+ ptr = dataPtr = readBundleFile(foundFileIdx);
loadRelatedPalette(ctName);
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index 9eb751835e..2c0fdc7d88 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -23,7 +23,6 @@
*
*/
-#include "common/events.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
@@ -101,6 +100,7 @@ int CineEngine::go() {
delete renderer;
delete[] collisionPage;
delete g_sound;
+
return 0;
}
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index b15f30c35c..91ef964a0b 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -533,8 +533,17 @@ public:
}
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual SaveStateList listSaves(const char *target) const;
};
+bool CineMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad);
+}
+
bool CineMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Cine::CINEGameDescription *gd = (const Cine::CINEGameDescription *)desc;
if (gd) {
@@ -543,6 +552,50 @@ bool CineMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
+SaveStateList CineMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ SaveStateList saveList;
+
+ Common::String pattern = target;
+ pattern += ".?";
+ Common::StringList filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end());
+ Common::StringList::const_iterator file = filenames.begin();
+
+ Common::String filename = target;
+ filename += ".dir";
+ Common::InSaveFile *in = saveFileMan->openForLoading(filename.c_str());
+ if (in) {
+ int8 ch;
+ char saveDesc[20];
+ do {
+ // Obtain the last digit of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 1);
+
+ uint pos = 0;
+ do {
+ ch = in->readByte();
+ if (pos < (sizeof(saveDesc) - 1)) {
+ if (ch < 32 || in->eos()) {
+ saveDesc[pos++] = '\0';
+ }
+ else if (ch >= 32) {
+ saveDesc[pos++] = ch;
+ }
+ }
+ } while (ch >= 32 && !in->eos());
+ if (saveDesc[0] != 0) {
+ saveList.push_back(SaveStateDescriptor(slotNum, Common::String(saveDesc), *file));
+ file++;
+ }
+ } while (!in->eos());
+ }
+
+ delete in;
+
+ return saveList;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(CINE)
REGISTER_PLUGIN_DYNAMIC(CINE, PLUGIN_TYPE_ENGINE, CineMetaEngine);
#else
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index cb900e8850..e24b23f7f0 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -200,9 +200,15 @@ void FWRenderer::incrustSprite(const objectStruct &obj) {
width = animDataTable[obj.frame]._realWidth;
height = animDataTable[obj.frame]._height;
- assert(mask);
-
- drawSpriteRaw(data, mask, width, height, _background, x, y);
+ // There was an assert(mask) here before but it made savegame loading
+ // in Future Wars sometimes fail the assertion (e.g. see bug #2055912).
+ // Not drawing sprites that have no mask seems to work, but not sure
+ // if this is really a correct way to fix this.
+ if (mask) {
+ drawSpriteRaw(data, mask, width, height, _background, x, y);
+ } else { // mask == NULL
+ warning("FWRenderer::incrustSprite: Skipping maskless sprite (frame=%d)", obj.frame);
+ }
}
/*! \brief Draw command box on screen
@@ -368,7 +374,7 @@ int FWRenderer::drawChar(char character, int x, int y) {
x += 5;
} else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
- drawSpriteRaw(g_cine->_textHandler.textTable[idx][0], g_cine->_textHandler.textTable[idx][1], 16, 8, _backBuffer, x, y);
+ drawSpriteRaw(g_cine->_textHandler.textTable[idx][FONT_DATA], g_cine->_textHandler.textTable[idx][FONT_MASK], FONT_WIDTH, FONT_HEIGHT, _backBuffer, x, y);
x += width + 1;
}
@@ -436,6 +442,9 @@ void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
switch (it->type) {
// color sprite
case 0:
+ if (objectTable[it->objIdx].frame < 0) {
+ return;
+ }
sprite = &animDataTable[objectTable[it->objIdx].frame];
len = sprite->_realWidth * sprite->_height;
mask = new byte[len];
@@ -1037,7 +1046,7 @@ int OSRenderer::drawChar(char character, int x, int y) {
x += 5;
} else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
- drawSpriteRaw2(g_cine->_textHandler.textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
+ drawSpriteRaw2(g_cine->_textHandler.textTable[idx][FONT_DATA], 0, FONT_WIDTH, FONT_HEIGHT, _backBuffer, x, y);
x += width + 1;
}
@@ -1664,6 +1673,16 @@ void gfxResetRawPage(byte *pageRaw) {
}
void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h) {
+ // Output is 4 bits per pixel.
+ // Pixels are in 16 pixel chunks (8 bytes of source per 16 pixels of output).
+ // The source data is interleaved so that
+ // 1st big-endian 16-bit value contains all bit position 0 values for 16 pixels,
+ // 2nd big-endian 16-bit value contains all bit position 1 values for 16 pixels,
+ // 3rd big-endian 16-bit value contains all bit position 2 values for 16 pixels,
+ // 4th big-endian 16-bit value contains all bit position 3 values for 16 pixels.
+ // 1st pixel's bits are in the 16th bits,
+ // 2nd pixel's bits are in the 15th bits,
+ // 3rd pixel's bits are in the 14th bits etc.
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w / 8; ++x) {
for (int bit = 0; bit < 16; ++bit) {
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index e2402a4c8d..04c6f5c769 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -25,7 +25,6 @@
#include "common/scummsys.h"
-#include "common/events.h"
#include "common/system.h"
#include "cine/main_loop.h"
@@ -61,9 +60,6 @@ static void processEvent(Common::Event &event) {
break;
case Common::EVENT_MOUSEMOVE:
break;
- case Common::EVENT_QUIT:
- exitEngine = 1;
- break;
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
case Common::KEYCODE_RETURN:
@@ -258,13 +254,9 @@ void purgeSeqList() {
void CineEngine::mainLoop(int bootScriptIdx) {
bool playerAction;
- uint16 quitFlag;
byte di;
uint16 mouseButton;
- quitFlag = 0;
- exitEngine = 0;
-
if (_preLoad == false) {
resetBgIncrustList();
@@ -418,7 +410,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
if ("quit"[menuCommandLen] == (char)di) {
++menuCommandLen;
if (menuCommandLen == 4) {
- quitFlag = 1;
+ quitGame();
}
} else {
menuCommandLen = 0;
@@ -427,7 +419,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
manageEvents();
- } while (!exitEngine && !quitFlag && _danKeysPressed != 7);
+ } while (!quit() && _danKeysPressed != 7);
hideMouse();
g_sound->stopMusic();
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index 657471be4e..7679d9d380 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -123,13 +123,13 @@ void CineEngine::readVolCnf() {
unpackedSize = packedSize = f.size();
}
uint8 *buf = new uint8[unpackedSize];
- f.read(buf, packedSize);
- if (packedSize != unpackedSize) {
- CineUnpacker cineUnpacker;
- if (!cineUnpacker.unpack(buf, packedSize, buf, unpackedSize)) {
- error("Error while unpacking 'vol.cnf' data");
- }
+ uint8 *packedBuf = new uint8[packedSize];
+ f.read(packedBuf, packedSize);
+ CineUnpacker cineUnpacker;
+ if (!cineUnpacker.unpack(packedBuf, packedSize, buf, unpackedSize)) {
+ error("Error while unpacking 'vol.cnf' data");
}
+ delete[] packedBuf;
uint8 *p = buf;
int resourceFilesCount = READ_BE_UINT16(p); p += 2;
int entrySize = READ_BE_UINT16(p); p += 2;
@@ -211,26 +211,23 @@ int16 findFileInBundle(const char *fileName) {
}
void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize) {
+ assert(maxSize >= partBuffer[idx].packedSize);
setMouseCursor(MOUSE_CURSOR_DISK);
g_cine->_partFileHandle.seek(partBuffer[idx].offset, SEEK_SET);
- g_cine->_partFileHandle.read(dataPtr, MIN(partBuffer[idx].packedSize, maxSize));
+ g_cine->_partFileHandle.read(dataPtr, partBuffer[idx].packedSize);
}
byte *readBundleFile(int16 foundFileIdx, uint32 *size) {
assert(foundFileIdx >= 0 && foundFileIdx < (int32)partBuffer.size());
bool error = false;
byte *dataPtr = (byte *)calloc(partBuffer[foundFileIdx].unpackedSize, 1);
- readFromPart(foundFileIdx, dataPtr, partBuffer[foundFileIdx].unpackedSize);
- if (partBuffer[foundFileIdx].unpackedSize > partBuffer[foundFileIdx].packedSize) {
- CineUnpacker cineUnpacker;
- error = !cineUnpacker.unpack(dataPtr, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize);
- } else if (partBuffer[foundFileIdx].unpackedSize < partBuffer[foundFileIdx].packedSize) {
- // Unpacked size of a file should never be less than its packed size
- error = true;
- } else { // partBuffer[foundFileIdx].unpackedSize == partBuffer[foundFileIdx].packedSize
- debugC(5, kCineDebugPart, "Loaded non-compressed file '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName);
- }
+ byte *packedData = (byte *)calloc(partBuffer[foundFileIdx].packedSize, 1);
+ assert(dataPtr && packedData);
+ readFromPart(foundFileIdx, packedData, partBuffer[foundFileIdx].packedSize);
+ CineUnpacker cineUnpacker;
+ error = !cineUnpacker.unpack(packedData, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize);
+ free(packedData);
if (error) {
warning("Error unpacking '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName);
diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp
index 5d789f9b3b..797a354c4f 100644
--- a/engines/cine/prc.cpp
+++ b/engines/cine/prc.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
+#include "common/events.h"
#include "cine/cine.h"
#include "cine/various.h"
@@ -54,7 +55,9 @@ bool loadPrc(const char *pPrcName) {
// This is copy protection. Used to hang the machine
if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) {
- exitEngine = 1;
+ Common::Event event;
+ event.type = Common::EVENT_RTL;
+ g_system->getEventManager()->pushEvent(event);
return false;
}
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 97f45488f2..6c13647ff3 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -1501,7 +1501,18 @@ int FWScript::o1_compareGlobalVar() {
debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
- _compare = compareVars(_globalVars[varIdx], value);
+ // WORKAROUND for bug #2054882. Without this, the monks will always
+ // kill you as an impostor, even if you enter the monastery in disguise.
+ //
+ // TODO: Check whether this might be worked around in some other way
+ // like setting global variable 255 to 143 in Future Wars (This is
+ // supposedly what Future Wars checks for from time to time during
+ // gameplay to verify that copy protection was successfully passed).
+ if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) {
+ _compare = kCmpEQ;
+ } else {
+ _compare = compareVars(_globalVars[varIdx], value);
+ }
}
return 0;
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 3618350476..164c5a9ca5 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -79,13 +79,13 @@ const int PCSoundDriver::_noteTable[] = {
const int PCSoundDriver::_noteTableCount = ARRAYSIZE(_noteTable);
struct AdlibRegisterSoundInstrument {
- uint16 vibrato;
- uint16 attackDecay;
- uint16 sustainRelease;
- uint16 feedbackStrength;
- uint16 keyScaling;
- uint16 outputLevel;
- uint16 freqMod;
+ uint8 vibrato;
+ uint8 attackDecay;
+ uint8 sustainRelease;
+ uint8 feedbackStrength;
+ uint8 keyScaling;
+ uint8 outputLevel;
+ uint8 freqMod;
};
struct AdlibSoundInstrument {
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index 33c16159ec..ffc36b4b1a 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -39,6 +39,13 @@ const char **commandPrepositionTable;
void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
+/*! \brief Loads font data from the given file.
+ * The number of characters used in the font varies between game versions:
+ * 78 (Most PC, Amiga and Atari ST versions of Future Wars, but also Operation Stealth's Amiga demo),
+ * 85 (All observed versions of German Future Wars (Amiga and PC), possibly Spanish Future Wars too),
+ * 90 (Most PC, Amiga and Atari ST versions of Operation Stealth),
+ * 93 (All observed versions of German Operation Stealth (Amiga and PC)).
+ */
void loadTextData(const char *filename) {
Common::File fileHandle;
assert(filename);
@@ -46,30 +53,29 @@ void loadTextData(const char *filename) {
if (!fileHandle.open(filename))
error("loadTextData(): Cannot open file %s", filename);
- uint entrySize = fileHandle.readUint16BE();
- uint numEntry = fileHandle.readUint16BE();
+ static const uint headerSize = 2 + 2; // The entry size (16-bit) and entry count (16-bit).
+ const uint entrySize = fileHandle.readUint16BE(); // Observed values: 8.
+ const uint entryCount = fileHandle.readUint16BE(); // Observed values: 624, 680, 720, 744.
+ const uint fontDataSize = entryCount * entrySize; // Observed values: 4992, 5440, 5760, 5952.
+ const uint numChars = entryCount / entrySize; // Observed values: 78, 85, 90, 93.
+ const uint bytesPerChar = fontDataSize / numChars; // Observed values: 64.
+ static const uint bytesPerRow = FONT_WIDTH / 2; // The input font data is 4-bit so it takes only half the space
+
+ if (headerSize + fontDataSize != (uint)fileHandle.size()) {
+ warning("loadTextData: file '%s' (entrySize = %d, entryCount = %d) is of incorrect size %d", filename, entrySize, entryCount, fileHandle.size());
+ }
- uint sourceSize = numEntry * entrySize;
Common::Array<byte> source;
- source.resize(sourceSize);
- fileHandle.read(source.begin(), sourceSize);
+ source.resize(fontDataSize);
+ fileHandle.read(source.begin(), fontDataSize);
- const int fontHeight = 8;
- const int fontWidth = (g_cine->getGameType() == Cine::GType_FW) ? 16 : 8;
- uint numCharacters;
- uint bytesPerCharacter;
if (g_cine->getGameType() == Cine::GType_FW) {
- numCharacters = (g_cine->getFeatures() & GF_ALT_FONT) ? 85 : 78;
- bytesPerCharacter = sourceSize / numCharacters; // TODO: Check if this could be replaced with fontWidth * fontHeight
loadRelatedPalette(filename);
- } else {
- numCharacters = 90;
- bytesPerCharacter = fontWidth * fontHeight;
}
- for (uint i = 0; i < numCharacters; i++) {
- gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], &source[i * bytesPerCharacter], fontWidth, fontHeight);
- generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], fontWidth * fontHeight, 0);
+ for (uint i = 0; i < numChars; i++) {
+ gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][FONT_DATA], &source[i * bytesPerChar], bytesPerRow, FONT_HEIGHT);
+ generateMask(g_cine->_textHandler.textTable[i][FONT_DATA], g_cine->_textHandler.textTable[i][FONT_MASK], FONT_WIDTH * FONT_HEIGHT, 0);
}
fileHandle.close();
diff --git a/engines/cine/texte.h b/engines/cine/texte.h
index bc4beac492..0b1fc88e86 100644
--- a/engines/cine/texte.h
+++ b/engines/cine/texte.h
@@ -36,13 +36,20 @@ typedef char CommandeType[20];
// Number of characters in a font
#define NUM_FONT_CHARS 256
+#define FONT_WIDTH 16
+#define FONT_HEIGHT 8
+
+// Used for choosing between font's data and font's mask
+#define FONT_DATA 0
+#define FONT_MASK 1
+
struct CharacterEntry {
byte characterIdx;
byte characterWidth;
};
struct TextHandler {
- byte textTable[NUM_FONT_CHARS][2][16 * 8];
+ byte textTable[NUM_FONT_CHARS][2][FONT_WIDTH * FONT_HEIGHT];
CharacterEntry fontParamTable[NUM_FONT_CHARS];
};
diff --git a/engines/cine/unpack.cpp b/engines/cine/unpack.cpp
index 5d85ff6cab..7915fd1cf8 100644
--- a/engines/cine/unpack.cpp
+++ b/engines/cine/unpack.cpp
@@ -100,6 +100,14 @@ bool CineUnpacker::unpack(const byte *src, uint srcLen, byte *dst, uint dstLen)
_dstBegin = dst;
_dstEnd = dst + dstLen;
+ // Handle already unpacked data here
+ if (srcLen == dstLen) {
+ // Source length is same as destination length so the source
+ // data is already unpacked. Let's just copy it then.
+ memcpy(dst, src, srcLen);
+ return true;
+ }
+
// Initialize other variables
_src = _srcBegin + srcLen - 4;
uint32 unpackedLength = readSource(); // Unpacked length in bytes
diff --git a/engines/cine/unpack.h b/engines/cine/unpack.h
index e16cb594a9..2355df5ee1 100644
--- a/engines/cine/unpack.h
+++ b/engines/cine/unpack.h
@@ -35,14 +35,14 @@ namespace Cine {
* A LZ77 style decompressor for Delphine's data files
* used in at least Future Wars and Operation Stealth.
* @note Works backwards in the source and destination buffers.
- * @note Can work with source and destination in the same buffer if there's space.
+ * @warning Having the source and destination in the same buffer when unpacking can cause errors!
*/
class CineUnpacker {
public:
/**
* Unpacks packed data from the source buffer to the destination buffer.
- * @warning Do NOT call this on data that is not packed.
- * @note Source and destination buffer pointers can be the same as long as there's space for the unpacked data.
+ * @note You may call this on already unpacked data but then source length must be equal to destination length.
+ * @warning The source and destination should not point to the same buffer. If they do, errors may occur!
* @param src Pointer to the source buffer.
* @param srcLen Length of the source buffer.
* @param dst Pointer to the destination buffer.
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index e96e03b03c..92fd35d865 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -25,7 +25,6 @@
#include "common/endian.h"
-#include "common/events.h"
#include "common/savefile.h"
#include "cine/cine.h"
@@ -125,7 +124,6 @@ static const int16 canUseOnItemTable[] = { 1, 0, 0, 1, 1, 0, 0 };
CommandeType objectListCommand[20];
int16 objListTab[20];
-uint16 exitEngine;
Common::Array<uint16> zoneData;
Common::Array<uint16> zoneQuery; //!< Only exists in Operation Stealth
@@ -499,7 +497,7 @@ enum CineSaveGameFormat detectSaveGameFormat(Common::SeekableReadStream &fHandle
uint animEntrySize = animEntrySizeChoices[i];
// Jump over the animDataTable entries and the screen parameters
- uint32 newPos = animDataTableStart + animEntrySize * animEntriesCount + sizeofScreenParams;
+ int32 newPos = animDataTableStart + animEntrySize * animEntriesCount + sizeofScreenParams;
// Check that there's data left after the point we're going to jump to
if (newPos >= fHandle.size()) {
continue;
@@ -1094,7 +1092,7 @@ bool CineEngine::makeLoad(char *saveName) {
// that's not implemented here because it was never used in a stable
// release of ScummVM but only during development (From revision 31453,
// which introduced the problem, until revision 32073, which fixed it).
- // Therefore be bail out if we detect this particular savegame format.
+ // Therefore we bail out if we detect this particular savegame format.
warning("Detected a known broken savegame format, not loading savegame");
load = false; // Don't load the savegame
} else if (saveGameFormat == ANIMSIZE_UNKNOWN) {
@@ -1223,7 +1221,7 @@ void CineEngine::makeSystemMenu(void) {
{
getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
- exitEngine = 1;
+ quitGame();
}
break;
}
diff --git a/engines/cine/various.h b/engines/cine/various.h
index 0ee77c1b47..b841908c65 100644
--- a/engines/cine/various.h
+++ b/engines/cine/various.h
@@ -120,8 +120,6 @@ void mainLoopSub6(void);
void checkForPendingDataLoad(void);
-extern uint16 exitEngine;
-
void hideMouse(void);
void removeExtention(char *dest, const char *source);
diff --git a/engines/cruise/object.cpp b/engines/cruise/object.cpp
index 66a3a53018..bb8d85acd0 100644
--- a/engines/cruise/object.cpp
+++ b/engines/cruise/object.cpp
@@ -58,7 +58,7 @@ objDataStruct *getObjectDataFromOverlay(int ovlIdx, int objIdx) {
}
int16 getMultipleObjectParam(int16 overlayIdx, int16 objectIdx, objectParamsQuery *returnParam) {
- objectParams *ptr2;
+ objectParams *ptr2 = 0;
objDataStruct *ptr;
ovlDataStruct *ovlData;
// int16 type;
@@ -246,7 +246,7 @@ int16 getSingleObjectParam(int16 overlayIdx, int16 param2, int16 param3, int16 *
//char* ptr3 = NULL;
objDataStruct *ptr;
ovlDataStruct *ovlData;
- objectParams *ptr2;
+ objectParams *ptr2 = 0;
ptr = getObjectDataFromOverlay(overlayIdx, param2);
diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h
index a325de3f36..5f65446cc5 100644
--- a/engines/cruise/vars.h
+++ b/engines/cruise/vars.h
@@ -86,7 +86,7 @@ struct filesData2Struct {
int16 field_2;
};
-struct fileName {
+struct dataFileName {
char name[13];
};
@@ -103,7 +103,7 @@ struct setHeaderEntry {
struct volumeDataStruct {
char ident[10];
- fileName *ptr;
+ dataFileName *ptr;
int16 diskNumber;
int32 size;
};
diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp
index b2ff2631c0..47e2f02184 100644
--- a/engines/cruise/volume.cpp
+++ b/engines/cruise/volume.cpp
@@ -395,12 +395,12 @@ int16 readVolCnf(void) {
}
for (i = 0; i < numOfDisks; i++) {
- fileName *ptr;
+ dataFileName *ptr;
fileHandle.read(&volumeData[i].size, 4);
flipLong(&volumeData[i].size);
- ptr = (fileName *) mallocAndZero(volumeData[i].size);
+ ptr = (dataFileName *) mallocAndZero(volumeData[i].size);
volumeData[i].ptr = ptr;
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
new file mode 100644
index 0000000000..8d8888246b
--- /dev/null
+++ b/engines/dialogs.cpp
@@ -0,0 +1,264 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "base/version.h"
+
+#include "common/config-manager.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/events.h"
+
+#include "graphics/scaler.h"
+
+#include "gui/about.h"
+#include "gui/newgui.h"
+#include "gui/ListWidget.h"
+#include "gui/theme.h"
+
+#include "engines/dialogs.h"
+#include "engines/engine.h"
+#include "engines/metaengine.h"
+
+#ifdef SMALL_SCREEN_DEVICE
+#include "gui/KeysDialog.h"
+#endif
+
+using GUI::CommandSender;
+using GUI::StaticTextWidget;
+using GUI::kButtonWidth;
+using GUI::kButtonHeight;
+using GUI::kBigButtonWidth;
+using GUI::kBigButtonHeight;
+using GUI::kCloseCmd;
+using GUI::kTextAlignCenter;
+using GUI::kTextAlignLeft;
+using GUI::WIDGET_ENABLED;
+
+typedef GUI::OptionsDialog GUI_OptionsDialog;
+typedef GUI::Dialog GUI_Dialog;
+
+GlobalDialog::GlobalDialog(String name) : GUI::Dialog(name) {}
+
+enum {
+ kSaveCmd = 'SAVE',
+ kLoadCmd = 'LOAD',
+ kPlayCmd = 'PLAY',
+ kOptionsCmd = 'OPTN',
+ kHelpCmd = 'HELP',
+ kAboutCmd = 'ABOU',
+ kQuitCmd = 'QUIT',
+ kRTLCmd = 'RTL ',
+ kChooseCmd = 'CHOS'
+};
+
+MainMenuDialog::MainMenuDialog(Engine *engine)
+ : GlobalDialog("globalmain"), _engine(engine) {
+
+#ifndef DISABLE_FANCY_THEMES
+ _logo = 0;
+ if (g_gui.xmlEval()->getVar("global_logo.visible") == 1 && g_gui.theme()->supportsImages()) {
+ _logo = new GUI::GraphicsWidget(this, "global_logo");
+ _logo->useThemeTransparency(true);
+ _logo->setGfx(g_gui.theme()->getImageSurface(GUI::Theme::kImageLogoSmall));
+ } else {
+ new StaticTextWidget(this, "global_title", "ScummVM");
+ }
+#else
+ new StaticTextWidget(this, "global_title", "ScummVM");
+#endif
+
+ new StaticTextWidget(this, "global_version", gScummVMVersionDate);
+
+ new GUI::ButtonWidget(this, "globalmain_resume", "Resume", kPlayCmd, 'P');
+
+// new GUI::ButtonWidget(this, "globalmain_load", "Load", kLoadCmd, 'L');
+// new GUI::ButtonWidget(this, "globalmain_save", "Save", kSaveCmd, 'S');
+
+ new GUI::ButtonWidget(this, "globalmain_options", "Options", kOptionsCmd, 'O');
+
+ new GUI::ButtonWidget(this, "globalmain_about", "About", kAboutCmd, 'A');
+
+ _rtlButton = new GUI::ButtonWidget(this, "globalmain_rtl", "Return to Launcher", kRTLCmd, 'R');
+ // '0' corresponds to the kSupportsRTL MetaEngineFeature
+ _rtlButton->setEnabled(_engine->hasFeature(0));
+
+
+ new GUI::ButtonWidget(this, "globalmain_quit", "Quit", kQuitCmd, 'Q');
+
+ _aboutDialog = new GUI::AboutDialog();
+ _optionsDialog = new ConfigDialog();
+}
+
+MainMenuDialog::~MainMenuDialog() {
+ delete _aboutDialog;
+ delete _optionsDialog;
+}
+
+void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case kPlayCmd:
+ close();
+ break;
+ case kOptionsCmd:
+ _optionsDialog->runModal();
+ break;
+ case kAboutCmd:
+ _aboutDialog->runModal();
+ break;
+ case kRTLCmd: {
+ Common::Event eventRTL;
+ eventRTL.type = Common::EVENT_RTL;
+ g_system->getEventManager()->pushEvent(eventRTL);
+ close();
+ }
+ break;
+ case kQuitCmd: {
+ Common::Event eventQ;
+ eventQ.type = Common::EVENT_QUIT;
+ g_system->getEventManager()->pushEvent(eventQ);
+ close();
+ }
+ break;
+ default:
+ GlobalDialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void MainMenuDialog::reflowLayout() {
+#ifndef DISABLE_FANCY_THEMES
+ if (g_gui.xmlEval()->getVar("global_logo.visible") == 1 && g_gui.theme()->supportsImages()) {
+ if (!_logo)
+ _logo = new GUI::GraphicsWidget(this, "global_logo");
+ _logo->useThemeTransparency(true);
+ _logo->setGfx(g_gui.theme()->getImageSurface(GUI::Theme::kImageLogoSmall));
+
+ GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("global_title");
+ if (title) {
+ removeWidget(title);
+ title->setNext(0);
+ delete title;
+ }
+ } else {
+ GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("global_title");
+ if (!title)
+ new StaticTextWidget(this, "global_title", "ScummVM");
+
+ if (_logo) {
+ removeWidget(_logo);
+ _logo->setNext(0);
+ delete _logo;
+ _logo = 0;
+ }
+ }
+#endif
+
+ Dialog::reflowLayout();
+}
+
+enum {
+ kOKCmd = 'ok '
+};
+
+enum {
+ kKeysCmd = 'KEYS'
+};
+
+// FIXME: We use the empty string as domain name here. This tells the
+// ConfigManager to use the 'default' domain for all its actions. We do that
+// to get as close as possible to editing the 'active' settings.
+//
+// However, that requires bad & evil hacks in the ConfigManager code,
+// and even then still doesn't work quite correctly.
+// For example, if the transient domain contains 'false' for the 'fullscreen'
+// flag, but the user used a hotkey to switch to windowed mode, then the dialog
+// will display the wrong value anyway.
+//
+// Proposed solution consisting of multiple steps:
+// 1) Add special code to the open() code that reads out everything stored
+// in the transient domain that is controlled by this dialog, and updates
+// the dialog accordingly.
+// 2) Even more code is added to query the backend for current settings, like
+// the fullscreen mode flag etc., and also updates the dialog accordingly.
+// 3) The domain being edited is set to the active game domain.
+// 4) If the dialog is closed with the "OK" button, then we remove everything
+// stored in the transient domain (or at least everything corresponding to
+// switches in this dialog.
+// If OTOH the dialog is closed with "Cancel" we do no such thing.
+//
+// These changes will achieve two things at once: Allow us to get rid of using
+// "" as value for the domain, and in fact provide a somewhat better user
+// experience at the same time.
+ConfigDialog::ConfigDialog()
+ : GUI::OptionsDialog("", "scummconfig") {
+
+ //
+ // Sound controllers
+ //
+
+ addVolumeControls(this, "scummconfig_");
+
+ //
+ // Some misc options
+ //
+
+ // SCUMM has a talkspeed range of 0-9
+ addSubtitleControls(this, "scummconfig_", 9);
+
+ //
+ // Add the buttons
+ //
+
+ new GUI::ButtonWidget(this, "scummconfig_ok", "OK", GUI::OptionsDialog::kOKCmd, 'O');
+ new GUI::ButtonWidget(this, "scummconfig_cancel", "Cancel", kCloseCmd, 'C');
+
+#ifdef SMALL_SCREEN_DEVICE
+ new GUI::ButtonWidget(this, "scummconfig_keys", "Keys", kKeysCmd, 'K');
+
+ //
+ // Create the sub dialog(s)
+ //
+
+ _keysDialog = new GUI::KeysDialog();
+#endif
+}
+
+ConfigDialog::~ConfigDialog() {
+#ifdef SMALL_SCREEN_DEVICE
+ delete _keysDialog;
+#endif
+}
+
+void ConfigDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case kKeysCmd:
+
+#ifdef SMALL_SCREEN_DEVICE
+ _keysDialog->runModal();
+#endif
+ break;
+ default:
+ GUI_OptionsDialog::handleCommand (sender, cmd, data);
+ }
+}
+
diff --git a/engines/dialogs.h b/engines/dialogs.h
new file mode 100644
index 0000000000..66ea13b8f1
--- /dev/null
+++ b/engines/dialogs.h
@@ -0,0 +1,77 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 GLOBAL_DIALOGS_H
+#define GLOBAL_DIALOGS_H
+
+#include "common/str.h"
+#include "gui/dialog.h"
+#include "gui/options.h"
+#include "gui/widget.h"
+
+#include "engines/engine.h"
+
+
+class GlobalDialog : public GUI::Dialog {
+public:
+ GlobalDialog(Common::String name);
+
+protected:
+ typedef Common::String String;
+};
+
+
+class MainMenuDialog : public GlobalDialog {
+public:
+ MainMenuDialog(Engine *engine);
+ ~MainMenuDialog();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+
+ virtual void reflowLayout();
+
+protected:
+ Engine *_engine;
+
+ GUI::GraphicsWidget *_logo;
+ GUI::ButtonWidget *_rtlButton;
+ GUI::Dialog *_aboutDialog;
+ GUI::Dialog *_optionsDialog;
+
+};
+
+class ConfigDialog : public GUI::OptionsDialog {
+protected:
+#ifdef SMALL_SCREEN_DEVICE
+ GUI::Dialog *_keysDialog;
+#endif
+
+public:
+ ConfigDialog();
+ ~ConfigDialog();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+};
+
+#endif
diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp
index 10ce415c2c..ff46d8201a 100644
--- a/engines/drascula/actors.cpp
+++ b/engines/drascula/actors.cpp
@@ -28,45 +28,45 @@
namespace Drascula {
void DrasculaEngine::placeIgor() {
- int pos_igor[6] = { 1, 0, igorX, igorY, 54, 61 };
+ int igY = 0;
if (currentChapter == 4) {
- pos_igor[1] = 138;
+ igY = 138;
} else {
if (trackIgor == 3)
- pos_igor[1] = 138;
+ igY = 138;
else if (trackIgor == 1)
- pos_igor[1] = 76;
+ igY = 76;
}
- copyRectClip(pos_igor, frontSurface, screenSurface);
+ copyRect(1, igY, igorX, igorY, 54, 61, frontSurface, screenSurface);
}
void DrasculaEngine::placeDrascula() {
- int pos_dr[6] = { 0, 122, drasculaX, drasculaY, 45, 77 };
+ int drX = 0;
if (trackDrascula == 1)
- pos_dr[0] = 47;
+ drX = 47;
else if (trackDrascula == 0)
- pos_dr[0] = 1;
+ drX = 1;
else if (trackDrascula == 3 && currentChapter == 1)
- pos_dr[0] = 93;
+ drX = 93;
if (currentChapter == 6)
- copyRectClip(pos_dr, drawSurface2, screenSurface);
+ copyRect(drX, 122, drasculaX, drasculaY, 45, 77, drawSurface2, screenSurface);
else
- copyRectClip(pos_dr, backSurface, screenSurface);
+ copyRect(drX, 122, drasculaX, drasculaY, 45, 77, backSurface, screenSurface);
}
void DrasculaEngine::placeBJ() {
- int pos_bj[6] = { 0, 99, bjX, bjY, 26, 76 };
+ int bX = 0;
if (trackBJ == 3)
- pos_bj[0] = 10;
+ bX = 10;
else if (trackBJ == 0)
- pos_bj[0] = 37;
+ bX = 37;
- copyRectClip(pos_bj, drawSurface3, screenSurface);
+ copyRect(bX, 99, bjX, bjY, 26, 76, drawSurface3, screenSurface);
}
void DrasculaEngine::hiccup(int counter) {
@@ -189,7 +189,7 @@ void DrasculaEngine::moveCharacters() {
}
}
- if (currentChapter == 1 || currentChapter == 4 || currentChapter == 5 || currentChapter == 6) {
+ if (currentChapter != 2 && currentChapter != 3) {
if (hare_se_ve == 0) {
increaseFrameNum();
return;
@@ -212,25 +212,29 @@ void DrasculaEngine::moveCharacters() {
if (trackProtagonist == 0) {
curPos[1] = 0;
if (currentChapter == 2)
- copyRectClip(curPos, extraSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ extraSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], extraSurface, screenSurface);
} else if (trackProtagonist == 1) {
if (currentChapter == 2)
- copyRectClip(curPos, extraSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ extraSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], extraSurface, screenSurface);
} else if (trackProtagonist == 2) {
if (currentChapter == 2)
- copyRectClip(curPos, backSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ backSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], backSurface, screenSurface);
} else {
if (currentChapter == 2)
- copyRectClip(curPos, frontSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ frontSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], frontSurface, screenSurface);
@@ -250,25 +254,29 @@ void DrasculaEngine::moveCharacters() {
if (trackProtagonist == 0) {
curPos[1] = 0;
if (currentChapter == 2)
- copyRectClip(curPos, extraSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ extraSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], extraSurface, screenSurface);
} else if (trackProtagonist == 1) {
if (currentChapter == 2)
- copyRectClip(curPos, extraSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ extraSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], extraSurface, screenSurface);
} else if (trackProtagonist == 2) {
if (currentChapter == 2)
- copyRectClip(curPos, backSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ backSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], backSurface, screenSurface);
} else {
if (currentChapter == 2)
- copyRectClip(curPos, frontSurface, screenSurface);
+ copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
+ frontSurface, screenSurface);
else
reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5],
factor_red[curY + curHeight], frontSurface, screenSurface);
@@ -288,11 +296,11 @@ void DrasculaEngine::quadrant_1() {
distanceY = (curY + curHeight) - roomY;
if (distanceX < distanceY) {
- curDirection = 0;
+ curDirection = kDirectionUp;
trackProtagonist = 2;
stepX = (int)(distanceX / (distanceY / STEP_Y));
} else {
- curDirection = 7;
+ curDirection = kDirectionUp;
trackProtagonist = 0;
stepY = (int)(distanceY / (distanceX / STEP_X));
}
@@ -309,11 +317,11 @@ void DrasculaEngine::quadrant_2() {
distanceY = (curY + curHeight) - roomY;
if (distanceX < distanceY) {
- curDirection = 1;
+ curDirection = kDirectionRight;
trackProtagonist = 2;
stepX = (int)(distanceX / (distanceY / STEP_Y));
} else {
- curDirection = 2;
+ curDirection = kDirectionRight;
trackProtagonist = 1;
stepY = (int)(distanceY / (distanceX / STEP_X));
}
@@ -330,11 +338,11 @@ void DrasculaEngine::quadrant_3() {
distanceY = roomY - (curY + curHeight);
if (distanceX < distanceY) {
- curDirection = 5;
+ curDirection = kDirectionLeft;
trackProtagonist = 3;
stepX = (int)(distanceX / (distanceY / STEP_Y));
} else {
- curDirection = 6;
+ curDirection = kDirectionLeft;
trackProtagonist = 0;
stepY = (int)(distanceY / (distanceX / STEP_X));
}
@@ -351,11 +359,11 @@ void DrasculaEngine::quadrant_4() {
distanceY = roomY - (curY + curHeight);
if (distanceX < distanceY) {
- curDirection = 4;
+ curDirection = kDirectionDown;
trackProtagonist = 3;
stepX = (int)(distanceX / (distanceY / STEP_Y));
} else {
- curDirection = 3;
+ curDirection = kDirectionDown;
trackProtagonist = 1;
stepY = (int)(distanceY / (distanceX / STEP_X));
}
@@ -370,16 +378,16 @@ void DrasculaEngine::increaseFrameNum() {
if (num_frame == 6)
num_frame = 0;
- if (curDirection == 0 || curDirection == 7) {
+ if (curDirection == kDirectionUp) {
curX -= stepX;
curY -= stepY;
- } else if (curDirection == 1 || curDirection == 2) {
+ } else if (curDirection == kDirectionRight) {
curX += stepX;
curY -= stepY;
- } else if (curDirection == 3 || curDirection == 4) {
+ } else if (curDirection == kDirectionDown) {
curX += stepX;
curY += stepY;
- } else if (curDirection == 5 || curDirection == 6) {
+ } else if (curDirection == kDirectionLeft) {
curX -= stepX;
curY += stepY;
}
@@ -394,13 +402,13 @@ void DrasculaEngine::increaseFrameNum() {
}
void DrasculaEngine::walkDown() {
- curDirection = 4;
+ curDirection = kDirectionDown;
trackProtagonist = 3;
stepX = 0;
}
void DrasculaEngine::walkUp() {
- curDirection = 0;
+ curDirection = kDirectionUp;
trackProtagonist = 2;
stepX = 0;
}
@@ -432,7 +440,8 @@ void DrasculaEngine::moveVonBraun() {
actorFrames[kFrameVonBraun] = 1;
}
- copyRectClip(pos_vb, frontSurface, screenSurface);
+ copyRect(pos_vb[0], pos_vb[1], pos_vb[2], pos_vb[3], pos_vb[4], pos_vb[5],
+ frontSurface, screenSurface);
}
void DrasculaEngine::placeVonBraun(int pointX) {
diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp
index 06868494b5..ad7fe64d0e 100644
--- a/engines/drascula/animation.cpp
+++ b/engines/drascula/animation.cpp
@@ -55,7 +55,7 @@ void DrasculaEngine::updateAnim2(int y, int px, int py, int width, int height, i
// This is the game's introduction sequence
void DrasculaEngine::animation_1_1() {
int l, l2, p;
- int pixelPos[6];
+ //int pixelPos[6];
while (term_int == 0) {
playMusic(29);
@@ -87,7 +87,7 @@ void DrasculaEngine::animation_1_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
color_abc(kColorRed);
- centerText(_textmisc[_lang][1], 160, 100);
+ centerText(_textmisc[1], 160, 100);
updateScreen();
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
@@ -134,7 +134,7 @@ void DrasculaEngine::animation_1_1() {
for (l2 = 0; l2 < 3; l2++)
for (l = 0; l < 7; l++) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyBackground(interf_x[l], interf_y[l], 156, 45, 63, 31, drawSurface2, screenSurface);
updateScreen();
if (getScan() == Common::KEYCODE_ESCAPE) {
@@ -147,19 +147,13 @@ void DrasculaEngine::animation_1_1() {
break;
l2 = 0; p = 0;
- pixelPos[3] = 45;
- pixelPos[4] = 63;
- pixelPos[5] = 31;
for (l = 0; l < 180; l++) {
copyBackground(0, 0, 320 - l, 0, l, 200, drawSurface3, screenSurface);
copyBackground(l, 0, 0, 0, 320 - l, 200, bgSurface, screenSurface);
- pixelPos[0] = interf_x[l2];
- pixelPos[1] = interf_y[l2];
- pixelPos[2] = 156 - l;
-
- copyRectClip(pixelPos, drawSurface2, screenSurface);
+ copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31,
+ drawSurface2, screenSurface);
updateScreen();
p++;
if (p == 6) {
@@ -177,7 +171,7 @@ void DrasculaEngine::animation_1_1() {
break;
copyBackground(0, 0, 0, 0, 320, 200, screenSurface, bgSurface);
- talk_dr_grande(1);
+ talk_drascula_big(1);
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
@@ -193,14 +187,14 @@ void DrasculaEngine::animation_1_1() {
igorX = 66;
igorY = 97;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
talk_igor(8, kIgorDch);
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
@@ -219,12 +213,12 @@ void DrasculaEngine::animation_1_1() {
loadPic("plan1.alg", screenSurface, HALF_PAL);
updateScreen();
pause(10);
- talk_solo(_textd[_lang][4],"d4.als");
+ talk_solo(_textd[4],"d4.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
loadPic("plan1.alg", screenSurface, HALF_PAL);
updateScreen();
- talk_solo(_textd[_lang][5], "d5.als");
+ talk_solo(_textd[5], "d5.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
if (animate("lib2.bin", 16))
@@ -233,7 +227,7 @@ void DrasculaEngine::animation_1_1() {
loadPic("plan2.alg", screenSurface, HALF_PAL);
updateScreen();
pause(20);
- talk_solo(_textd[_lang][6], "d6.als");
+ talk_solo(_textd[6], "d6.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
if (animate("lib2.bin", 16))
@@ -244,12 +238,12 @@ void DrasculaEngine::animation_1_1() {
pause(20);
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
- talk_solo(_textd[_lang][7], "d7.als");
+ talk_solo(_textd[7], "d7.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
loadPic("plan3.alg", screenSurface, HALF_PAL);
updateScreen();
- talk_solo(_textd[_lang][8], "d8.als");
+ talk_solo(_textd[8], "d8.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
clearRoom();
@@ -297,13 +291,13 @@ void DrasculaEngine::animation_1_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
trackDrascula = 3;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
pause(1);
trackDrascula = 0;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
@@ -311,13 +305,13 @@ void DrasculaEngine::animation_1_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
trackDrascula = 3;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
pause(1);
trackDrascula = 1;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
@@ -329,13 +323,13 @@ void DrasculaEngine::animation_1_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
trackDrascula = 3;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
pause(1);
trackDrascula = 0;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
updateScreen();
@@ -402,9 +396,6 @@ void DrasculaEngine::animation_2_1() {
if (animate("ag.bin", 14))
break;
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an11y13.alg", extraSurface);
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
@@ -413,9 +404,6 @@ void DrasculaEngine::animation_2_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
- if (_lang == kSpanish)
- textSurface = extraSurface;
-
loadPic(97, extraSurface);
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
@@ -436,7 +424,7 @@ void DrasculaEngine::animation_2_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
- talk_solo(_textbj[_lang][1], "BJ1.als");
+ talk_solo(_textbj[1], "BJ1.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
clearRoom();
@@ -449,7 +437,7 @@ void DrasculaEngine::animation_2_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
color_solo = kColorYellow;
- talk_solo(_text[_lang][214], "214.als");
+ talk_solo(_text[214], "214.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
clearRoom();
@@ -491,23 +479,8 @@ void DrasculaEngine::animation_2_1() {
curX = 100;
curY = 95;
- talk_bj(2);
- talk(215);
- talk_bj(3);
- talk(216);
- talk_bj(4);
- talk_bj(5);
- talk_bj(6);
- talk(217);
- talk_bj(7);
- talk(218);
- talk_bj(8);
- talk(219);
- talk_bj(9);
- talk(220);
- talk(221);
- talk_bj(10);
- talk(222);
+ playTalkSequence(2); // sequence 2, chapter 1
+
if (animate("gaf.bin", 15))
break;
if (animate("bjb.bin", 14))
@@ -523,7 +496,7 @@ void DrasculaEngine::animation_2_1() {
pause(120);
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
- talk_solo(_text[_lang][223], "223.als");
+ talk_solo(_text[223], "223.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
color_solo = kColorWhite;
@@ -532,7 +505,7 @@ void DrasculaEngine::animation_2_1() {
break;
updateScreen();
pause(110);
- talk_solo(_textbj[_lang][11], "BJ11.als");
+ talk_solo(_textbj[11], "BJ11.als");
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE))
break;
updateRoom();
@@ -596,45 +569,17 @@ void DrasculaEngine::animation_2_1() {
}
}
+// John Hacker talks with the bartender to book a room
void DrasculaEngine::animation_3_1() {
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an11y13.alg", extraSurface);
- talk(192);
- talk_bartender(1);
- talk(193);
- talk_bartender(2);
- talk(194);
- talk_bartender(3);
- talk(195);
- talk_bartender(4);
- talk(196);
- talk_bartender(5);
- talk_bartender(6);
- talk(197);
- talk_bartender(7);
- talk(198);
- talk_bartender(8);
- talk(199);
- talk_bartender(9);
- talk(200);
- talk(201);
- talk(202);
-
- flags[0] = 1;
-
- if (_lang == kSpanish)
- textSurface = extraSurface;
+ playTalkSequence(3); // sequence 3, chapter 1
loadPic(97, extraSurface);
}
+// John Hacker talks with the pianist
void DrasculaEngine::animation_4_1() {
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an12.alg", extraSurface);
talk(205);
@@ -666,28 +611,20 @@ void DrasculaEngine::animation_4_1() {
talk_pianist(4);
talk(209);
- if (_lang == kSpanish)
- textSurface = extraSurface;
-
flags[11] = 0;
loadPic(97, extraSurface);
}
-void DrasculaEngine::animation_1_2() {
- gotoObject(178, 121);
- gotoObject(169, 135);
-}
-
void DrasculaEngine::animation_2_2() {
trackProtagonist = 0;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
moveCharacters();
updateRefresh();
updateScreen();
loadPic("an2_1.alg", frontSurface);
loadPic("an2_2.alg", extraSurface);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyBackground(1, 1, 201, 87, 50, 52, frontSurface, screenSurface);
updateScreen();
@@ -701,7 +638,7 @@ void DrasculaEngine::animation_2_2() {
updateAnim(55, 201, 87, 50, 52, 6, extraSurface);
updateAnim(109, 201, 87, 50, 52, 2, extraSurface);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
finishSound();
@@ -713,18 +650,12 @@ void DrasculaEngine::animation_2_2() {
finishSound();
}
-void DrasculaEngine::animation_3_2() {
- gotoObject(163, 106);
- gotoObject(287, 101);
- trackProtagonist = 0;
-}
-
void DrasculaEngine::animation_4_2() {
stopMusic();
flags[9] = 1;
pause(12);
- talk(56);
+ talk(60);
pause(8);
clearRoom();
@@ -734,10 +665,7 @@ void DrasculaEngine::animation_4_2() {
loadPic("ciego4.alg", backSurface);
loadPic("ciego5.alg", frontSurface);
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
pause(10);
@@ -761,13 +689,13 @@ void DrasculaEngine::animation_4_2() {
talk_blind(7);
talk_hacker(63);
talk_blind(8);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
_system->delayMillis(1000);
talk_hacker(64);
talk_blind(9);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
pause(14);
@@ -780,54 +708,25 @@ void DrasculaEngine::animation_4_2() {
loadPic(96, frontSurface);
loadPic(97, extraSurface);
loadPic(99, backSurface);
- withoutVerb();
-
- if (_lang == kSpanish)
- textSurface = extraSurface;
+ selectVerb(0);
flags[9] = 0;
flags[4] = 1;
}
-void DrasculaEngine::animation_8_2() {
- talk_pianist(6);
- talk(358);
- talk_pianist(7);
- talk_pianist(8);
-}
-
-void DrasculaEngine::animation_9_2() {
- talk_pianist(9);
- talk_pianist(10);
- talk_pianist(11);
-}
-
-void DrasculaEngine::animation_10_2() {
- talk_pianist(12);
- talk(361);
- pause(40);
- talk_pianist(13);
- talk(362);
- talk_pianist(14);
- talk(363);
- talk_pianist(15);
- talk(364);
- talk_pianist(16);
-}
-
void DrasculaEngine::animation_14_2() {
- int cabinPos[6] = { 150, 6, 69, -160, 158, 161 };
+ int cY = -160;
int l = 0;
loadPic("an14_2.alg", backSurface);
for (int n = -160; n <= 0; n = n + 5 + l) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
moveCharacters();
moveVonBraun();
- cabinPos[3] = n;
- copyRectClip(cabinPos, backSurface, screenSurface);
+ cY = n;
+ copyRect(150, 6, 69, cY, 158, 161, backSurface, screenSurface);
updateRefresh();
updateScreen();
l++;
@@ -845,143 +744,64 @@ void DrasculaEngine::animation_14_2() {
loadPic(99, backSurface);
}
-void DrasculaEngine::animation_15_2() {
- talk_drunk(8);
- pause(7);
- talk_drunk(9);
- talk_drunk(10);
- talk_drunk(11);
-}
-
+// The drunk tells us about Von Braun
void DrasculaEngine::animation_16_2() {
+ char curPic[20];
talk_drunk(12);
talk(371);
clearRoom();
+ // FIXME: Track 31 is missing from the soundtrack available
+ // from ScummVM's downloads page, so for now we're using the
+ // Spanish track 29
+#if 1
+ playMusic(30);
+#else
if (_lang == kSpanish)
playMusic(30);
else
playMusic(32);
+#endif
- int key = getScan();
- if (key != 0)
- goto asco;
-
- if (_lang != kSpanish)
- color_abc(kColorDarkGreen);
-
- loadPic("his1.alg", bgSurface, HALF_PAL);
-
- if (_lang == kSpanish)
- black();
-
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
-
- if (_lang != kSpanish)
- centerText(_texthis[_lang][1], 180, 180);
-
- updateScreen();
-
- if (_lang == kSpanish)
- fadeFromBlack(1);
-
- key = getScan();
- if (key != 0)
+ if (getScan() != 0)
goto asco;
- if (_lang == kSpanish)
- _system->delayMillis(3000);
- else
- _system->delayMillis(4000);
-
- key = getScan();
- if (key != 0)
- goto asco;
-
- fadeToBlack(1);
- key = getScan();
- if (key != 0)
- goto asco;
+ color_abc(kColorDarkGreen);
- clearRoom();
- loadPic("his2.alg", bgSurface, HALF_PAL);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
-
- if (_lang != kSpanish)
- centerText(_texthis[_lang][2], 180, 180);
-
- updateScreen();
- key = getScan();
- if (key != 0)
- goto asco;
-
- if (_lang == kSpanish)
- _system->delayMillis(3000);
- else
- _system->delayMillis(4000);
-
- key = getScan();
- if (key != 0)
- goto asco;
-
- fadeToBlack(1);
- key = getScan();
- if (key != 0)
- goto asco;
+ for (int i = 1; i <= 4; i++) {
+ if (i < 4)
+ sprintf(curPic, "his%i.alg", i);
+ else
+ strcpy(curPic, "his4_2.alg");
- clearRoom();
- loadPic("his3.alg", bgSurface, HALF_PAL);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ loadPic(curPic, screenSurface, HALF_PAL);
+ centerText(_texthis[i], 180, 180);
+ updateScreen();
- if (_lang != kSpanish)
- centerText(_texthis[_lang][3], 180, 180);
+ if (getScan() != 0)
+ goto asco;
- updateScreen();
- key = getScan();
- if (key != 0)
- goto asco;
+ delay(3000);
- if (_lang == kSpanish)
- _system->delayMillis(3000);
- else
- _system->delayMillis(4000);
+ if (i < 4) {
+ fadeToBlack(1);
- key = getScan();
- if (key != 0)
- goto asco;
+ if (getScan() != 0)
+ goto asco;
- fadeToBlack(1);
+ clearRoom();
+ }
+ }
- clearRoom();
loadPic("his4_1.alg", bgSurface, HALF_PAL);
loadPic("his4_2.alg", drawSurface3);
- copyBackground(0, 0, 0, 0, 320, 200, drawSurface3, screenSurface);
-
- if (_lang != kSpanish)
- centerText(_texthis[_lang][1], 180, 180);
-
- updateScreen();
- key = getScan();
- if (key != 0)
- goto asco;
-
- if (_lang == kSpanish)
- _system->delayMillis(2000);
- else
- _system->delayMillis(4000);
-
- key = getScan();
- if (key != 0)
- goto asco;
-
for (int l = 1; l < 200; l++) {
copyBackground(0, 0, 0, l, 320, 200 - l, drawSurface3, screenSurface);
copyBackground(0, 200 - l, 0, 0, 320, l, bgSurface, screenSurface);
updateScreen();
- key = getScan();
- if (key != 0)
+ if (getScan() != 0)
goto asco;
}
@@ -1002,34 +822,24 @@ asco:
stopMusic();
}
-void DrasculaEngine::animation_17_2() {
- talk_drunk(13);
- talk_drunk(14);
- flags[40] = 1;
-}
-
-void DrasculaEngine::animation_19_2() {
- talk_vonBraunpuerta(5);
-}
-
void DrasculaEngine::animation_20_2() {
- talk_vonBraunpuerta(7);
- talk_vonBraunpuerta(8);
+ talk_vonBraun(7, kVonBraunDoor);
+ talk_vonBraun(8, kVonBraunDoor);
talk(383);
- talk_vonBraunpuerta(9);
+ talk_vonBraun(9, kVonBraunDoor);
talk(384);
- talk_vonBraunpuerta(10);
+ talk_vonBraun(10, kVonBraunDoor);
talk(385);
- talk_vonBraunpuerta(11);
+ talk_vonBraun(11, kVonBraunDoor);
if (flags[23] == 0) {
talk(350);
- talk_vonBraunpuerta(57);
+ talk_vonBraun(57, kVonBraunDoor);
} else {
talk(386);
- talk_vonBraunpuerta(12);
+ talk_vonBraun(12, kVonBraunDoor);
flags[18] = 0;
flags[14] = 1;
- openDoor(15, 1);
+ toggleDoor(15, 1, kOpenDoor);
exitRoom(1);
animation_23_2();
exitRoom(0);
@@ -1042,36 +852,32 @@ void DrasculaEngine::animation_20_2() {
}
}
-void DrasculaEngine::animation_21_2() {
- talk_vonBraunpuerta(6);
-}
-
void DrasculaEngine::animation_23_2() {
loadPic("an24.alg", frontSurface);
flags[21] = 1;
if (flags[25] == 0) {
- talk_vonBraun(13);
- talk_vonBraun(14);
+ talk_vonBraun(13, kVonBraunDoor);
+ talk_vonBraun(14, kVonBraunDoor);
pause(10);
talk(387);
}
- talk_vonBraun(15);
+ talk_vonBraun(15, kVonBraunNormal);
placeVonBraun(42);
trackVonBraun = 1;
- talk_vonBraun(16);
+ talk_vonBraun(16, kVonBraunNormal);
trackVonBraun = 2;
gotoObject(157, 147);
gotoObject(131, 149);
trackProtagonist = 0;
animation_14_2();
if (flags[25] == 0)
- talk_vonBraun(17);
+ talk_vonBraun(17, kVonBraunNormal);
pause(8);
trackVonBraun = 1;
- talk_vonBraun(18);
+ talk_vonBraun(18, kVonBraunNormal);
if (flags[29] == 0)
animation_23_joined();
@@ -1083,9 +889,9 @@ void DrasculaEngine::animation_23_2() {
placeVonBraun(99);
if (flags[29] == 0) {
- talk_vonBraun(19);
+ talk_vonBraun(19, kVonBraunNormal);
if (flags[25] == 0) {
- talk_vonBraun(20);
+ talk_vonBraun(20, kVonBraunNormal);
if (removeObject(kItemMoney) == 0)
flags[30] = 1;
if (removeObject(kItemTwoCoins) == 0)
@@ -1093,7 +899,7 @@ void DrasculaEngine::animation_23_2() {
if (removeObject(kItemOneCoin) == 0)
flags[32] = 1;
}
- talk_vonBraun(21);
+ talk_vonBraun(21, kVonBraunNormal);
} else
animation_27_2();
@@ -1142,7 +948,7 @@ void DrasculaEngine::animation_23_joined2() {
}
void DrasculaEngine::animation_25_2() {
- int cabinPos[6] = { 150, 6, 69, 0, 158, 161 };
+ int cY = 0;
loadPic("an14_2.alg", backSurface);
loadPic(18, bgSurface);
@@ -1152,15 +958,15 @@ void DrasculaEngine::animation_25_2() {
playSound(6);
for (int n = 0; n >= -160; n = n - 8) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
moveCharacters();
moveVonBraun();
- cabinPos[3] = n;
+ cY = n;
- copyRectClip(cabinPos, backSurface, screenSurface);
+ copyRect(150, 6, 69, cY, 158, 161, backSurface, screenSurface);
updateRefresh();
updateScreen();
@@ -1174,50 +980,30 @@ void DrasculaEngine::animation_25_2() {
void DrasculaEngine::animation_27_2() {
flags[22] = 1;
- withoutVerb();
+ selectVerb(0);
removeObject(kItemEarWithEarPlug);
addObject(kItemEarplugs);
- talk_vonBraun(23);
- talk_vonBraun(24);
+ talk_vonBraun(23, kVonBraunNormal);
+ talk_vonBraun(24, kVonBraunNormal);
if (flags[30] == 1)
addObject(kItemMoney);
if (flags[31] == 1)
addObject(kItemTwoCoins);
if (flags[32] == 1)
addObject(kItemOneCoin);
- talk_vonBraun(25);
- talk_vonBraun(26);
-}
-
-void DrasculaEngine::animation_28_2() {
- for(int i = 27; i <= 30; i++)
- talk_vonBraun(i);
+ talk_vonBraun(25, kVonBraunNormal);
+ talk_vonBraun(26, kVonBraunNormal);
}
void DrasculaEngine::animation_29_2() {
if (flags[33] == 0) {
- talk_vonBraun(32);
- talk(398);
- talk_vonBraun(33);
- talk(399);
- talk_vonBraun(34);
- talk_vonBraun(35);
- talk(400);
- talk_vonBraun(36);
- talk_vonBraun(37);
- talk(386);
- talk_vonBraun(38);
- talk_vonBraun(39);
- talk(401);
- talk_vonBraun(40);
- talk_vonBraun(41);
- flags[33] = 1;
+ playTalkSequence(29); // sequence 29, chapter 2
} else
- talk_vonBraun(43);
+ talk_vonBraun(43, kVonBraunNormal);
talk(402);
- talk_vonBraun(42);
+ talk_vonBraun(42, kVonBraunNormal);
if (flags[38] == 0) {
talk(403);
@@ -1226,50 +1012,16 @@ void DrasculaEngine::animation_29_2() {
talk(386);
}
-void DrasculaEngine::animation_30_2() {
- talk_vonBraun(31);
- talk(396);
-}
-
void DrasculaEngine::animation_31_2() {
- talk_vonBraun(44);
+ talk_vonBraun(44, kVonBraunNormal);
placeVonBraun(-50);
pause(15);
gotoObject(159, 140);
loadPic(99, backSurface);
- trackProtagonist = 2;
- updateRoom();
- updateScreen();
- pause(78);
- trackProtagonist = 0;
- updateRoom();
- updateScreen();
- pause(22);
- talk(406);
- placeVonBraun(98);
- talk_vonBraun(45);
- talk_vonBraun(46);
- talk_vonBraun(47);
- talk(407);
- talk_vonBraun(48);
- talk_vonBraun(49);
- talk(408);
- talk_vonBraun(50);
- talk_vonBraun(51);
- talk(409);
- talk_vonBraun(52);
- talk_vonBraun(53);
- pause(12);
- talk_vonBraun(54);
- talk_vonBraun(55);
- talk(410);
- talk_vonBraun(56);
- breakOut = 1;
+ playTalkSequence(31); // sequence 31, chapter 2
- flags[38] = 0;
- flags[36] = 1;
- withoutVerb();
+ selectVerb(0);
removeObject(kItemLeaves);
removeObject(kItemBubbleGum);
removeObject(kItemTissues);
@@ -1293,7 +1045,7 @@ void DrasculaEngine::animation_35_2() {
updateAnim(1, 70, 90, 46, 80, 6, frontSurface);
updateAnim(82, 70, 90, 46, 80, 2, frontSurface);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
@@ -1308,13 +1060,6 @@ void DrasculaEngine::animation_35_2() {
fadeToBlack(2);
}
-void DrasculaEngine::animation_1_3() {
- talk(413);
- grr();
- pause(50);
- talk(414);
-}
-
void DrasculaEngine::animation_2_3() {
flags[0] = 1;
playMusic(13);
@@ -1396,7 +1141,7 @@ void DrasculaEngine::animation_6_3() {
for (frame = 0; frame < 6; frame++) {
pause(3);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyRect(yoda_x[frame], yoda_y[frame], px, py, 78, 90, frontSurface, screenSurface);
updateScreen(px, py, px, py, 78, 90, screenSurface);
}
@@ -1436,29 +1181,6 @@ void DrasculaEngine::animation_ray() {
finishSound();
}
-void DrasculaEngine::animation_2_4() {
- talk_igor(16, kIgorSeated);
- talk(278);
- talk_igor(17, kIgorSeated);
- talk(279);
- talk_igor(18, kIgorSeated);
-}
-
-void DrasculaEngine::animation_3_4() {
- talk_igor(19, kIgorSeated);
- talk_igor(20, kIgorSeated);
- talk(281);
-}
-
-void DrasculaEngine::animation_4_4() {
- talk(287);
- talk_igor(21, kIgorSeated);
- talk(284);
- talk_igor(22, kIgorSeated);
- talk(285);
- talk_igor(23, kIgorSeated);
-}
-
void DrasculaEngine::animation_7_4() {
black();
talk(427);
@@ -1512,37 +1234,6 @@ void DrasculaEngine::animation_1_5() {
converse(8);
}
-void DrasculaEngine::animation_2_5() {
- talk_bj(22);
-}
-
-void DrasculaEngine::animation_3_5() {
- talk_bj(23);
- pickObject(10);
- breakOut = 1;
-}
-
-void DrasculaEngine::animation_4_5() {
- flags[7] = 1;
- updateRoom();
- updateScreen();
- talk(228);
- talk_werewolf(1);
- talk_werewolf(2);
- pause(23);
- talk(229);
- talk_werewolf(3);
- talk_werewolf(4);
- talk(230);
- talk_werewolf(5);
- talk(231);
- talk_werewolf(6);
- talk_werewolf(7);
- pause(33);
- talk(232);
- talk_werewolf(8);
-}
-
void DrasculaEngine::animation_5_5(){
int h;
int frame = 0;
@@ -1551,7 +1242,7 @@ void DrasculaEngine::animation_5_5(){
int flyX[] = {1, 63, 125, 187, 249};
int pixelX = curX - 53, pixelY = curY - 9;
- withoutVerb();
+ selectVerb(0);
removeObject(8);
gotoObject(curX - 19, curY + curHeight);
@@ -1564,7 +1255,7 @@ void DrasculaEngine::animation_5_5(){
for (frame = 0; frame < 9; frame++) {
pause(3);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, backSurface, screenSurface);
updateScreen(pixelX, pixelY, pixelX,pixelY, 97,64, screenSurface);
}
@@ -1574,7 +1265,7 @@ void DrasculaEngine::animation_5_5(){
for (frame = 0; frame < 9; frame++) {
pause(3);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, frontSurface, screenSurface);
updateScreen(pixelX, pixelY, pixelX,pixelY, 97, 64, screenSurface);
}
@@ -1618,41 +1309,6 @@ void DrasculaEngine::animation_5_5(){
loadPic(49, bgSurface, HALF_PAL);
}
-void DrasculaEngine::animation_6_5() {
- talk_werewolf(9);
- talk(234);
-}
-
-void DrasculaEngine::animation_7_5() {
- talk_werewolf(10);
- talk(236);
- talk_werewolf(11);
- talk_werewolf(12);
- talk_werewolf(13);
- pause(34);
- talk_werewolf(14);
-}
-
-void DrasculaEngine::animation_8_5() {
- talk_werewolf(15);
- talk(238);
- talk_werewolf(16);
-}
-
-void DrasculaEngine::animation_9_5() {
- flags[4] = 1;
- talk(401);
- withoutVerb();
- removeObject(15);
-}
-
-void DrasculaEngine::animation_10_5() {
- flags[3] = 1;
- talk(401);
- withoutVerb();
- removeObject(12);
-}
-
void DrasculaEngine::animation_11_5() {
flags[9] = 1;
if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1)
@@ -1686,7 +1342,7 @@ void DrasculaEngine::animation_12_5() {
updateRoom();
updateScreen();
- setDarkPalette();
+ setDefaultPalette(darkPalette);
for (color = 0; color < 255; color++)
for (component = 0; component < 3; component++) {
@@ -1742,7 +1398,7 @@ void DrasculaEngine::animation_12_5() {
animate("frel.bin", 16);
clearRoom();
- setBrightPalette();
+ setDefaultPalette(brightPalette);
setPalette((byte *)&gamePalette);
flags[1] = 1;
@@ -1765,7 +1421,7 @@ void DrasculaEngine::animation_12_5() {
characterMoved = 0;
curX = -1;
objExit = 104;
- withoutVerb();
+ selectVerb(0);
enterRoom(57);
}
@@ -1774,12 +1430,11 @@ void DrasculaEngine::animation_13_5() {
int frame = 0;
int frus_x[] = {1, 46, 91, 136, 181, 226, 271};
int frus_y[] = {1, 1, 1, 1, 1, 1, 1, 89};
- int pos_frusky[6] = { 1, 1, frank_x, 81, 44, 87 };
loadPic("auxfr.alg", backSurface);
updateRoom();
- copyRectClip(pos_frusky, backSurface, screenSurface);
+ copyRect(1, 1, frank_x, 81, 44, 87, backSurface, screenSurface);
updateScreen();
pause(15);
@@ -1787,10 +1442,7 @@ void DrasculaEngine::animation_13_5() {
for (;;) {
updateRoom();
- pos_frusky[0] = frus_x[frame];
- pos_frusky[1] = frus_y[frame];
- pos_frusky[2] = frank_x;
- copyRectClip( pos_frusky, backSurface, screenSurface);
+ copyRect(frus_x[frame], frus_y[frame], frank_x, 81, 44, 87, backSurface, screenSurface);
updateScreen();
frank_x -= 5;
frame++;
@@ -1823,26 +1475,10 @@ void DrasculaEngine::animation_14_5() {
trackProtagonist = 3;
updateRoom();
updateScreen();
- talk_solo(_textd[_lang][18], "d18.als");
+ talk_solo(_textd[18], "d18.als");
fadeToBlack(1);
}
-void DrasculaEngine::animation_15_5() {
- talk_mus(4);
- talk_mus(5);
- talk_mus(6);
- talk(291);
- talk_mus(7);
-}
-
-void DrasculaEngine::animation_16_5() {
- talk_mus(8);
-}
-
-void DrasculaEngine::animation_17_5() {
- talk_mus(9);
-}
-
void DrasculaEngine::animation_1_6() {
trackProtagonist = 0;
curX = 103;
@@ -1909,36 +1545,21 @@ void DrasculaEngine::animation_1_6() {
trackDrascula = 0;
talk_drascula(35);
- if (_lang == kSpanish)
- textSurface = extraSurface;
-
clearRoom();
enterRoom(102);
activatePendulum();
}
-void DrasculaEngine::animation_2_6() {
- talk_drascula(24, 1);
-}
-
-void DrasculaEngine::animation_3_6() {
- talk_drascula(24, 1);
-}
-
-void DrasculaEngine::animation_4_6() {
- talk_drascula(25, 1);
-}
-
void DrasculaEngine::animation_5_6() {
- int pos_pen[6] = { 1, 29, 204, -125, 18, 125 };
+ int pY = -125;
animate("man.bin", 14);
for (int n = -125; n <= 0; n = n + 2) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
- pos_pen[3] = n;
- copyRectClip(pos_pen, drawSurface3, screenSurface);
+ pY = n;
+ copyRect(1, 29, 204, pY, 18, 125, drawSurface3, screenSurface);
updateRefresh();
@@ -1952,7 +1573,7 @@ void DrasculaEngine::animation_5_6() {
void DrasculaEngine::animation_6_6() {
animate("rct.bin", 11);
clearRoom();
- withoutVerb();
+ selectVerb(0);
removeObject(20);
loadPic(96, frontSurface);
loadPic(97, frontSurface);
@@ -1961,7 +1582,7 @@ void DrasculaEngine::animation_6_6() {
doBreak = 1;
objExit = 104;
curX = -1;
- withoutVerb();
+ selectVerb(0);
enterRoom(58);
hare_se_ve = 1;
trackProtagonist = 1;
@@ -1973,11 +1594,6 @@ void DrasculaEngine::animation_6_6() {
flags[2] = 1;
}
-void DrasculaEngine::animation_7_6() {
- flags[8] = 1;
- updateVisible();
-}
-
void DrasculaEngine::animation_9_6() {
int v_cd;
@@ -2014,11 +1630,11 @@ void DrasculaEngine::animation_9_6() {
clearRoom();
loadPic("nota.alg", bgSurface, COMPLETE_PAL);
color_abc(kColorWhite);
- talk_solo(_textbj[_lang][24], "bj24.als");
- talk_solo(_textbj[_lang][25], "bj25.als");
- talk_solo(_textbj[_lang][26], "bj26.als");
- talk_solo(_textbj[_lang][27], "bj27.als");
- talk_solo(_textbj[_lang][28], "bj28.als");
+ talk_solo(_textbj[24], "bj24.als");
+ talk_solo(_textbj[25], "bj25.als");
+ talk_solo(_textbj[26], "bj26.als");
+ talk_solo(_textbj[27], "bj27.als");
+ talk_solo(_textbj[28], "bj28.als");
trackProtagonist = 3;
clearRoom();
loadPic(96, frontSurface, COMPLETE_PAL);
@@ -2033,7 +1649,7 @@ void DrasculaEngine::animation_9_6() {
copyBackground(0, 0, 0, 0, 320, 200, screenSurface, bgSurface);
updateScreen();
color_abc(kColorLightGreen);
- talk_solo(_textmisc[_lang][2], "s15.als");
+ talk_solo(_textmisc[2], "s15.als");
loadPic("nota2.alg", bgSurface);
trackProtagonist = 0;
updateRoom();
@@ -2054,54 +1670,8 @@ void DrasculaEngine::animation_9_6() {
stopMusic();
}
-void DrasculaEngine::animation_10_6() {
- playSound(14);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
- updateRefresh_pre();
- copyBackground(164, 85, 155, 48, 113, 114, drawSurface3, screenSurface);
- updateScreen();
- finishSound();
- talk_bartender(23, 1);
- flags[7] = 1;
-}
-
-void DrasculaEngine::animation_11_6() {
- talk_bartender(10, 1);
- talk(268);
- talk_bartender(11, 1);
-}
-
-void DrasculaEngine::animation_12_6() {
- talk_bartender(12, 1);
- talk(270);
- talk_bartender(13, 1);
- talk_bartender(14, 1);
-}
-
-void DrasculaEngine::animation_13_6() {
- talk_bartender(15, 1);
-}
-
-void DrasculaEngine::animation_14_6() {
- talk_bartender(24, 1);
- addObject(21);
- flags[10] = 1;
- breakOut = 1;
-}
-
-void DrasculaEngine::animation_15_6() {
- talk_bartender(16, 1);
-}
-
-void DrasculaEngine::animation_18_6() {
- flags[6] = 1;
- withoutVerb();
- removeObject(21);
- animate("beb.bin", 10);
-}
-
void DrasculaEngine::animation_19_6() {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyBackground(140, 23, 161, 69, 35, 80, drawSurface3, screenSurface);
updateRefresh_pre();
@@ -2116,9 +1686,6 @@ void DrasculaEngine::animation_19_6() {
}
void DrasculaEngine::animation_12_2() {
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an12.alg", extraSurface);
talk(356);
@@ -2144,17 +1711,11 @@ void DrasculaEngine::animation_12_2() {
talk_pianist(5);
converse(1);
- if (_lang == kSpanish)
- textSurface = extraSurface;
-
flags[11] = 0;
loadPic(974, extraSurface);
}
void DrasculaEngine::animation_26_2() {
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an12.alg", extraSurface);
talk(392);
@@ -2205,9 +1766,6 @@ void DrasculaEngine::animation_26_2() {
pickObject(11);
removeObject(kItemBook);
- if (_lang == kSpanish)
- textSurface = extraSurface;
-
flags[11] = 0;
flags[39] = 1;
loadPic(974, extraSurface);
@@ -2215,23 +1773,9 @@ void DrasculaEngine::animation_26_2() {
}
void DrasculaEngine::animation_11_2() {
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an11y13.alg", extraSurface);
- talk(352);
- talk_bartender(1);
- talk(353);
- talk_bartender(17);
- talk(354);
- talk_bartender(18);
- talk(355);
- pause(40);
- talk_bartender(82);
-
- if (_lang == kSpanish)
- textSurface = extraSurface;
+ playTalkSequence(11); // sequence 11, chapter 2
loadPic(974, extraSurface);
}
@@ -2240,47 +1784,12 @@ void DrasculaEngine::animation_13_2() {
loadPic("an11y13.alg", frontSurface);
if (flags[41] == 0) {
- talk(103);
- talk_drunk(4);
- flags[12] = 1;
- talk(367);
- talk_drunk(5);
- flags[12] = 1;
- talk(368);
- talk_drunk(6);
- talk_drunk(7);
- flags[41] = 1;
+ playTalkSequence(13); // sequence 13, chapter 2
}
- converse(2);
loadPic(964, frontSurface);
}
-void DrasculaEngine::animation_18_2() {
- talk(378);
- talk_vonBraunpuerta(4);
- converse(3);
-}
-
-void DrasculaEngine::animation_22_2() {
- talk(374);
-
- trackProtagonist=2;
- updateRoom();
- updateScreen();
- playSound(13);
- finishSound();
- trackProtagonist = 1;
-
- talk_vonBraunpuerta(1);
- talk(375);
- talk_vonBraunpuerta(2);
- talk(376);
- talk_vonBraunpuerta(3);
-
- flags[18] = 1;
-}
-
void DrasculaEngine::animation_24_2() {
if (curX < 178)
gotoObject(208, 136);
@@ -2297,7 +1806,7 @@ void DrasculaEngine::animation_24_2() {
flags[21] = 1;
- talk_vonBraun(22);
+ talk_vonBraun(22, kVonBraunNormal);
if (flags[22] == 0)
converse(4);
@@ -2360,9 +1869,6 @@ void DrasculaEngine::animation_34_2() {
}
void DrasculaEngine::animation_36_2() {
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
loadPic("an11y13.alg", extraSurface);
talk(404);
@@ -2373,9 +1879,6 @@ void DrasculaEngine::animation_36_2() {
pause(40);
talk_bartender(82);
- if (_lang == kSpanish)
- textSurface = extraSurface;
-
loadPic(974, extraSurface);
}
@@ -2387,7 +1890,7 @@ void DrasculaEngine::animation_7_2() {
if (flags[3] == 1)
copyBackground(258, 110, 85, 44, 23, 53, drawSurface3, bgSurface);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
@@ -2467,17 +1970,14 @@ void DrasculaEngine::animation_5_2() {
loadPic("aux5.alg", drawSurface3);
flags[8] = 1;
curX = curX - 4;
- talk_sync(_text[_lang][46], "46.als", "4442444244244");
- withoutVerb();
+ talk_sync(_text[46], "46.als", "4442444244244");
+ selectVerb(0);
}
void DrasculaEngine::animation_6_2() {
stopMusic();
flags[9] = 1;
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
clearRoom();
loadPic("ciego1.alg", bgSurface, HALF_PAL); // ciego = blind
loadPic("ciego2.alg", drawSurface3);
@@ -2485,7 +1985,7 @@ void DrasculaEngine::animation_6_2() {
loadPic("ciego4.alg", backSurface);
loadPic("ciego5.alg", frontSurface);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
pause(1);
@@ -2497,7 +1997,7 @@ void DrasculaEngine::animation_6_2() {
pause(4);
talk_hacker(67);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
pause(10);
@@ -2510,10 +2010,7 @@ void DrasculaEngine::animation_6_2() {
loadPic(96, frontSurface);
loadPic(97, extraSurface);
loadPic(99, backSurface);
- withoutVerb();
-
- if (_lang == kSpanish)
- textSurface = extraSurface;
+ selectVerb(0);
flags[9] = 0;
}
@@ -2523,7 +2020,7 @@ void DrasculaEngine::animation_33_2() {
flags[9] = 1;
pause(12);
- talk(56);
+ talk(60);
pause(8);
clearRoom();
@@ -2533,10 +2030,7 @@ void DrasculaEngine::animation_33_2() {
loadPic("ciego4.alg", backSurface);
loadPic("ciego5.alg", frontSurface);
- if (_lang == kSpanish)
- textSurface = frontSurface;
-
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
pause(10);
@@ -2549,7 +2043,7 @@ void DrasculaEngine::animation_33_2() {
talk_blind(10);
talk_hacker(65);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
pause(14);
@@ -2562,10 +2056,7 @@ void DrasculaEngine::animation_33_2() {
loadPic(96, frontSurface);
loadPic(97, extraSurface);
loadPic(99, backSurface);
- withoutVerb();
-
- if (_lang == kSpanish)
- textSurface = extraSurface;
+ selectVerb(0);
flags[33] = 1;
flags[9] = 0;
@@ -2642,7 +2133,7 @@ void DrasculaEngine::animation_5_4(){
curY = 82;
updateRoom();
updateScreen();
- openDoor(2, 0);
+ toggleDoor(2, 0, kOpenDoor);
loadPic("auxigor.alg", frontSurface);
igorX = 100;
igorY = 65;
@@ -2663,7 +2154,7 @@ void DrasculaEngine::animation_6_4() {
loadPic(26, bgSurface, HALF_PAL);
loadPic("aux26.alg", drawSurface3);
loadPic("auxigor.alg", frontSurface);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
update_26_pre();
igorX = 104;
igorY = 71;
@@ -2676,7 +2167,7 @@ void DrasculaEngine::animation_6_4() {
loadPic(96, frontSurface);
loadPic(roomDisk, drawSurface3);
loadPic(roomNumber, bgSurface, HALF_PAL);
- withoutVerb();
+ selectVerb(0);
updateRoom();
}
@@ -2693,12 +2184,7 @@ void DrasculaEngine::animation_8_4() {
}
loadPic(96, frontSurface);
- openDoor(7, 2);
-}
-
-void DrasculaEngine::animation_9_4() {
- animate("st.bin", 14);
- fadeToBlack(1);
+ toggleDoor(7, 2, kOpenDoor);
}
void DrasculaEngine::activatePendulum() {
diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp
index 1c3831e4ca..cef1a17486 100644
--- a/engines/drascula/converse.cpp
+++ b/engines/drascula/converse.cpp
@@ -27,38 +27,128 @@
namespace Drascula {
+void DrasculaEngine::playTalkSequence(int sequence) {
+ bool seen = false;
+
+ for (int i = 0; i < _talkSequencesSize; i++) {
+ if (_talkSequences[i].chapter == currentChapter &&
+ _talkSequences[i].sequence == sequence) {
+ seen = true;
+
+ doTalkSequenceCommand(_talkSequences[i]);
+ } else if (seen) // Stop searching down the list
+ break;
+ }
+}
+
+void DrasculaEngine::doTalkSequenceCommand(TalkSequenceCommand cmd) {
+ switch (cmd.commandType) {
+ case kPause:
+ pause(cmd.action);
+ break;
+ case kSetFlag:
+ flags[cmd.action] = 1;
+ break;
+ case kClearFlag:
+ flags[cmd.action] = 0;
+ break;
+ case kPickObject:
+ pickObject(cmd.action);
+ break;
+ case kAddObject:
+ addObject(cmd.action);
+ break;
+ case kBreakOut:
+ breakOut = 1;
+ break;
+ case kConverse:
+ converse(cmd.action);
+ break;
+ case kPlaceVB:
+ placeVonBraun(cmd.action);
+ break;
+ case kUpdateRoom:
+ updateRoom();
+ break;
+ case kUpdateScreen:
+ updateScreen();
+ break;
+ case kTrackProtagonist:
+ trackProtagonist = cmd.action;
+ break;
+ case kPlaySound:
+ playSound(cmd.action);
+ break;
+ case kFinishSound:
+ finishSound();
+ break;
+ case kTalkerGeneral:
+ talk(cmd.action);
+ break;
+ case kTalkerDrunk:
+ talk_drunk(cmd.action);
+ break;
+ case kTalkerPianist:
+ talk_pianist(cmd.action);
+ break;
+ case kTalkerBJ:
+ talk_bj(cmd.action);
+ break;
+ case kTalkerVBNormal:
+ talk_vonBraun(cmd.action, kVonBraunNormal);
+ break;
+ case kTalkerVBDoor:
+ talk_vonBraun(cmd.action, kVonBraunDoor);
+ break;
+ case kTalkerIgorSeated:
+ talk_igor(cmd.action, kIgorSeated);
+ break;
+ case kTalkerWerewolf:
+ talk_werewolf(cmd.action);
+ break;
+ case kTalkerMus:
+ talk_mus(cmd.action);
+ break;
+ case kTalkerDrascula:
+ talk_drascula(cmd.action, 1);
+ break;
+ case kTalkerBartender0:
+ talk_bartender(cmd.action, 0);
+ break;
+ case kTalkerBartender1:
+ talk_bartender(cmd.action, 1);
+ break;
+ default:
+ error("doTalkSequenceCommand: Unknown command: %d", cmd.commandType);
+ }
+}
+
+void DrasculaEngine::cleanupString(char *string) {
+ uint len = strlen(string);
+ for (uint h = 0; h < len; h++)
+ if (string[h] == (char)0xa7)
+ string[h] = ' ';
+}
+
void DrasculaEngine::converse(int index) {
char fileName[20];
sprintf(fileName, "op_%d.cal", index);
- uint h;
- int game1 = 1, game2 = 1, game3 = 1, game4 = 1;
- char phrase1[78];
- char phrase2[78];
- char phrase3[87];
- char phrase4[78];
- char sound1[13];
- char sound2[13];
- char sound3[13];
- char sound4[13];
- int answer1;
- int answer2;
- int answer3;
- int used1 = 0;
- int used2 = 0;
- int used3 = 0;
+ _arj.open(fileName);
+ if (!_arj.isOpen())
+ error("missing data file %s", fileName);
+
+ int size = _arj.size();
+ int game1 = kDialogOptionUnselected,
+ game2 = kDialogOptionUnselected,
+ game3 = kDialogOptionUnselected;
+ char phrase1[78], phrase2[78], phrase3[78], phrase4[78];
+ char sound1[13], sound2[13], sound3[13], sound4[13];
+ int answer1, answer2, answer3;
char buffer[256];
- uint len;
breakOut = 0;
- if (currentChapter == 5)
- withoutVerb();
-
- _arj.open(fileName);
- if (!_arj.isOpen()) {
- error("missing data file %s", fileName);
- }
- int size = _arj.size();
+ selectVerb(0);
getStringFromLine(buffer, size, phrase1);
getStringFromLine(buffer, size, phrase2);
@@ -75,222 +165,131 @@ void DrasculaEngine::converse(int index) {
_arj.close();
if (currentChapter == 2 && !strcmp(fileName, "op_5.cal") && flags[38] == 1 && flags[33] == 1) {
- strcpy(phrase3, _text[_lang][405]);
+ strcpy(phrase3, _text[405]);
strcpy(sound3, "405.als");
answer3 = 31;
}
if (currentChapter == 6 && !strcmp(fileName, "op_12.cal") && flags[7] == 1) {
- strcpy(phrase3, _text[_lang][273]);
+ strcpy(phrase3, _text[273]);
strcpy(sound3, "273.als");
answer3 = 14;
}
if (currentChapter == 6 && !strcmp(fileName, "op_12.cal") && flags[10] == 1) {
- strcpy(phrase3, _text[_lang][274]);
+ strcpy(phrase3, _text[274]);
strcpy(sound3, "274.als");
answer3 = 15;
}
- len = strlen(phrase1);
- for (h = 0; h < len; h++)
- if (phrase1[h] == (char)0xa7)
- phrase1[h] = ' ';
-
- len = strlen(phrase2);
- for (h = 0; h < len; h++)
- if (phrase2[h] == (char)0xa7)
- phrase2[h] = ' ';
-
- len = strlen(phrase3);
- for (h = 0; h < len; h++)
- if (phrase3[h] == (char)0xa7)
- phrase3[h] = ' ';
-
- len = strlen(phrase4);
- for (h = 0; h < len; h++)
- if (phrase4[h] == (char)0xa7)
- phrase4[h] = ' ';
+ cleanupString(phrase1);
+ cleanupString(phrase2);
+ cleanupString(phrase3);
+ cleanupString(phrase4);
loadPic("car.alg", backSurface);
// TODO code here should limit y position for mouse in dialog menu,
- // but we can't implement this due lack backend functionality
+ // but we can't implement this as there is lack in backend functionality
// from 1(top) to 31
color_abc(kColorLightGreen);
while (breakOut == 0) {
updateRoom();
- if (currentChapter == 1 || currentChapter == 4 || currentChapter == 6) {
- if (musicStatus() == 0 && flags[11] == 0)
- playMusic(roomMusic);
- } else if (currentChapter == 2) {
- if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0)
- playMusic(roomMusic);
- } else if (currentChapter == 3 || currentChapter == 5) {
- if (musicStatus() == 0)
+ if (musicStatus() == 0 && roomMusic != 0) {
+ if (currentChapter == 3 || currentChapter == 5) {
playMusic(roomMusic);
+ } else { // chapters 1, 2, 4, 6
+ if (flags[11] == 0)
+ playMusic(roomMusic);
+ }
}
updateEvents();
+ print_abc_opc(phrase1, 2, game1);
+ print_abc_opc(phrase2, 10, game2);
+ print_abc_opc(phrase3, 18, game3);
+ print_abc_opc(phrase4, 26, kDialogOptionUnselected);
+
if (mouseY > 0 && mouseY < 9) {
- if (used1 == 1 && _color != kColorWhite)
+ if (game1 == kDialogOptionClicked && _color != kColorWhite)
color_abc(kColorWhite);
- else if (used1 == 0 && _color != kColorLightGreen)
+ else if (game1 != kDialogOptionClicked && _color != kColorLightGreen)
color_abc(kColorLightGreen);
+
+ print_abc_opc(phrase1, 2, kDialogOptionSelected);
+
+ if (leftMouseButton == 1) {
+ delay(100);
+ game1 = kDialogOptionClicked;
+ talk(phrase1, sound1);
+ response(answer1);
+ }
} else if (mouseY > 8 && mouseY < 17) {
- if (used2 == 1 && _color != kColorWhite)
+ if (game2 == kDialogOptionClicked && _color != kColorWhite)
color_abc(kColorWhite);
- else if (used2 == 0 && _color != kColorLightGreen)
+ else if (game2 != kDialogOptionClicked && _color != kColorLightGreen)
color_abc(kColorLightGreen);
+
+ print_abc_opc(phrase2, 10, kDialogOptionSelected);
+
+ if (leftMouseButton == 1) {
+ delay(100);
+ game2 = kDialogOptionClicked;
+ talk(phrase2, sound2);
+ response(answer2);
+ }
} else if (mouseY > 16 && mouseY < 25) {
- if (used3 == 1 && _color != kColorWhite)
+ if (game3 == kDialogOptionClicked && _color != kColorWhite)
color_abc(kColorWhite);
- else if (used3 == 0 && _color != kColorLightGreen)
+ else if (game3 != kDialogOptionClicked && _color != kColorLightGreen)
color_abc(kColorLightGreen);
- } else if (_color != kColorLightGreen)
- color_abc(kColorLightGreen);
- if (mouseY > 0 && mouseY < 9)
- game1 = 2;
- else if (mouseY > 8 && mouseY < 17)
- game2 = 2;
- else if (mouseY > 16 && mouseY < 25)
- game3 = 2;
- else if (mouseY > 24 && mouseY < 33)
- game4 = 2;
+ print_abc_opc(phrase3, 18, kDialogOptionSelected);
- print_abc_opc(phrase1, 1, 2, game1);
- print_abc_opc(phrase2, 1, 10, game2);
- print_abc_opc(phrase3, 1, 18, game3);
- print_abc_opc(phrase4, 1, 26, game4);
-
- updateScreen();
-
- if ((leftMouseButton == 1) && (game1 == 2)) {
- delay(100);
- used1 = 1;
- talk(phrase1, sound1);
- if (currentChapter == 3)
- grr();
- else
- response(answer1);
- } else if ((leftMouseButton == 1) && (game2 == 2)) {
- delay(100);
- used2 = 1;
- talk(phrase2, sound2);
- if (currentChapter == 3)
- grr();
- else
- response(answer2);
- } else if ((leftMouseButton == 1) && (game3 == 2)) {
- delay(100);
- used3 = 1;
- talk(phrase3, sound3);
- if (currentChapter == 3)
- grr();
- else
+ if (leftMouseButton == 1) {
+ delay(100);
+ game3 = kDialogOptionClicked;
+ talk(phrase3, sound3);
response(answer3);
- } else if ((leftMouseButton == 1) && (game4 == 2)) {
- delay(100);
- talk(phrase4, sound4);
- breakOut = 1;
- }
+ }
+ } else if (mouseY > 24 && mouseY < 33) {
+ print_abc_opc(phrase4, 26, kDialogOptionSelected);
- if (leftMouseButton == 1) {
- delay(100);
+ if (leftMouseButton == 1) {
+ delay(100);
+ talk(phrase4, sound4);
+ breakOut = 1;
+ }
+ } else if (_color != kColorLightGreen)
color_abc(kColorLightGreen);
- }
- game1 = (used1 == 0) ? 1 : 3;
- game2 = (used2 == 0) ? 1 : 3;
- game3 = (used3 == 0) ? 1 : 3;
- game4 = 1;
+ updateScreen();
} // while (breakOut == 0)
if (currentChapter == 2)
loadPic(menuBackground, backSurface);
else
loadPic(99, backSurface);
- if (currentChapter != 5)
- withoutVerb();
}
void DrasculaEngine::response(int function) {
- if (currentChapter == 1) {
- if (function >= 10 && function <= 12)
- talk_drunk(function - 9);
- } else if (currentChapter == 2) {
- if (function == 8)
- animation_8_2();
- else if (function == 9)
- animation_9_2();
- else if (function == 10)
- animation_10_2();
- else if (function == 15)
- animation_15_2();
- else if (function == 16)
+ playTalkSequence(function);
+
+ if (currentChapter == 2) {
+ if (function == 16)
animation_16_2();
- else if (function == 17)
- animation_17_2();
- else if (function == 19)
- animation_19_2();
else if (function == 20)
animation_20_2();
- else if (function == 21)
- animation_21_2();
else if (function == 23)
animation_23_2();
- else if (function == 28)
- animation_28_2();
else if (function == 29)
animation_29_2();
- else if (function == 30)
- animation_30_2();
else if (function == 31)
animation_31_2();
- } else if (currentChapter == 4) {
- if (function == 2)
- animation_2_4();
- else if (function == 3)
- animation_3_4();
- else if (function == 4)
- animation_4_4();
- } else if (currentChapter == 5) {
- if (function == 2)
- animation_2_5();
- else if (function == 3)
- animation_3_5();
- else if (function == 6)
- animation_6_5();
- else if (function == 7)
- animation_7_5();
- else if (function == 8)
- animation_8_5();
- else if (function == 15)
- animation_15_5();
- else if (function == 16)
- animation_16_5();
- else if (function == 17)
- animation_17_5();
- } else if (currentChapter == 6) {
- if (function == 2)
- animation_2_6();
- else if (function == 3)
- animation_3_6();
- else if (function == 4)
- animation_4_6();
- else if (function == 11)
- animation_11_6();
- else if (function == 12)
- animation_12_6();
- else if (function == 13)
- animation_13_6();
- else if (function == 14)
- animation_14_6();
- else if (function == 15)
- animation_15_6();
+ } else if (currentChapter == 3) {
+ grr();
}
}
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index 9832d58294..81c8d9a62a 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -218,7 +218,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
0,
{
{"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563},
- {"packet.005", 0, "f80e10e37000a2201eabf8dad82c7f64", 16184223},
+ {"packet.005", 0, "58caac54b891f5d7f335e710e45e5d29", 16209623},
{NULL, 0, NULL, 0}
},
Common::IT_ITA,
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index 2d24978f21..c1449ea2c9 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -65,7 +65,7 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam
if (cd_num >= 0)
_system->openCD(cd_num);
- _lang = 0;
+ _lang = kEnglish;
}
DrasculaEngine::~DrasculaEngine() {
@@ -86,6 +86,7 @@ DrasculaEngine::~DrasculaEngine() {
free(_roomPreUpdates);
free(_roomUpdates);
free(_roomActions);
+ free(_talkSequences);
freeTexts(_text);
freeTexts(_textd);
freeTexts(_textb);
@@ -112,23 +113,23 @@ int DrasculaEngine::init() {
switch (getLanguage()) {
case Common::EN_ANY:
- _lang = 0;
+ _lang = kEnglish;
break;
case Common::ES_ESP:
- _lang = 1;
+ _lang = kSpanish;
break;
case Common::DE_DEU:
- _lang = 2;
+ _lang = kGerman;
break;
case Common::FR_FRA:
- _lang = 3;
+ _lang = kFrench;
break;
case Common::IT_ITA:
- _lang = 4;
+ _lang = kItalian;
break;
default:
warning("Unknown game language. Falling back to English");
- _lang = 0;
+ _lang = kEnglish;
}
_charMap = 0;
@@ -179,7 +180,9 @@ int DrasculaEngine::init() {
int DrasculaEngine::go() {
currentChapter = 1; // values from 1 to 6 will start each part of game
- hay_que_load = 0;
+ loadedDifferentChapter = 0;
+
+ checkCD();
for (;;) {
int i;
@@ -199,7 +202,6 @@ int DrasculaEngine::go() {
talkHeight = TALK_HEIGHT; talkWidth = TALK_WIDTH;
hasAnswer = 0;
savedTime = 0;
- changeColor = 0;
breakOut = 0;
vonBraunX = 120; trackVonBraun = 1; vonBraunHasMoved = 0;
framesWithoutAction = 0;
@@ -221,50 +223,46 @@ int DrasculaEngine::go() {
withVoices = 0;
selectionMade = 0;
- if (currentChapter != 6)
- loadPic(95, tableSurface);
+ if (currentChapter != 3)
+ loadPic(96, frontSurface, COMPLETE_PAL);
if (currentChapter == 1) {
- loadPic(96, frontSurface, COMPLETE_PAL);
- loadPic(99, backSurface);
- loadPic(97, extraSurface);
} else if (currentChapter == 2) {
- loadPic(96, frontSurface, COMPLETE_PAL);
loadPic("pts.alg", drawSurface2);
} else if (currentChapter == 3) {
loadPic("aux13.alg", bgSurface, COMPLETE_PAL);
loadPic(96, frontSurface);
- loadPic(97, extraSurface);
- loadPic(99, backSurface);
} else if (currentChapter == 4) {
- loadPic(96, frontSurface, COMPLETE_PAL);
- if (hay_que_load == 0)
+ if (loadedDifferentChapter == 0)
animation_ray();
loadPic(96, frontSurface);
clearRoom();
- loadPic(99, backSurface);
- loadPic(97, extraSurface);
} else if (currentChapter == 5) {
- loadPic(96, frontSurface, COMPLETE_PAL);
- loadPic(97, extraSurface);
- loadPic(99, backSurface);
} else if (currentChapter == 6) {
igorX = 105, igorY = 85, trackIgor = 1;
drasculaX = 62, drasculaY = 99, trackDrascula = 1;
actorFrames[kFramePendulum] = 0;
flag_tv = 0;
+ }
- loadPic(96, frontSurface, COMPLETE_PAL);
+ loadPic(95, tableSurface);
+ for (i = 0; i < 25; i++)
+ memcpy(crosshairCursor + i * 40, tableSurface + 225 + (56 + i) * 320, 40);
+
+ if (_lang == kSpanish)
+ loadPic(974, tableSurface);
+
+ if (currentChapter != 2) {
loadPic(99, backSurface);
loadPic(97, extraSurface);
- loadPic(95, tableSurface);
}
+
memset(iconName, 0, sizeof(iconName));
for (i = 0; i < 6; i++)
- strcpy(iconName[i + 1], _textverbs[_lang][i]);
+ strcpy(iconName[i + 1], _textverbs[i]);
- assignDefaultPalette();
+ assignPalette(defaultPalette);
if (!runCurrentChapter()) {
endChapter();
break;
@@ -294,11 +292,6 @@ bool DrasculaEngine::runCurrentChapter() {
rightMouseButton = 0;
- if (_lang == kSpanish)
- textSurface = extraSurface;
- else
- textSurface = tableSurface;
-
previousMusic = -1;
if (currentChapter != 2) {
@@ -327,14 +320,14 @@ bool DrasculaEngine::runCurrentChapter() {
if (currentChapter == 1) {
pickObject(28);
- if (hay_que_load == 0)
+ if (loadedDifferentChapter == 0)
animation_1_1();
- withoutVerb();
+ selectVerb(0);
loadPic("2aux62.alg", drawSurface2);
trackProtagonist = 1;
objExit = 104;
- if (hay_que_load != 0) {
+ if (loadedDifferentChapter != 0) {
if (!loadGame(saveName)) {
return true;
}
@@ -348,7 +341,7 @@ bool DrasculaEngine::runCurrentChapter() {
addObject(kItemPhone);
trackProtagonist = 3;
objExit = 162;
- if (hay_que_load == 0)
+ if (loadedDifferentChapter == 0)
enterRoom(14);
else {
if (!loadGame(saveName)) {
@@ -366,7 +359,7 @@ bool DrasculaEngine::runCurrentChapter() {
flags[1] = 1;
trackProtagonist = 1;
objExit = 99;
- if (hay_que_load == 0)
+ if (loadedDifferentChapter == 0)
enterRoom(20);
else {
if (!loadGame(saveName)) {
@@ -380,7 +373,7 @@ bool DrasculaEngine::runCurrentChapter() {
addObject(kItemReefer2);
addObject(kItemOneCoin2);
objExit = 100;
- if (hay_que_load == 0) {
+ if (loadedDifferentChapter == 0) {
enterRoom(21);
trackProtagonist = 0;
curX = 235;
@@ -402,7 +395,7 @@ bool DrasculaEngine::runCurrentChapter() {
addObject(20);
trackProtagonist = 1;
objExit = 100;
- if (hay_que_load == 0) {
+ if (loadedDifferentChapter == 0) {
enterRoom(45);
} else {
if (!loadGame(saveName)) {
@@ -415,7 +408,7 @@ bool DrasculaEngine::runCurrentChapter() {
trackProtagonist = 1;
objExit = 104;
- if (hay_que_load == 0) {
+ if (loadedDifferentChapter == 0) {
enterRoom(58);
animation_1_6();
} else {
@@ -426,6 +419,8 @@ bool DrasculaEngine::runCurrentChapter() {
}
}
+ showCursor();
+
while (1) {
if (characterMoved == 0) {
stepX = STEP_X;
@@ -444,7 +439,8 @@ bool DrasculaEngine::runCurrentChapter() {
// made the character start walking off screen, as his actual position was
// different than the displayed one
if (roomNumber == 3 && (curX == 279) && (curY + curHeight == 101)) {
- animation_1_2();
+ gotoObject(178, 121);
+ gotoObject(169, 135);
} else if (roomNumber == 14 && (curX == 214) && (curY + curHeight == 121)) {
walkToObject = 1;
gotoObject(190, 130);
@@ -485,6 +481,7 @@ bool DrasculaEngine::runCurrentChapter() {
#else
if (rightMouseButton == 1 && menuScreen == 1) {
#endif
+ delay(100);
if (currentChapter == 2)
loadPic(menuBackground, backSurface);
else
@@ -502,8 +499,14 @@ bool DrasculaEngine::runCurrentChapter() {
} else {
#else
}
- if (rightMouseButton == 1 && menuScreen == 0) {
+
+ // Do not show the inventory screen in chapter 5, if the right mouse button is clicked
+ // while the plug (object 16) is held
+ // Fixes bug #2059621 - "DRASCULA: Plug bug"
+ if (rightMouseButton == 1 && menuScreen == 0 &&
+ !(currentChapter == 5 && pickedObject == 16)) {
#endif
+ delay(100);
characterMoved = 0;
if (trackProtagonist == 2)
trackProtagonist = 1;
@@ -519,12 +522,14 @@ bool DrasculaEngine::runCurrentChapter() {
#ifndef _WIN32_WCE
updateEvents();
#endif
- withoutVerb();
+ selectVerb(0);
}
if (leftMouseButton == 1 && menuBar == 1) {
+ delay(100);
selectVerbFromBar();
} else if (leftMouseButton == 1 && takeObject == 0) {
+ delay(100);
if (verify1())
return true;
} else if (leftMouseButton == 1 && takeObject == 1) {
@@ -553,15 +558,15 @@ bool DrasculaEngine::runCurrentChapter() {
if (!saveLoadScreen())
return true;
} else if (key == Common::KEYCODE_F8) {
- withoutVerb();
+ selectVerb(0);
} else if (key == Common::KEYCODE_v) {
withVoices = 1;
- print_abc(_textsys[_lang][2], 96, 86);
+ print_abc(_textsys[2], 96, 86);
updateScreen();
delay(1410);
} else if (key == Common::KEYCODE_t) {
withVoices = 0;
- print_abc(_textsys[_lang][3], 94, 86);
+ print_abc(_textsys[3], 94, 86);
updateScreen();
delay(1460);
} else if (key == Common::KEYCODE_ESCAPE) {
@@ -593,8 +598,10 @@ char *DrasculaEngine::getLine(char *buf, int len) {
for (;;) {
b = buf;
- while (!_arj.eos()) {
+ while (true) {
c = ~_arj.readByte();
+ if (_arj.eos()) break;
+
if (c == '\r')
continue;
if (c == '\n' || b - buf >= (len - 1))
@@ -702,14 +709,14 @@ void DrasculaEngine::updateEvents() {
Common::Event event;
Common::EventManager *eventMan = _system->getEventManager();
- AudioCD.updateCD();
+ updateMusic();
#ifdef _WIN32_WCE
if (eventMan->pollEvent(event)) {
#else
while (eventMan->pollEvent(event)) {
#endif
- switch (event.type) {
+ switch (event.type) {
case Common::EVENT_KEYDOWN:
_keyPressed = event.kbd;
break;
@@ -759,7 +766,6 @@ void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int w
float totalX, totalY;
int n, m;
float pixelX, pixelY;
- int pixelPos[6];
newWidth = (width * factor) / 100;
newHeight = (height * factor) / 100;
@@ -772,14 +778,8 @@ void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int w
for (n = 0; n < newHeight; n++) {
for (m = 0; m < newWidth; m++) {
- pixelPos[0] = (int)pixelX;
- pixelPos[1] = (int)pixelY;
- pixelPos[2] = xx2 + m;
- pixelPos[3] = yy2 + n;
- pixelPos[4] = 1;
- pixelPos[5] = 1;
-
- copyRectClip(pixelPos, dir_inicio, dir_fin);
+ copyRect((int)pixelX, (int)pixelY, xx2 + m, yy2 + n,
+ 1, 1, dir_inicio, dir_fin);
pixelX += totalX;
}
@@ -796,7 +796,7 @@ void DrasculaEngine::hipo_sin_nadie(int counter){
do {
counter--;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
if (currentChapter == 3)
updateScreen(0, 0, 0, y, 320, 200, screenSurface);
else
@@ -820,7 +820,7 @@ void DrasculaEngine::hipo_sin_nadie(int counter){
}
} while (counter > 0);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
}
@@ -965,6 +965,15 @@ bool DrasculaEngine::loadDrasculaDat() {
_roomActions[i].speechID = in.readSint16BE();
}
+ _talkSequencesSize = in.readUint16BE();
+ _talkSequences = (TalkSequenceCommand *)malloc(sizeof(TalkSequenceCommand) * _talkSequencesSize);
+ for (i = 0; i < _talkSequencesSize; i++) {
+ _talkSequences[i].chapter = in.readSint16BE();
+ _talkSequences[i].sequence = in.readSint16BE();
+ _talkSequences[i].commandType = in.readSint16BE();
+ _talkSequences[i].action = in.readSint16BE();
+ }
+
_numLangs = in.readUint16BE();
_text = loadTexts(in);
@@ -986,24 +995,22 @@ bool DrasculaEngine::loadDrasculaDat() {
return true;
}
-char ***DrasculaEngine::loadTexts(Common::File &in) {
+char **DrasculaEngine::loadTexts(Common::File &in) {
int numTexts = in.readUint16BE();
- char ***res;
+ char **res = (char **)malloc(sizeof(char *) * numTexts);
int entryLen;
- char *pos;
+ char *pos = 0;
int len;
- res = (char ***)malloc(sizeof(char *) * _numLangs);
-
for (int lang = 0; lang < _numLangs; lang++) {
entryLen = in.readUint16BE();
-
- res[lang] = (char **)malloc(sizeof(char *) * numTexts);
-
pos = (char *)malloc(entryLen);
- res[lang][0] = pos;
-
- in.read(res[lang][0], entryLen);
+ if (lang == _lang) {
+ res[0] = pos;
+ in.read(res[0], entryLen);
+ } else {
+ in.read(pos, entryLen);
+ }
pos += DATAALIGNMENT;
@@ -1013,23 +1020,19 @@ char ***DrasculaEngine::loadTexts(Common::File &in) {
len = READ_BE_UINT16(pos);
pos += 2 + len;
- res[lang][i] = pos;
+ if (lang == _lang)
+ res[i] = pos;
}
}
return res;
}
-void DrasculaEngine::freeTexts(char ***ptr) {
+void DrasculaEngine::freeTexts(char **ptr) {
if (!ptr)
return;
- for (int lang = 0; lang < _numLangs; lang++) {
- if (ptr[lang]) {
- free(ptr[lang][0]);
- free(ptr[lang]);
- }
- }
+ free(ptr[0]);
free(ptr);
}
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index 8bb73d8dd1..3b499f27a0 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -37,16 +37,13 @@
#include "common/keyboard.h"
#include "common/unarj.h"
-#include "sound/audiostream.h"
#include "sound/mixer.h"
-#include "sound/voc.h"
-#include "sound/audiocd.h"
#include "engines/engine.h"
namespace Drascula {
-#define DRASCULA_DAT_VER 2
+#define DRASCULA_DAT_VER 4
#define DATAALIGNMENT 4
enum DrasculaGameFeatures {
@@ -135,6 +132,11 @@ enum IgorTalkerTypes {
kIgorWig = 4
};
+enum VonBraunTalkerTypes {
+ kVonBraunNormal = 0,
+ kVonBraunDoor = 1
+};
+
enum AnimFrameTypes {
kFrameBlind = 0,
kFrameSnore = 1,
@@ -146,6 +148,64 @@ enum AnimFrameTypes {
kFramePendulum = 7
};
+enum DialogOptionStatus {
+ kDialogOptionUnselected = 1,
+ kDialogOptionSelected = 2,
+ kDialogOptionClicked = 3
+};
+
+enum TalkSequenceCommands {
+ kPause = 0,
+ kSetFlag = 1,
+ kClearFlag = 2,
+ kPickObject = 3,
+ kAddObject = 4,
+ kBreakOut = 5,
+ kConverse = 6,
+ kPlaceVB = 7,
+ kUpdateRoom = 8,
+ kUpdateScreen = 9,
+ kTrackProtagonist = 10,
+ kPlaySound = 11,
+ kFinishSound = 12,
+ kTalkerGeneral = 13,
+ kTalkerDrunk = 14,
+ kTalkerPianist = 15,
+ kTalkerBJ = 16,
+ kTalkerVBNormal = 17,
+ kTalkerVBDoor = 18,
+ kTalkerIgorSeated = 19,
+ kTalkerWerewolf = 20,
+ kTalkerMus = 21,
+ kTalkerDrascula = 22,
+ kTalkerBartender0 = 23,
+ kTalkerBartender1 = 24
+};
+
+enum CharacterDirections {
+ kDirectionUp = 0,
+ kDirectionDown = 1,
+ kDirectionLeft = 2,
+ kDirectionRight = 3
+};
+
+enum MouseCursors {
+ kCursorCrosshair = 0,
+ kCursorCurrentItem = 1
+};
+
+enum DoorActions {
+ kCloseDoor = 0,
+ kOpenDoor = 1
+};
+
+struct TalkSequenceCommand {
+ int chapter;
+ int sequence;
+ int commandType;
+ int action;
+};
+
#define TEXTD_START 68
struct DrasculaGameDescription;
@@ -248,13 +308,18 @@ public:
typedef signed char DacPalette256[256][3];
void setRGB(byte *pal, int plt);
- void assignDefaultPalette();
+ void assignPalette(DacPalette256 pal);
+ void setDefaultPalette(DacPalette256 pal);
void setPalette(byte *PalBuf);
void copyBackground(int xorg, int yorg, int xdes, int ydes, int width,
int height, byte *src, byte *dest);
+
+ void copyBackground() {
+ copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ }
+
void copyRect(int xorg, int yorg, int xdes, int ydes, int width,
int height, byte *src, byte *dest);
- void copyRectClip(int *Array, byte *src, byte *dest);
void updateScreen() {
updateScreen(0, 0, 0, 0, 320, 200, screenSurface);
}
@@ -275,6 +340,9 @@ public:
DacPalette256 brightPalette;
DacPalette256 darkPalette;
+ byte *crosshairCursor;
+ byte *mouseCursor;
+
// Graphics buffers/pointers
byte *VGA;
byte *bgSurface;
@@ -309,7 +377,7 @@ public:
int roomObjX[40], roomObjY[40], trackObj[40];
int inventoryObjects[43];
char _targetSurface[40][20];
- int _destX[40], _destY[40], trackCharacter_alkeva[40], alapuertakeva[40];
+ int _destX[40], _destY[40], trackCharacter_alkeva[40], roomExits[40];
int x1[40], y1[40], x2[40], y2[40];
int takeObject, pickedObject;
int withVoices;
@@ -321,7 +389,8 @@ public:
int flags[NUM_FLAGS];
int frame_y;
- int curX, curY, characterMoved, curDirection, trackProtagonist, num_frame, hare_se_ve;
+ int curX, curY, characterMoved, curDirection, trackProtagonist, num_frame;
+ int hare_se_ve; // TODO: what is this for?
int roomX, roomY, checkFlags;
int doBreak;
int stepX, stepY;
@@ -334,7 +403,6 @@ public:
int timeDiff, startTime;
int hasAnswer;
int savedTime;
- int changeColor;
int breakOut;
int vonBraunX, trackVonBraun, vonBraunHasMoved;
float newHeight, newWidth;
@@ -347,7 +415,7 @@ public:
int framesWithoutAction;
int term_int;
int currentChapter;
- int hay_que_load;
+ int loadedDifferentChapter;
char saveName[13];
int _color;
int musicStopped;
@@ -368,12 +436,9 @@ public:
void moveVonBraun();
void placeVonBraun(int pointX);
void hipo_sin_nadie(int counter);
- void openDoor(int nflag, int doorNum);
+ void toggleDoor(int nflag, int doorNum, int action);
void showMap();
- void setDarkPalette();
-
- void withoutVerb();
void enterRoom(int);
void clearRoom();
void gotoObject(int, int);
@@ -399,6 +464,7 @@ public:
void fadeToBlack(int fadeSpeed);
signed char adjustToVGA(signed char value);
void color_abc(int cl);
+ bool textFitsCentered(char *text, int x);
void centerText(const char *,int,int);
void playSound(int soundNum);
bool animate(const char *animation, int FPS);
@@ -408,7 +474,7 @@ public:
void placeDrascula();
void talkInit(const char *filename);
- bool isTalkFinished(int* length);
+ bool isTalkFinished();
void talk_igor(int, int);
void talk_drascula(int index, int talkerType = 0);
void talk_solo(const char *, const char *);
@@ -417,7 +483,7 @@ public:
void talk_bj_bed(int);
void talk_htel(int);
void talk_bj(int);
- void talk_baul(int);
+ void talk_trunk(int);
void talk(int);
void talk(const char *, const char *);
void talk_sync(const char *, const char *, const char *);
@@ -425,9 +491,8 @@ public:
void talk_pianist(int);
void talk_werewolf(int);
void talk_mus(int);
- void talk_dr_grande(int);
- void talk_vonBraun(int);
- void talk_vonBraunpuerta(int);
+ void talk_drascula_big(int);
+ void talk_vonBraun(int, int);
void talk_blind(int);
void talk_hacker(int);
void talk_generic(const char* said, const char* filename, int* faces, int faceCount, int* coords, byte* surface);
@@ -435,18 +500,14 @@ public:
void hiccup(int);
void finishSound();
void stopSound();
- void closeDoor(int nflag, int doorNum);
void playMusic(int p);
void stopMusic();
+ void updateMusic();
int musicStatus();
void updateRoom();
bool loadGame(const char *);
void updateDoor(int);
- void setDefaultPalette();
void setPaletteBase(int darkness);
- void assignBrightPalette();
- void assignDarkPalette();
- void setBrightPalette();
void updateVisible();
void startWalking();
void updateRefresh();
@@ -458,7 +519,10 @@ public:
bool exitRoom(int);
bool pickupObject();
bool checkAction(int);
- void setCursorTable();
+ void setCursor(int cursor);
+ void showCursor();
+ void hideCursor();
+ bool isCursorVisible();
void enterName();
bool soundIsActive();
void waitFrameSSN();
@@ -490,8 +554,11 @@ public:
bool checkMenuFlags();
void setupRoomsTable();
bool roomParse(int, int);
+ void cleanupString(char *string);
+ void playTalkSequence(int sequence);
+ void doTalkSequenceCommand(TalkSequenceCommand cmd);
void converse(int);
- void print_abc_opc(const char *, int, int, int);
+ void print_abc_opc(const char *, int, int);
void response(int);
void activatePendulum();
@@ -551,28 +618,17 @@ public:
void animation_3_1();
void animation_4_1();
//
- void animation_1_2();
void animation_2_2();
- void animation_3_2();
void animation_4_2();
void animation_5_2();
void animation_6_2();
void animation_7_2();
- void animation_8_2();
- void animation_9_2();
- void animation_10_2();
void animation_11_2();
void animation_12_2();
void animation_13_2();
void animation_14_2();
- void animation_15_2();
void animation_16_2();
- void animation_17_2();
- void animation_18_2();
- void animation_19_2();
void animation_20_2();
- void animation_21_2();
- void animation_22_2();
void animation_23_2();
void animation_23_joined();
void animation_23_joined2();
@@ -580,9 +636,7 @@ public:
void animation_25_2();
void animation_26_2();
void animation_27_2();
- void animation_28_2();
void animation_29_2();
- void animation_30_2();
void animation_31_2();
void animation_32_2();
void animation_33_2();
@@ -590,7 +644,6 @@ public:
void animation_35_2();
void animation_36_2();
//
- void animation_1_3();
void animation_2_3();
void animation_3_3();
void animation_4_3();
@@ -599,48 +652,22 @@ public:
void animation_ray();
//
void animation_1_4();
- void animation_2_4();
- void animation_3_4();
- void animation_4_4();
void animation_5_4();
void animation_6_4();
void animation_7_4();
void animation_8_4();
- void animation_9_4();
//
void animation_1_5();
- void animation_2_5();
- void animation_3_5();
- void animation_4_5();
void animation_5_5();
- void animation_6_5();
- void animation_7_5();
- void animation_8_5();
- void animation_9_5();
- void animation_10_5();
void animation_11_5();
void animation_12_5();
void animation_13_5();
void animation_14_5();
- void animation_15_5();
- void animation_16_5();
- void animation_17_5();
//
void animation_1_6();
- void animation_2_6();
- void animation_3_6();
- void animation_4_6();
void animation_5_6();
void animation_6_6();
- void animation_7_6();
void animation_9_6();
- void animation_10_6();
- void animation_11_6();
- void animation_12_6();
- void animation_13_6();
- void animation_14_6();
- void animation_15_6();
- void animation_18_6();
void animation_19_6();
void update_1_pre();
@@ -683,23 +710,24 @@ private:
int _roomPreUpdatesSize;
int _roomUpdatesSize;
int _roomActionsSize;
+ int _talkSequencesSize;
int _numLangs;
- char ***_text;
- char ***_textd;
- char ***_textb;
- char ***_textbj;
- char ***_texte;
- char ***_texti;
- char ***_textl;
- char ***_textp;
- char ***_textt;
- char ***_textvb;
- char ***_textsys;
- char ***_texthis;
- char ***_textverbs;
- char ***_textmisc;
- char ***_textd1;
+ char **_text;
+ char **_textd;
+ char **_textb;
+ char **_textbj;
+ char **_texte;
+ char **_texti;
+ char **_textl;
+ char **_textp;
+ char **_textt;
+ char **_textvb;
+ char **_textsys;
+ char **_texthis;
+ char **_textverbs;
+ char **_textmisc;
+ char **_textd1;
ItemLocation *_itemLocations;
int *_polX, *_polY;
int *_verbBarX;
@@ -709,9 +737,10 @@ private:
int *_pianistX, *_drunkX;
RoomUpdate *_roomPreUpdates, *_roomUpdates;
RoomTalkAction *_roomActions;
+ TalkSequenceCommand *_talkSequences;
- char ***loadTexts(Common::File &in);
- void freeTexts(char ***ptr);
+ char **loadTexts(Common::File &in);
+ void freeTexts(char **ptr);
};
} // End of namespace Drascula
diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 67993bfb6c..de35de5ab2 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -47,6 +47,10 @@ void DrasculaEngine::allocMemory() {
assert(tableSurface);
extraSurface = (byte *)malloc(64000);
assert(extraSurface);
+ crosshairCursor = (byte *)malloc(40 * 25);
+ assert(crosshairCursor);
+ mouseCursor = (byte *)malloc(OBJWIDTH * OBJHEIGHT);
+ assert(mouseCursor);
}
void DrasculaEngine::freeMemory() {
@@ -58,10 +62,12 @@ void DrasculaEngine::freeMemory() {
free(drawSurface3);
free(extraSurface);
free(frontSurface);
+ free(crosshairCursor);
+ free(mouseCursor);
}
void DrasculaEngine::moveCursor() {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
moveCharacters();
@@ -78,14 +84,6 @@ void DrasculaEngine::moveCursor() {
showMenu();
else if (menuBar == 1)
clearMenu();
-
- int cursorPos[6] = { 0, 0, mouseX - 20, mouseY - 17, OBJWIDTH, OBJHEIGHT };
- copyRectClip(cursorPos, drawSurface3, screenSurface);
-}
-
-void DrasculaEngine::setCursorTable() {
- int cursorPos[6] = { 225, 56, mouseX - 20, mouseY - 12, 40, 25 };
- copyRectClip(cursorPos, tableSurface, screenSurface);
}
void DrasculaEngine::loadPic(const char *NamePcc, byte *targetSurface, int colorCount) {
@@ -148,7 +146,15 @@ void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int
int height, byte *src, byte *dest) {
dest += xdes + ydes * 320;
src += xorg + yorg * 320;
+ /* Unoptimized code
for (int x = 0; x < height; x++) {
+ memcpy(dest + 320 * x, src + 320 * x, width);
+ } */
+
+ // A bit more optimized code, thanks to Fingolfin
+ // Uses 2 less registers and performs 2 less multiplications
+ int x = height;
+ while (x--) {
memcpy(dest, src, width);
dest += 320;
src += 320;
@@ -159,24 +165,7 @@ void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width,
int height, byte *src, byte *dest) {
int y, x;
- dest += xdes + ydes * 320;
- src += xorg + yorg * 320;
-
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- if (src[x + y * 320] != 255)
- dest[x + y * 320] = src[x + y * 320];
-}
-
-void DrasculaEngine::copyRectClip(int *Array, byte *src, byte *dest) {
- int y, x;
- int xorg = Array[0];
- int yorg = Array[1];
- int xdes = Array[2];
- int ydes = Array[3];
- int width = Array[4];
- int height = Array[5];
-
+ //
if (ydes < 0) {
yorg += -ydes;
height += ydes;
@@ -191,6 +180,7 @@ void DrasculaEngine::copyRectClip(int *Array, byte *src, byte *dest) {
width -= (xdes + width) - 320;
if ((ydes + height) > 199)
height -= (ydes + height) - 200;
+ //
dest += xdes + ydes * 320;
src += xorg + yorg * 320;
@@ -202,16 +192,7 @@ void DrasculaEngine::copyRectClip(int *Array, byte *src, byte *dest) {
}
void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) {
- byte *ptr = VGA;
-
- ptr += xdes + ydes * 320;
- buffer += xorg + yorg * 320;
- for (int x = 0; x < height; x++) {
- memcpy(ptr, buffer, width);
- ptr += 320;
- buffer += 320;
- }
-
+ copyBackground(xorg, yorg, xdes, ydes, width, height, buffer, VGA);
_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
_system->updateScreen();
}
@@ -229,22 +210,22 @@ void DrasculaEngine::print_abc(const char *said, int screenX, int screenY) {
letterX = _charMap[i].mappedChar;
switch (_charMap[i].charType) {
- case 0: // letters
- letterY = (_lang == kSpanish) ? 149 : 158;
- break;
- case 1: // signs
- letterY = (_lang == kSpanish) ? 160 : 169;
- break;
- case 2: // accented
- letterY = 180;
- break;
+ case 0: // letters
+ letterY = (_lang == kSpanish) ? 149 : 158;
+ break;
+ case 1: // signs
+ letterY = (_lang == kSpanish) ? 160 : 169;
+ break;
+ case 2: // accented
+ letterY = 180;
+ break;
} // switch
break;
} // if
} // for
- int textPos[6] = { letterX, letterY, screenX, screenY, CHAR_WIDTH, CHAR_HEIGHT };
- copyRectClip(textPos, textSurface, screenSurface);
+ copyRect(letterX, letterY, screenX, screenY,
+ CHAR_WIDTH, CHAR_HEIGHT, tableSurface, screenSurface);
screenX = screenX + CHAR_WIDTH;
if (screenX > 317) {
@@ -254,10 +235,12 @@ void DrasculaEngine::print_abc(const char *said, int screenX, int screenY) {
} // for
}
-void DrasculaEngine::print_abc_opc(const char *said, int screenX, int screenY, int game) {
+void DrasculaEngine::print_abc_opc(const char *said, int screenY, int game) {
int signY, letterY, letterX = 0;
uint len = strlen(said);
+ int screenX = 1;
+
for (uint h = 0; h < len; h++) {
if (game == 1) {
letterY = 6;
@@ -293,76 +276,70 @@ void DrasculaEngine::print_abc_opc(const char *said, int screenX, int screenY, i
} // if
} // for
- int textPos[6] = { letterX, letterY, screenX, screenY, CHAR_WIDTH_OPC, CHAR_HEIGHT_OPC };
- copyRectClip(textPos, backSurface, screenSurface);
+ copyRect(letterX, letterY, screenX, screenY,
+ CHAR_WIDTH_OPC, CHAR_HEIGHT_OPC, backSurface, screenSurface);
screenX = screenX + CHAR_WIDTH_OPC;
}
}
-void DrasculaEngine::centerText(const char *message, int textX, int textY) {
- char bb[200], m2[200], m1[200], mb[10][50];
- char m3[200];
- int h, fil, textX3, textX2, textX1, conta_f = 0, ya = 0;
-
- strcpy(m1, " ");
- strcpy(m2, " ");
- strcpy(m3, " ");
- strcpy(bb, " ");
-
- for (h = 0; h < 10; h++)
- strcpy(mb[h], " ");
-
- if (textX > 160)
- ya = 1;
-
- strcpy(m1, message);
- textX = CLIP<int>(textX, 60, 255);
-
- textX1 = textX;
-
- if (ya == 1)
- textX1 = 315 - textX;
-
- textX2 = (strlen(m1) / 2) * CHAR_WIDTH;
-
- while (true) {
- strcpy(bb, m1);
- scumm_strrev(bb);
-
- if (textX1 < textX2) {
- strcpy(m3, strrchr(m1, ' '));
- strcpy(m1, strstr(bb, " "));
- scumm_strrev(m1);
- m1[strlen(m1) - 1] = '\0';
- strcat(m3, m2);
- strcpy(m2, m3);
- };
-
- textX2 = (strlen(m1) / 2) * CHAR_WIDTH;
-
- if (textX1 < textX2)
- continue;
+bool DrasculaEngine::textFitsCentered(char *text, int x) {
+ int len = strlen(text);
+ int tmp = CLIP<int>(x - len * CHAR_WIDTH / 2, 60, 255);
+ return (tmp + len * CHAR_WIDTH) <= 320;
+}
- strcpy(mb[conta_f], m1);
+void DrasculaEngine::centerText(const char *message, int textX, int textY) {
+ char msg[200];
+ char messageLine[200];
+ char tmpMessageLine[200];
+ *messageLine = 0;
+ *tmpMessageLine = 0;
+ char *curWord;
+ int curLine = 0;
+ int x = 0;
+ // original starts printing 4 lines above textY
+ int y = CLIP<int>(textY - (4 * CHAR_HEIGHT), 0, 320);
- if (!strcmp(m2, ""))
- break;
+ strcpy(msg, message);
- scumm_strrev(m2);
- m2[strlen(m2) - 1] = '\0';
- scumm_strrev(m2);
- strcpy(m1, m2);
- strcpy(m2, "");
- conta_f++;
+ // If the message fits on screen as-is, just print it here
+ if (textFitsCentered(msg, textX)) {
+ x = CLIP<int>(textX - strlen(msg) * CHAR_WIDTH / 2, 60, 255);
+ print_abc(msg, x, y);
+ return;
}
- fil = textY - (((conta_f + 3) * CHAR_HEIGHT));
+ // Message doesn't fit on screen, split it
+
+ // Get a word from the message
+ curWord = strtok(msg, " ");
+ while (curWord != NULL) {
+ // Check if the word and the current line fit on screen
+ if (strlen(tmpMessageLine) > 0)
+ strcat(tmpMessageLine, " ");
+ strcat(tmpMessageLine, curWord);
+ if (textFitsCentered(tmpMessageLine, textX)) {
+ // Line fits, so add the word to the current message line
+ strcpy(messageLine, tmpMessageLine);
+ } else {
+ // Line doesn't fit, so show the current line on screen and
+ // create a new one
+ // If it goes off screen, print_abc will adjust it
+ x = CLIP<int>(textX - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255);
+ print_abc(messageLine, x, y + curLine * CHAR_HEIGHT);
+ strcpy(messageLine, curWord);
+ strcpy(tmpMessageLine, curWord);
+ curLine++;
+ }
+
+ // Get next word
+ curWord = strtok(NULL, " ");
- for (h = 0; h < conta_f + 1; h++) {
- textX3 = strlen(mb[h]) / 2;
- print_abc(mb[h], ((textX) - textX3 * CHAR_WIDTH) - 1, fil);
- fil = fil + CHAR_HEIGHT + 2;
+ if (curWord == NULL) {
+ x = CLIP<int>(textX - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255);
+ print_abc(messageLine, x, y + curLine * CHAR_HEIGHT);
+ }
}
}
@@ -375,6 +352,8 @@ void DrasculaEngine::screenSaver() {
int tempLine[320];
int tempRow[200];
+ hideCursor();
+
clearRoom();
loadPic("sv.alg", bgSurface, HALF_PAL);
@@ -463,6 +442,7 @@ void DrasculaEngine::screenSaver() {
free(ghost);
loadPic(roomNumber, bgSurface, HALF_PAL);
+ showCursor();
}
void DrasculaEngine::playFLI(const char *filefli, int vel) {
@@ -621,12 +601,11 @@ void DrasculaEngine::decodeRLE(byte* srcPtr, byte* dstPtr) {
pixel = *srcPtr++;
}
for (uint j = 0; j < repeat; j++) {
- curByte++;
- if (curByte > 64000) {
+ *dstPtr++ = pixel;
+ if (++curByte >= 64000) {
stopProcessing = true;
break;
}
- *dstPtr++ = pixel;
}
}
}
diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp
index ef1d1cc7a3..32f07fce73 100644
--- a/engines/drascula/interface.cpp
+++ b/engines/drascula/interface.cpp
@@ -24,9 +24,34 @@
*/
#include "drascula/drascula.h"
+#include "graphics/cursorman.h"
namespace Drascula {
+void DrasculaEngine::setCursor(int cursor) {
+ switch (cursor) {
+ case kCursorCrosshair:
+ CursorMan.replaceCursor((const byte *)crosshairCursor, 40, 25, 20, 17);
+ break;
+ case kCursorCurrentItem:
+ CursorMan.replaceCursor((const byte *)mouseCursor, OBJWIDTH, OBJHEIGHT, 20, 17);
+ default:
+ break;
+ }
+}
+
+void DrasculaEngine::showCursor() {
+ CursorMan.showMouse(true);
+}
+
+void DrasculaEngine::hideCursor() {
+ CursorMan.showMouse(false);
+}
+
+bool DrasculaEngine::isCursorVisible() {
+ return CursorMan.isVisible();
+}
+
void DrasculaEngine::selectVerbFromBar() {
for (int n = 0; n < 7; n++) {
if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1] && n > 0) {
@@ -36,7 +61,7 @@ void DrasculaEngine::selectVerbFromBar() {
}
// no verb selected
- withoutVerb();
+ selectVerb(0);
}
void DrasculaEngine::selectVerb(int verb) {
@@ -50,10 +75,17 @@ void DrasculaEngine::selectVerb(int verb) {
addObject(pickedObject);
}
- copyBackground(OBJWIDTH * verb, c, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3);
+ for (int i = 0; i < OBJHEIGHT; i++)
+ memcpy(mouseCursor + i * OBJWIDTH, backSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH);
+ setCursor(kCursorCurrentItem);
- takeObject = 1;
- pickedObject = verb;
+ if (verb > 0) {
+ takeObject = 1;
+ pickedObject = verb;
+ } else {
+ takeObject = 0;
+ hasName = 0;
+ }
}
bool DrasculaEngine::confirmExit() {
@@ -61,7 +93,7 @@ bool DrasculaEngine::confirmExit() {
color_abc(kColorRed);
updateRoom();
- centerText(_textsys[_lang][1], 160, 87);
+ centerText(_textsys[1], 160, 87);
updateScreen();
delay(100);
@@ -194,25 +226,4 @@ void DrasculaEngine::showMap() {
}
}
-void DrasculaEngine::grr() {
- int length = 30;
-
- color_abc(kColorDarkGreen);
-
- playFile("s10.als");
-
- updateRoom();
- copyBackground(253, 110, 150, 65, 20, 30, drawSurface3, screenSurface);
-
- if (withVoices == 0)
- centerText("groaaarrrrgghhhh!", 153, 65);
-
- updateScreen();
-
- while (!isTalkFinished(&length));
-
- updateRoom();
- updateScreen();
-}
-
} // End of namespace Drascula
diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp
index 01967d975d..c9c99aafa8 100644
--- a/engines/drascula/objects.cpp
+++ b/engines/drascula/objects.cpp
@@ -51,7 +51,9 @@ void DrasculaEngine::chooseObject(int object) {
if (takeObject == 1 && menuScreen == 0)
addObject(pickedObject);
}
- copyBackground(_x1d_menu[object], _y1d_menu[object], 0, 0, OBJWIDTH,OBJHEIGHT, backSurface, drawSurface3);
+ for (int i = 0; i < OBJHEIGHT; i++)
+ memcpy(mouseCursor + i * OBJWIDTH, backSurface + _x1d_menu[object] + (_y1d_menu[object] + i) * 320, OBJWIDTH);
+ setCursor(kCursorCurrentItem);
takeObject = 1;
pickedObject = object;
}
@@ -70,23 +72,10 @@ int DrasculaEngine::removeObject(int obj) {
return result;
}
-void DrasculaEngine::withoutVerb() {
- int c = (menuScreen == 1) ? 0 : 171;
-
- if (currentChapter == 5) {
- if (takeObject == 1 && pickedObject != 16)
- addObject(pickedObject);
- } else {
- if (takeObject == 1)
- addObject(pickedObject);
- }
- copyBackground(0, c, 0, 0, OBJWIDTH,OBJHEIGHT, backSurface, drawSurface3);
-
- takeObject = 0;
- hasName = 0;
-}
-
void DrasculaEngine::gotoObject(int pointX, int pointY) {
+ bool cursorVisible = isCursorVisible();
+ hideCursor();
+
if (currentChapter == 5 || currentChapter == 6) {
if (hare_se_ve == 0) {
curX = roomX;
@@ -113,6 +102,9 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) {
}
updateRoom();
updateScreen();
+
+ if (cursorVisible)
+ showCursor();
}
void DrasculaEngine::checkObjects() {
@@ -186,7 +178,7 @@ bool DrasculaEngine::pickupObject() {
}
updateEvents();
if (takeObject == 0)
- withoutVerb();
+ selectVerb(0);
return false;
}
@@ -256,7 +248,7 @@ void DrasculaEngine::updateVisible() {
if (roomNumber == 22 && flags[27] == 1)
visible[3] = 0;
if (roomNumber == 26 && flags[21] == 0)
- strcpy(objName[2], _textmisc[_lang][0]);
+ strcpy(objName[2], _textmisc[0]);
if (roomNumber == 26 && flags[18] == 1)
visible[2] = 0;
if (roomNumber == 26 && flags[12] == 1)
diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp
index 6a93f21e55..ba174c9237 100644
--- a/engines/drascula/palette.cpp
+++ b/engines/drascula/palette.cpp
@@ -27,6 +27,17 @@
namespace Drascula {
+const char colorTable[][3] = {
+ { 0, 0, 0 }, { 0x10, 0x3E, 0x28 },
+ { 0, 0, 0 }, // unused
+ { 0x16, 0x3F, 0x16 }, { 0x09, 0x3F, 0x12 },
+ { 0x3F, 0x3F, 0x15 },
+ { 0, 0, 0 }, // unused
+ { 0x38, 0, 0 }, { 0x3F, 0x27, 0x0B },
+ { 0x2A, 0, 0x2A }, { 0x30, 0x30, 0x30 },
+ { 98, 91, 100 }
+};
+
void DrasculaEngine::setRGB(byte *pal, int colorCount) {
int x, cnt = 0;
@@ -70,17 +81,6 @@ void DrasculaEngine::setPalette(byte *PalBuf) {
void DrasculaEngine::color_abc(int cl) {
_color = cl;
- char colorTable[][3] = {
- { 0, 0, 0 }, { 0x10, 0x3E, 0x28 },
- { 0, 0, 0 }, // unused
- { 0x16, 0x3F, 0x16 }, { 0x09, 0x3F, 0x12 },
- { 0x3F, 0x3F, 0x15 },
- { 0, 0, 0 }, // unused
- { 0x38, 0, 0 }, { 0x3F, 0x27, 0x0B },
- { 0x2A, 0, 0x2A }, { 0x30, 0x30, 0x30 },
- { 98, 91, 100 }
- };
-
for (int i = 0; i <= 2; i++)
gamePalette[254][i] = colorTable[cl][i];
@@ -127,64 +127,25 @@ void DrasculaEngine::fadeFromBlack(int fadeSpeed) {
}
}
-void DrasculaEngine::assignDefaultPalette() {
+void DrasculaEngine::assignPalette(DacPalette256 pal) {
int color, component;
for (color = 235; color < 253; color++)
for (component = 0; component < 3; component++)
- defaultPalette[color][component] = gamePalette[color][component];
-}
-
-void DrasculaEngine::assignBrightPalette() {
- int color, component;
-
- for (color = 235; color < 253; color++) {
- for (component = 0; component < 3; component++)
- brightPalette[color][component] = gamePalette[color][component];
- }
-}
-
-void DrasculaEngine::assignDarkPalette() {
- int color, component;
-
- for (color = 235; color < 253; color++) {
- for (component = 0; component < 3; component++)
- darkPalette[color][component] = gamePalette[color][component];
- }
+ pal[color][component] = gamePalette[color][component];
}
-void DrasculaEngine::setDefaultPalette() {
+void DrasculaEngine::setDefaultPalette(DacPalette256 pal) {
int color, component;
for (color = 235; color < 253; color++) {
for (component = 0; component < 3; component++) {
- gamePalette[color][component] = defaultPalette[color][component];
+ gamePalette[color][component] = pal[color][component];
}
}
setPalette((byte *)&gamePalette);
}
-void DrasculaEngine::setBrightPalette() {
- int color, component;
-
- for (color = 235; color < 253; color++) {
- for (component = 0; component < 3; component++)
- gamePalette[color][component] = brightPalette[color][component];
- }
-
- setPalette((byte *)&gamePalette);
-}
-
-void DrasculaEngine::setDarkPalette() {
- int color, component;
-
- for (color = 235; color < 253; color++ )
- for (component = 0; component < 3; component++)
- gamePalette[color][component] = darkPalette[color][component];
-
- setPalette((byte *)&gamePalette);
-}
-
void DrasculaEngine::setPaletteBase(int darkness) {
signed char fade;
unsigned int color, component;
diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp
index 37dddf4b7e..027685f56a 100644
--- a/engines/drascula/rooms.cpp
+++ b/engines/drascula/rooms.cpp
@@ -29,6 +29,24 @@
namespace Drascula {
+struct doorInfo {
+ int chapter;
+ int doorNum;
+ int flag;
+};
+
+doorInfo doors[] = {
+ { 2, 138, 0 }, { 2, 136, 8 },
+ { 2, 156, 16 }, { 2, 163, 17 },
+ { 2, 177, 15 }, { 2, 175, 40 },
+ { 2, 173, 36 }, { 4, 103, 0 },
+ { 4, 104, 1 }, { 4, 105, 1 },
+ { 4, 106, 2 }, { 4, 107, 2 },
+ { 4, 110, 6 }, { 4, 114, 4 },
+ { 4, 115, 4 }, { 4, 117, 5 },
+ { 4, 120, 8 }, { 4, 122, 7 }
+};
+
typedef bool (DrasculaEngine::*RoomParser)(int args);
struct DrasculaRoomParser {
@@ -184,9 +202,9 @@ bool DrasculaEngine::room_3(int fl) {
if (pickedObject == kVerbTalk && fl == 129) {
talk(23);
pause(6);
- talk_sync(_text[_lang][50], "50.als", "11111111111144432554433");
+ talk_sync(_text[50], "50.als", "11111111111144432554433");
} else if (pickedObject == kVerbTalk && fl == 133) {
- talk_sync(_text[_lang][322], "322.als", "13333334125433333333");
+ talk_sync(_text[322], "322.als", "13333334125433333333");
updateRoom();
updateScreen();
pause(25);
@@ -248,11 +266,11 @@ bool DrasculaEngine::room_6(int fl) {
talk(41);
talk(42);
} else if (pickedObject == kVerbOpen && fl == 138)
- openDoor(0, 1);
+ toggleDoor(0, 1, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 138)
- closeDoor(0, 1);
+ toggleDoor(0, 1, kCloseDoor);
else if (pickedObject == kVerbOpen && fl == 143 && flags[2] == 0) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
copyRect(228, 102, curX + 5, curY - 1, 47, 73, drawSurface3, screenSurface);
updateScreen();
@@ -263,7 +281,7 @@ bool DrasculaEngine::room_6(int fl) {
updateScreen();
finishSound();
} else if (pickedObject == kVerbClose && fl == 143 && flags[2] == 1) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
flags[2] = 0;
updateRefresh_pre();
copyRect(228, 102, curX + 5, curY - 1, 47, 73, drawSurface3, screenSurface);
@@ -274,7 +292,7 @@ bool DrasculaEngine::room_6(int fl) {
updateScreen();
finishSound();
} else if (pickedObject == kVerbOpen && fl == 139 && flags[1] == 0) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
copyRect(267, 1, curX - 14, curY - 2, 52, 73, drawSurface3, screenSurface);
updateScreen();
@@ -287,7 +305,7 @@ bool DrasculaEngine::room_6(int fl) {
updateScreen();
finishSound();
} else if (pickedObject == kVerbPick && fl == 140) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
copyRect(267, 1, curX - 14, curY - 2, 52, 73, drawSurface3, screenSurface);
updateScreen();
@@ -350,9 +368,9 @@ bool DrasculaEngine::room_9(int fl) {
bool DrasculaEngine::room_12(int fl) {
if (pickedObject == kVerbOpen && fl == 156)
- openDoor(16, 4);
+ toggleDoor(16, 4, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 156)
- closeDoor(16, 4);
+ toggleDoor(16, 4, kCloseDoor);
else
hasAnswer = 0;
@@ -365,11 +383,14 @@ bool DrasculaEngine::room_13(int fl) {
trackProtagonist = 3;
talk(412);
strcpy(objName[1], "yoda");
- } else if (pickedObject == kVerbTalk && fl == 51)
+ } else if (pickedObject == kVerbTalk && fl == 51) {
converse(7);
- else if (pickedObject == 19 && fl == 51)
- animation_1_3();
- else if (pickedObject == 9 && fl == 51) {
+ } else if (pickedObject == 19 && fl == 51) {
+ talk(413);
+ grr();
+ pause(50);
+ talk(414);
+ } else if (pickedObject == 9 && fl == 51) {
animation_2_3();
return true;
} else
@@ -404,10 +425,10 @@ bool DrasculaEngine::room_15(int fl) {
talk(336);
trackProtagonist = 3;
talk(337);
- talk_sync(_text[_lang][46], "46.als", "4442444244244");
+ talk_sync(_text[46], "46.als", "4442444244244");
trackProtagonist = 1;
} else if (pickedObject == 18 && fl == 188 && flags[26] == 0) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
copyRect(133, 135, curX + 6, curY, 39, 63, drawSurface3, screenSurface);
updateScreen();
playSound(8);
@@ -432,17 +453,17 @@ bool DrasculaEngine::room_15(int fl) {
bool DrasculaEngine::room_16(int fl) {
if (pickedObject == kVerbOpen && fl == 163)
- openDoor(17, 0);
+ toggleDoor(17, 0, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 163)
- closeDoor(17, 0);
+ toggleDoor(17, 0, kCloseDoor);
else if (pickedObject == kVerbTalk && fl == 183) {
talk(341);
pause(10);
- talk_sync(_text[_lang][50], "50.als", "11111111111144432554433");
+ talk_sync(_text[50], "50.als", "11111111111144432554433");
pause(3);
- talk_baul(83);
+ talk_trunk(83);
} else if (pickedObject == kVerbOpen && fl == 183) {
- openDoor(19, NO_DOOR);
+ toggleDoor(19, NO_DOOR, kOpenDoor);
if (flags[20] == 0) {
flags[20] = 1;
trackProtagonist = 3;
@@ -452,7 +473,7 @@ bool DrasculaEngine::room_16(int fl) {
pickObject(22);
}
} else if (pickedObject == kVerbClose && fl == 183)
- closeDoor(19, NO_DOOR);
+ toggleDoor(19, NO_DOOR, kCloseDoor);
else if (pickedObject == kVerbLook && fl == 187) {
talk(343);
trackProtagonist = 3;
@@ -470,16 +491,18 @@ bool DrasculaEngine::room_17(int fl) {
talk(35);
else if (pickedObject == kVerbTalk && fl == 177 && flags[18] == 0)
talk(6);
- else if (pickedObject == kVerbTalk && fl == 177 && flags[18] == 1)
- animation_18_2();
- else if (pickedObject == kVerbOpen && fl == 177 && flags[18] == 1)
+ else if (pickedObject == kVerbTalk && fl == 177 && flags[18] == 1) {
+ talk(378);
+ talk_vonBraun(4, kVonBraunDoor);
+ converse(3);
+ } else if (pickedObject == kVerbOpen && fl == 177 && flags[18] == 1)
talk(346);
else if (pickedObject == kVerbOpen && fl == 177 && flags[14] == 0 && flags[18] == 0)
- animation_22_2();
+ playTalkSequence(22); // sequence 22, chapter 2
else if (pickedObject == kVerbOpen && fl == 177 && flags[14] == 1)
- openDoor(15, 1);
+ toggleDoor(15, 1, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 177 && flags[14] == 1)
- closeDoor(15, 1);
+ toggleDoor(15, 1, kCloseDoor);
else if (pickedObject == 11 && fl == 50 && flags[22] == 0) {
talk(347);
flags[29] = 1;
@@ -497,7 +520,7 @@ bool DrasculaEngine::room_18(int fl) {
else if (pickedObject == kVerbTalk && fl == 55 && flags[36] == 1)
talk(109);
else if (pickedObject == kVerbPick && fl == 182) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
copyRect(44, 1, curX, curY, 41, 70, drawSurface2, screenSurface);
updateRefresh();
@@ -519,7 +542,7 @@ bool DrasculaEngine::room_18(int fl) {
trackProtagonist = 3;
updateRoom();
updateScreen();
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
copyRect(1, 1, curX - 1, curY + 3, 42, 67, drawSurface2, screenSurface);
updateRefresh();
@@ -539,19 +562,20 @@ bool DrasculaEngine::room_21(int fl) {
if (pickedObject == kVerbOpen && fl == 101 && flags[28] == 0)
talk(419);
else if (pickedObject == kVerbOpen && fl == 101 && flags[28] == 1)
- openDoor(0, 1);
+ toggleDoor(0, 1, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 101)
- closeDoor(0, 1);
+ toggleDoor(0, 1, kCloseDoor);
else if(pickedObject == kVerbPick && fl == 141) {
pickObject(19);
visible[2] = 0;
flags[10] = 1;
} else if(pickedObject == 7 && fl == 101) {
flags[28] = 1;
- openDoor(0, 1);
- withoutVerb();
+ toggleDoor(0, 1, kOpenDoor);
+ selectVerb(0);
} else if (pickedObject == 21 && fl == 179) {
- animation_9_4();
+ animate("st.bin", 14);
+ fadeToBlack(1);
return true;
} else
hasAnswer = 0;
@@ -570,7 +594,7 @@ bool DrasculaEngine::room_22(int fl) {
playSound(1);
hiccup(14);
finishSound();
- withoutVerb();
+ selectVerb(0);
removeObject(22);
updateVisible();
trackProtagonist = 3;
@@ -590,15 +614,15 @@ bool DrasculaEngine::room_22(int fl) {
bool DrasculaEngine::room_23(int fl) {
if (pickedObject == kVerbOpen && fl == 103) {
- openDoor(0, 0);
+ toggleDoor(0, 0, kOpenDoor);
updateVisible();
} else if(pickedObject == kVerbClose && fl == 103) {
- closeDoor(0, 0);
+ toggleDoor(0, 0, kCloseDoor);
updateVisible();
} else if(pickedObject == kVerbOpen && fl == 104)
- openDoor(1, 1);
+ toggleDoor(1, 1, kOpenDoor);
else if(pickedObject == kVerbClose && fl == 104)
- closeDoor(1, 1);
+ toggleDoor(1, 1, kCloseDoor);
else if(pickedObject == kVerbPick && fl == 142) {
pickObject(8);
visible[2] = 0;
@@ -615,13 +639,13 @@ bool DrasculaEngine::room_23(int fl) {
bool DrasculaEngine::room_24(int fl) {
if (pickedObject == kVerbOpen && fl == 105)
- openDoor(1, 0);
+ toggleDoor(1, 0, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 105)
- closeDoor(1, 0);
+ toggleDoor(1, 0, kCloseDoor);
else if (pickedObject == kVerbOpen && fl == 106)
- openDoor(2, 1);
+ toggleDoor(2, 1, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 106)
- closeDoor(2, 1);
+ toggleDoor(2, 1, kCloseDoor);
else
hasAnswer = 0;
@@ -630,11 +654,11 @@ bool DrasculaEngine::room_24(int fl) {
bool DrasculaEngine::room_26(int fl) {
if (pickedObject == kVerbOpen && fl == 107 && flags[30] == 0)
- openDoor(2, 0);
+ toggleDoor(2, 0, kOpenDoor);
else if (pickedObject == kVerbOpen && fl == 107 && flags[30] == 1)
talk(421);
else if (pickedObject == kVerbClose && fl == 107)
- closeDoor(2, 0);
+ toggleDoor(2, 0, kCloseDoor);
else if (pickedObject == 10 && fl == 50 && flags[18] == 1 && flags[12] == 1)
animation_5_4();
else if (pickedObject == 8 && fl == 50 && flags[18] == 1 && flags[12] == 1)
@@ -648,7 +672,7 @@ bool DrasculaEngine::room_26(int fl) {
pickObject(10);
visible[1] = 0;
flags[12] = 1;
- closeDoor(2, 0);
+ toggleDoor(2, 0, kCloseDoor);
trackProtagonist = 2;
talk_igor(27, kIgorDoor);
flags[30] = 1;
@@ -671,17 +695,17 @@ bool DrasculaEngine::room_26(int fl) {
bool DrasculaEngine::room_27(int fl) {
if (pickedObject == kVerbOpen && fl == 110)
- openDoor(6, 1);
+ toggleDoor(6, 1, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 110)
- closeDoor(6, 1);
+ toggleDoor(6, 1, kCloseDoor);
else if (pickedObject == kVerbOpen && fl == 116 && flags[23] == 0)
talk(419);
else if (pickedObject == kVerbOpen && fl == 116 && flags[23] == 1)
- openDoor(5, 3);
+ toggleDoor(5, 3, kOpenDoor);
else if (pickedObject == 17 && fl == 116) {
flags[23] = 1;
- openDoor(5,3);
- withoutVerb();
+ toggleDoor(5, 3, kOpenDoor);
+ selectVerb(0);
} else if (fl == 150)
talk(460);
else
@@ -692,9 +716,9 @@ bool DrasculaEngine::room_27(int fl) {
bool DrasculaEngine::room_29(int fl) {
if (pickedObject == kVerbOpen && fl == 114)
- openDoor(4, 1);
+ toggleDoor(4, 1, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 114)
- closeDoor(4, 1);
+ toggleDoor(4, 1, kCloseDoor);
else
hasAnswer = 0;
@@ -703,15 +727,15 @@ bool DrasculaEngine::room_29(int fl) {
bool DrasculaEngine::room_30(int fl) {
if (pickedObject == kVerbOpen && fl == 115)
- openDoor(4, 0);
+ toggleDoor(4, 0, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 115)
- closeDoor(4, 0);
+ toggleDoor(4, 0, kCloseDoor);
else if (pickedObject == kVerbOpen && fl == 144 && flags[19] == 0)
talk(422);
else if (pickedObject == kVerbOpen && fl == 144 && flags[19] == 1 && flags[22] == 1)
- openDoor(16, 1);
+ toggleDoor(16, 1, kOpenDoor);
else if (pickedObject == kVerbOpen && fl == 144 && flags[19] == 1 && flags[22] == 0) {
- openDoor(16, 1);
+ toggleDoor(16, 1, kOpenDoor);
talk(423);
flags[22] = 1;
pickObject(12);
@@ -720,7 +744,7 @@ bool DrasculaEngine::room_30(int fl) {
if (flags[18] == 1)
animation_6_4();
} else if (pickedObject == kVerbClose && fl == 144)
- closeDoor(16, 1);
+ toggleDoor(16, 1, kCloseDoor);
else if (pickedObject == 13 && fl == 144) {
talk(424);
flags[19] = 1;
@@ -736,9 +760,9 @@ bool DrasculaEngine::room_31(int fl) {
visible[1] = 0;
flags[13] = 1;
} else if (pickedObject == kVerbOpen && fl == 117)
- openDoor(5, 0);
+ toggleDoor(5, 0, kOpenDoor);
else if (pickedObject == kVerbClose && fl == 117)
- closeDoor(5, 0);
+ toggleDoor(5, 0, kCloseDoor);
else
hasAnswer = 0;
@@ -749,15 +773,15 @@ bool DrasculaEngine::room_34(int fl) {
if (pickedObject == kVerbMove && fl == 146)
animation_8_4();
else if (pickedObject == kVerbOpen && fl == 120 && flags[25] == 1)
- openDoor(8, 2);
+ toggleDoor(8, 2, kOpenDoor);
else if (pickedObject == kVerbOpen && fl == 120 && flags[25] == 0) {
- openDoor(8, 2);
+ toggleDoor(8, 2, kOpenDoor);
trackProtagonist = 3;
talk(425);
pickObject(14);
flags[25] = 1;
} else if (pickedObject == kVerbClose && fl == 120)
- closeDoor(8, 2);
+ toggleDoor(8, 2, kCloseDoor);
else
hasAnswer=0;
@@ -805,20 +829,27 @@ bool DrasculaEngine::room_53(int fl) {
if (pickedObject == kVerbPick && fl == 120) {
pickObject(16);
visible[3] = 0;
- } else if (pickedObject == kVerbMove && fl == 123)
+ } else if (pickedObject == kVerbMove && fl == 123) {
animation_11_5();
- else if (pickedObject == 12 && fl == 52)
- animation_10_5();
- else if (pickedObject == 15 && fl == 52)
- animation_9_5();
- else if (pickedObject == 16 && fl == 121) {
+ } else if (pickedObject == 12 && fl == 52) {
+ flags[3] = 1;
+ talk(401);
+ selectVerb(0);
+ removeObject(12);
+ } else if (pickedObject == 15 && fl == 52) {
+ flags[4] = 1;
+ talk(401);
+ selectVerb(0);
+ removeObject(15);
+ } else if (pickedObject == 16 && fl == 121) {
flags[2] = 1;
- withoutVerb();
+ selectVerb(0);
updateVisible();
+ pickedObject = kVerbMove;
} else if (pickedObject == 16) {
- talk(439);
- withoutVerb();
+ // Wall plug in chapter 5
visible[3] = 1;
+ hasAnswer = 0;
} else
hasAnswer = 0;
@@ -851,7 +882,7 @@ bool DrasculaEngine::room_54(int fl) {
} else if (pickedObject == 10 && fl == 119) {
pause(4);
talk(436);
- withoutVerb();
+ selectVerb(0);
removeObject(10);
} else
hasAnswer = 0;
@@ -886,10 +917,12 @@ bool DrasculaEngine::room_56(int fl) {
}
bool DrasculaEngine::room_58(int fl) {
- if (pickedObject == kVerbMove && fl == 103)
- animation_7_6();
- else
+ if (pickedObject == kVerbMove && fl == 103) {
+ flags[8] = 1;
+ updateVisible();
+ } else {
hasAnswer = 0;
+ }
return true;
}
@@ -933,19 +966,19 @@ bool DrasculaEngine::room_59(int fl) {
talk_htel(240);
color_abc(kColorBrown);
- talk_solo(_textvb[_lang][58], "VB58.als");
+ talk_solo(_textvb[58], "VB58.als");
talk_htel(241);
color_abc(kColorBrown);
- talk_solo(_textvb[_lang][59], "VB59.als");
+ talk_solo(_textvb[59], "VB59.als");
talk_htel(242);
color_abc(kColorBrown);
- talk_solo(_textvb[_lang][60], "VB60.als");
+ talk_solo(_textvb[60], "VB60.als");
talk_htel(196);
color_abc(kColorBrown);
- talk_solo(_textvb[_lang][61],"VB61.als");
+ talk_solo(_textvb[61],"VB61.als");
talk_htel(244);
color_abc(kColorBrown);
- talk_solo(_textvb[_lang][62], "VB62.als");
+ talk_solo(_textvb[62], "VB62.als");
clearRoom();
loadPic("aux59.alg", drawSurface3);
loadPic(96, frontSurface, COMPLETE_PAL);
@@ -953,7 +986,7 @@ bool DrasculaEngine::room_59(int fl) {
loadPic(59, bgSurface, HALF_PAL);
trackProtagonist = 3;
talk(245);
- withoutVerb();
+ selectVerb(0);
flags[11] = 1;
}
} else
@@ -963,17 +996,27 @@ bool DrasculaEngine::room_59(int fl) {
}
bool DrasculaEngine::room_60(int fl) {
- if (pickedObject == kVerbMove && fl == 112)
- animation_10_6();
- else if (pickedObject == kVerbTalk && fl == 52) {
+ if (pickedObject == kVerbMove && fl == 112) {
+ playSound(14);
+ copyBackground();
+ updateRefresh_pre();
+ copyBackground(164, 85, 155, 48, 113, 114, drawSurface3, screenSurface);
+ updateScreen();
+ finishSound();
+ talk_bartender(23, 1);
+ flags[7] = 1;
+ } else if (pickedObject == kVerbTalk && fl == 52) {
talk(266);
talk_bartender(1, 1);
converse(12);
- withoutVerb();
+ selectVerb(0);
pickedObject = 0;
- } else if (pickedObject == 21 && fl == 56)
- animation_18_6();
- else if (pickedObject == 9 && fl == 56 && flags[6] == 1) {
+ } else if (pickedObject == 21 && fl == 56) {
+ flags[6] = 1;
+ selectVerb(0);
+ removeObject(21);
+ animate("beb.bin", 10);
+ } else if (pickedObject == 9 && fl == 56 && flags[6] == 1) {
animation_9_6();
return true;
} else if (pickedObject == 9 && fl == 56 && flags[6] == 0) {
@@ -1089,11 +1132,9 @@ void DrasculaEngine::updateRefresh_pre() {
void DrasculaEngine::update_1_pre() {
if (curX > 98 && curX < 153) {
- changeColor = 1;
- setDarkPalette();
+ setDefaultPalette(darkPalette);
} else {
- changeColor = 0;
- setBrightPalette();
+ setDefaultPalette(brightPalette);
}
if (flags[8] == 0)
@@ -1101,8 +1142,8 @@ void DrasculaEngine::update_1_pre() {
}
void DrasculaEngine::update_2() {
- int batPos[6];
int difference;
+ int w, h;
int batX[] = {0, 38, 76, 114, 152, 190, 228, 266,
0, 38, 76, 114, 152, 190, 228, 266,
0, 38, 76, 114, 152, 190,
@@ -1122,24 +1163,19 @@ void DrasculaEngine::update_2() {
if (actorFrames[kFrameBat] == 41)
actorFrames[kFrameBat] = 0;
- batPos[0] = batX[actorFrames[kFrameBat]];
- batPos[1] = batY[actorFrames[kFrameBat]];
-
if (actorFrames[kFrameBat] < 22) {
- batPos[4] = 37;
- batPos[5] = 21;
+ w = 37;
+ h = 21;
} else if (actorFrames[kFrameBat] > 27) {
- batPos[4] = 57;
- batPos[5] = 36;
+ w = 57;
+ h = 36;
} else {
- batPos[4] = 47;
- batPos[5] = 22;
+ w = 47;
+ h = 22;
}
- batPos[2] = 239;
- batPos[3] = 19;
-
- copyRectClip(batPos, drawSurface3, screenSurface);
+ copyRect(batX[actorFrames[kFrameBat]], batY[actorFrames[kFrameBat]],
+ 239, 19, w, h, drawSurface3, screenSurface);
difference = getTime() - savedTime;
if (difference >= 6) {
actorFrames[kFrameBat]++;
@@ -1158,22 +1194,18 @@ void DrasculaEngine::update_3() {
void DrasculaEngine::update_4() {
if (curX > 190) {
- changeColor = 1;
- setDarkPalette();
+ setDefaultPalette(darkPalette);
} else {
- changeColor = 0;
- setBrightPalette();
+ setDefaultPalette(brightPalette);
}
}
void DrasculaEngine::update_6_pre() {
if ((curX > 149 && curY + curHeight > 160 && curX < 220 && curY + curHeight < 188) ||
(curX > 75 && curY + curHeight > 183 && curX < 145)) {
- changeColor = 0;
- setBrightPalette();
+ setDefaultPalette(brightPalette);
} else {
- changeColor = 1;
- setDarkPalette();
+ setDefaultPalette(darkPalette);
}
}
@@ -1463,6 +1495,7 @@ void DrasculaEngine::update_102() {
}
bool DrasculaEngine::checkAction(int fl) {
+ hideCursor();
characterMoved = 0;
updateRoom();
updateScreen();
@@ -1481,7 +1514,7 @@ bool DrasculaEngine::checkAction(int fl) {
|| (pickedObject == kVerbOpen && fl == 22 && flags[23] == 0)) {
talk(164);
flags[23] = 1;
- withoutVerb();
+ selectVerb(0);
addObject(kItemMoney);
addObject(kItemTwoCoins);
} else if (pickedObject == kVerbLook && fl == 22 && flags[23] == 1)
@@ -1492,7 +1525,7 @@ bool DrasculaEngine::checkAction(int fl) {
hasAnswer = 0;
} else if (currentChapter == 4) {
if ((pickedObject == 18 && fl == 19) || (pickedObject == 19 && fl == 18)) {
- withoutVerb();
+ selectVerb(0);
chooseObject(21);
removeObject(18);
removeObject(19);
@@ -1504,13 +1537,7 @@ bool DrasculaEngine::checkAction(int fl) {
talk(495);
} else
hasAnswer = 0;
- } else if (currentChapter == 5) {
- if (pickedObject == kVerbLook && fl == 9) {
- talk(482);
- talk(483);
- } else
- hasAnswer = 0;
- } else if (currentChapter == 6) {
+ } else if (currentChapter == 5 || currentChapter == 6) {
if (pickedObject == kVerbLook && fl == 9) {
talk(482);
talk(483);
@@ -1528,8 +1555,10 @@ bool DrasculaEngine::checkAction(int fl) {
hasAnswer = 0;
} else if (currentChapter == 3) {
if (roomNumber == 13) {
- if (room(13, fl))
+ if (room(13, fl)) {
+ showCursor();
return true;
+ }
} else
hasAnswer = 0;
} else if (currentChapter == 4) {
@@ -1540,14 +1569,18 @@ bool DrasculaEngine::checkAction(int fl) {
else if (pickedObject == 12 && fl == 50 && flags[18] == 0)
talk(487);
else if (roomNumber == 21) {
- if (room(21, fl))
+ if (room(21, fl)) {
+ showCursor();
return true;
+ }
} else
hasAnswer = 0;
} else if (currentChapter == 5) {
if (roomNumber == 56) {
- if (room(56, fl))
+ if (room(56, fl)) {
+ showCursor();
return true;
+ }
} else
hasAnswer = 0;
} else if (currentChapter == 6) {
@@ -1558,8 +1591,10 @@ bool DrasculaEngine::checkAction(int fl) {
else if (roomNumber == 102)
room(102, fl);
else if (roomNumber == 60) {
- if (room(60, fl))
+ if (room(60, fl)) {
+ showCursor();
return true;
+ }
}
else
hasAnswer = 0;
@@ -1575,6 +1610,7 @@ bool DrasculaEngine::checkAction(int fl) {
if (hasAnswer == 0 && (hasName == 1 || menuScreen == 1))
room(0, -1);
+ showCursor();
return false;
}
@@ -1600,6 +1636,7 @@ bool DrasculaEngine::room(int rN, int fl) {
void DrasculaEngine::enterRoom(int roomIndex) {
debug(2, "Entering room %d", roomIndex);
+ showCursor();
char fileName[20];
sprintf(fileName, "%d.ald", roomIndex);
@@ -1661,7 +1698,7 @@ void DrasculaEngine::enterRoom(int roomIndex) {
getIntFromLine(buffer, size, &_destX[l]);
getIntFromLine(buffer, size, &_destY[l]);
getIntFromLine(buffer, size, &trackCharacter_alkeva[l]);
- getIntFromLine(buffer, size, &alapuertakeva[l]);
+ getIntFromLine(buffer, size, &roomExits[l]);
updateDoor(l);
}
}
@@ -1716,16 +1753,15 @@ void DrasculaEngine::enterRoom(int roomIndex) {
copyBackground(0, 171, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3);
- setDefaultPalette();
+ setDefaultPalette(defaultPalette);
if (palLevel != 0)
setPaletteBase(palLevel);
- assignBrightPalette();
- setDefaultPalette();
+ assignPalette(brightPalette);
+ setDefaultPalette(defaultPalette);
setPaletteBase(palLevel + 2);
- assignDarkPalette();
+ assignPalette(darkPalette);
- setBrightPalette();
- changeColor = -1;
+ setDefaultPalette(brightPalette);
if (currentChapter == 2)
color_abc(kColorLightGreen);
@@ -1821,8 +1857,9 @@ void DrasculaEngine::enterRoom(int roomIndex) {
if (currentChapter == 5) {
if (roomNumber == 45)
hare_se_ve = 0;
- if (roomNumber == 49 && flags[7] == 0)
- animation_4_5();
+ if (roomNumber == 49 && flags[7] == 0) {
+ playTalkSequence(4); // sequence 4, chapter 5
+ }
}
updateRoom();
@@ -1830,7 +1867,7 @@ void DrasculaEngine::enterRoom(int roomIndex) {
void DrasculaEngine::clearRoom() {
memset(VGA, 0, 64000);
- _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ _system->clearScreen();
_system->updateScreen();
}
@@ -1839,49 +1876,50 @@ bool DrasculaEngine::exitRoom(int l) {
int roomNum = 0;
- if (currentChapter == 1) {
- if (objectNum[l] == 105 && flags[0] == 0)
- talk(442);
- else {
- updateDoor(l);
- if (isDoor[l] != 0) {
- gotoObject(roomObjX[l], roomObjY[l]);
- trackProtagonist = trackObj[l];
- updateRoom();
- updateScreen();
- characterMoved = 0;
- trackProtagonist = trackCharacter_alkeva[l];
- objExit = alapuertakeva[l];
- doBreak = 1;
- previousMusic = roomMusic;
-
- if (objectNum[l] == 105) {
- animation_2_1();
- return true;
- }
- clearRoom();
- sscanf(_targetSurface[l], "%d", &roomNum);
- curX = -1;
- enterRoom(roomNum);
- }
+ // Player can't exit the inn in chapter 1
+ if (currentChapter == 1 && objectNum[l] == 104) {
+ return false;
+ }
+
+ if (currentChapter == 1 && objectNum[l] == 105 && flags[0] == 0) {
+ talk(442);
+ return false;
+ }
+
+ updateDoor(l);
+ if (isDoor[l] != 0 &&
+ ((currentChapter != 3 && currentChapter != 5) || visible[l] == 1)) {
+
+ hideCursor();
+ gotoObject(roomObjX[l], roomObjY[l]);
+ if (currentChapter != 2) {
+ trackProtagonist = trackObj[l];
+ updateRoom();
+ updateScreen();
}
- } else if (currentChapter == 2) {
- updateDoor(l);
- if (isDoor[l] != 0) {
- gotoObject(roomObjX[l], roomObjY[l]);
- characterMoved = 0;
- trackProtagonist = trackCharacter_alkeva[l];
- objExit = alapuertakeva[l];
- doBreak = 1;
- previousMusic = roomMusic;
+ characterMoved = 0;
+ trackProtagonist = trackCharacter_alkeva[l];
+ objExit = roomExits[l];
+ doBreak = 1;
+ previousMusic = roomMusic;
+
+ // Object specific actions
+ if (currentChapter == 1 && objectNum[l] == 105) {
+ animation_2_1();
+ return true;
+ } else if (currentChapter == 2) {
if (objectNum[l] == 136)
animation_2_2();
- if (objectNum[l] == 124)
- animation_3_2();
+ if (objectNum[l] == 124) {
+ gotoObject(163, 106);
+ gotoObject(287, 101);
+ trackProtagonist = 0;
+ }
if (objectNum[l] == 173) {
animation_35_2();
return true;
- } if (objectNum[l] == 146 && flags[39] == 1) {
+ }
+ if (objectNum[l] == 146 && flags[39] == 1) {
flags[5] = 1;
flags[11] = 1;
}
@@ -1890,93 +1928,27 @@ bool DrasculaEngine::exitRoom(int l) {
removeObject(kItemEarWithEarPlug);
addObject(kItemEarplugs);
}
- clearRoom();
- sscanf(_targetSurface[l], "%d", &roomNum);
- curX =- 1;
- enterRoom(roomNum);
- }
- } else if (currentChapter == 3) {
- updateDoor(l);
- if (isDoor[l] != 0 && visible[l] == 1) {
- gotoObject(roomObjX[l], roomObjY[l]);
- trackProtagonist = trackObj[l];
- updateRoom();
- updateScreen();
- characterMoved = 0;
- trackProtagonist = trackCharacter_alkeva[l];
- objExit = alapuertakeva[l];
- doBreak = 1;
- previousMusic = roomMusic;
- clearRoom();
- sscanf(_targetSurface[l], "%d", &roomNum);
- curX =- 1;
- enterRoom(roomNum);
- }
- } else if (currentChapter == 4) {
- updateDoor(l);
- if (isDoor[l] != 0) {
- gotoObject(roomObjX[l], roomObjY[l]);
- trackProtagonist = trackObj[l];
- updateRoom();
- updateScreen();
- characterMoved = 0;
- trackProtagonist = trackCharacter_alkeva[l];
- objExit = alapuertakeva[l];
- doBreak = 1;
- previousMusic = roomMusic;
-
- if (objectNum[l] == 108)
- gotoObject(171, 78);
- clearRoom();
- sscanf(_targetSurface[l], "%d", &roomNum);
- curX = -1;
- enterRoom(roomNum);
+ } else if (currentChapter == 4 && objectNum[l] == 108) {
+ gotoObject(171, 78);
}
- } else if (currentChapter == 5) {
- updateDoor(l);
- if (isDoor[l] != 0 && visible[l] == 1) {
- gotoObject(roomObjX[l], roomObjY[l]);
- trackProtagonist = trackObj[l];
- updateRoom();
- updateScreen();
- characterMoved = 0;
- trackProtagonist = trackCharacter_alkeva[l];
- objExit = alapuertakeva[l];
- doBreak = 1;
- previousMusic = roomMusic;
+
+ if (currentChapter == 5)
hare_se_ve = 1;
- clearRoom();
- sscanf(_targetSurface[l], "%d", &roomNum);
- curX = -1;
- enterRoom(roomNum);
- }
- } else if (currentChapter == 6) {
- updateDoor(l);
- if (isDoor[l] != 0) {
- gotoObject(roomObjX[l], roomObjY[l]);
- trackProtagonist = trackObj[l];
- updateRoom();
- updateScreen();
- characterMoved = 0;
- trackProtagonist = trackCharacter_alkeva[l];
- objExit = alapuertakeva[l];
- doBreak = 1;
- previousMusic = roomMusic;
- clearRoom();
- sscanf(_targetSurface[l], "%d", &roomNum);
- curX = -1;
- enterRoom(roomNum);
- if (objExit == 105)
- animation_19_6();
- }
+ clearRoom();
+ sscanf(_targetSurface[l], "%d", &roomNum);
+ curX = -1;
+ enterRoom(roomNum);
+
+ if (currentChapter == 6 && objExit == 105)
+ animation_19_6();
}
return false;
}
void DrasculaEngine::updateRoom() {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
if (currentChapter == 3) {
if (flags[0] == 0)
@@ -1990,67 +1962,41 @@ void DrasculaEngine::updateRoom() {
}
void DrasculaEngine::updateDoor(int doorNum) {
- if (currentChapter == 1 || currentChapter == 3 || currentChapter == 5 || currentChapter == 6)
+ if (currentChapter != 2 && currentChapter != 4)
return;
- else if (currentChapter == 2) {
- if (objectNum[doorNum] == 138)
- isDoor[doorNum] = flags[0];
- else if (objectNum[doorNum] == 136)
- isDoor[doorNum] = flags[8];
- else if (objectNum[doorNum] == 156)
- isDoor[doorNum] = flags[16];
- else if (objectNum[doorNum] == 163)
- isDoor[doorNum] = flags[17];
- else if (objectNum[doorNum] == 177)
- isDoor[doorNum] = flags[15];
- else if (objectNum[doorNum] == 175)
- isDoor[doorNum] = flags[40];
- else if (objectNum[doorNum] == 173)
- isDoor[doorNum] = flags[36];
- } else if (currentChapter == 4) {
+
+ for (int i = 0; i < ARRAYSIZE(doors); i++) {
+ if (doors[i].chapter == currentChapter &&
+ objectNum[doorNum] == doors[i].doorNum) {
+ isDoor[doorNum] = flags[doors[i].flag];
+ return;
+ }
+ }
+
+ if (currentChapter == 4) {
if (objectNum[doorNum] == 101 && flags[0] == 0)
isDoor[doorNum] = 0;
else if (objectNum[doorNum] == 101 && flags[0] == 1 && flags[28] == 1)
isDoor[doorNum] = 1;
- else if (objectNum[doorNum] == 103)
- isDoor[doorNum] = flags[0];
- else if (objectNum[doorNum] == 104)
- isDoor[doorNum] = flags[1];
- else if (objectNum[doorNum] == 105)
- isDoor[doorNum] = flags[1];
- else if (objectNum[doorNum] == 106)
- isDoor[doorNum] = flags[2];
- else if (objectNum[doorNum] == 107)
- isDoor[doorNum] = flags[2];
- else if (objectNum[doorNum] == 110)
- isDoor[doorNum] = flags[6];
- else if (objectNum[doorNum] == 114)
- isDoor[doorNum] = flags[4];
- else if (objectNum[doorNum] == 115)
- isDoor[doorNum] = flags[4];
else if (objectNum[doorNum] == 116 && flags[5] == 0)
isDoor[doorNum] = 0;
else if (objectNum[doorNum] == 116 && flags[5] == 1 && flags[23] == 1)
isDoor[doorNum] = 1;
- else if (objectNum[doorNum] == 117)
- isDoor[doorNum] = flags[5];
- else if (objectNum[doorNum] == 120)
- isDoor[doorNum] = flags[8];
- else if (objectNum[doorNum] == 122)
- isDoor[doorNum] = flags[7];
}
}
-void DrasculaEngine::openDoor(int nflag, int doorNum) {
- if (flags[nflag] == 0) {
- if (currentChapter == 1 /*|| currentChapter == 4*/) {
- if (nflag != 7) {
- playSound(3);
- flags[nflag] = 1;
- }
- } else {
+void DrasculaEngine::toggleDoor(int nflag, int doorNum, int action) {
+ if ((flags[nflag] == 0 && action == kOpenDoor) ||
+ (flags[nflag] == 1 && action == kCloseDoor)) {
+ if (currentChapter == 1 && nflag == 7 && action == kOpenDoor)
+ return;
+
+ if (action == kOpenDoor) {
playSound(3);
flags[nflag] = 1;
+ } else {
+ playSound(4);
+ flags[nflag] = 0;
}
if (doorNum != NO_DOOR)
@@ -2058,20 +2004,7 @@ void DrasculaEngine::openDoor(int nflag, int doorNum) {
updateRoom();
updateScreen();
finishSound();
- withoutVerb();
- }
-}
-
-void DrasculaEngine::closeDoor(int nflag, int doorNum) {
- if (flags[nflag] == 1) {
- playSound(4);
- flags[nflag] = 0;
- if (doorNum != NO_DOOR)
- updateDoor(doorNum);
- updateRoom();
- updateScreen();
- finishSound();
- withoutVerb();
+ selectVerb(0);
}
}
diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp
index 6f88a58fbb..503d2ab639 100644
--- a/engines/drascula/saveload.cpp
+++ b/engines/drascula/saveload.cpp
@@ -50,7 +50,7 @@ bool DrasculaEngine::saveLoadScreen() {
}
}
for (n = 0; n < NUM_SAVES; n++)
- sav->readLine(names[n], 23);
+ sav->readLine_OLD(names[n], 23);
delete sav;
loadPic("savescr.alg", bgSurface, HALF_PAL);
@@ -60,16 +60,16 @@ bool DrasculaEngine::saveLoadScreen() {
select[0] = 0;
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+ setCursor(kCursorCrosshair);
for (;;) {
y = 27;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
for (n = 0; n < NUM_SAVES; n++) {
print_abc(names[n], 116, y);
y = y + 9;
}
print_abc(select, 117, 15);
- setCursorTable();
updateScreen();
y = 27;
@@ -172,6 +172,8 @@ bool DrasculaEngine::saveLoadScreen() {
delay(5);
}
+ selectVerb(0);
+
clearRoom();
loadPic(roomNumber, bgSurface, HALF_PAL);
selectionMade = 0;
@@ -198,7 +200,7 @@ bool DrasculaEngine::loadGame(const char *gameName) {
if (savedChapter != currentChapter) {
strcpy(saveName, gameName);
currentChapter = savedChapter - 1;
- hay_que_load = 1;
+ loadedDifferentChapter = 1;
return false;
}
sav->read(currentData, 20);
@@ -216,10 +218,10 @@ bool DrasculaEngine::loadGame(const char *gameName) {
takeObject = sav->readSint32LE();
pickedObject = sav->readSint32LE();
- hay_que_load = 0;
+ loadedDifferentChapter = 0;
sscanf(currentData, "%d.ald", &roomNum);
enterRoom(roomNum);
- withoutVerb();
+ selectVerb(0);
return true;
}
@@ -253,9 +255,6 @@ void DrasculaEngine::saveGame(char gameName[]) {
warning("Can't write file '%s'. (Disk full?)", gameName);
delete out;
-
- playSound(99);
- finishSound();
}
} // End of namespace Drascula
diff --git a/engines/drascula/sound.cpp b/engines/drascula/sound.cpp
index 2eb40e2e30..6a3d83cae6 100644
--- a/engines/drascula/sound.cpp
+++ b/engines/drascula/sound.cpp
@@ -23,6 +23,10 @@
*
*/
+#include "sound/mixer.h"
+#include "sound/voc.h"
+#include "sound/audiocd.h"
+
#include "drascula/drascula.h"
namespace Drascula {
@@ -37,9 +41,15 @@ void DrasculaEngine::updateVolume(Audio::Mixer::SoundType soundType, int prevVol
}
void DrasculaEngine::volumeControls() {
+ if (_lang == kSpanish)
+ loadPic(95, tableSurface);
+
copyRect(1, 56, 73, 63, 177, 97, tableSurface, screenSurface);
updateScreen(73, 63, 73, 63, 177, 97, screenSurface);
+ setCursor(kCursorCrosshair);
+ showCursor();
+
for (;;) {
int masterVolume = CLIP((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16), 0, 15);
int voiceVolume = CLIP((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16), 0, 15);
@@ -57,8 +67,6 @@ void DrasculaEngine::volumeControls() {
copyBackground(183, 56, 138, voiceVolumeY, 39, 2 + voiceVolume * 4, tableSurface, screenSurface);
copyBackground(183, 56, 194, musicVolumeY, 39, 2 + musicVolume * 4, tableSurface, screenSurface);
- setCursorTable();
-
updateScreen();
updateEvents();
@@ -84,6 +92,11 @@ void DrasculaEngine::volumeControls() {
}
+ if (_lang == kSpanish)
+ loadPic(974, tableSurface);
+
+ selectVerb(0);
+
updateEvents();
}
@@ -110,6 +123,10 @@ void DrasculaEngine::stopMusic() {
AudioCD.stop();
}
+void DrasculaEngine::updateMusic() {
+ AudioCD.updateCD();
+}
+
int DrasculaEngine::musicStatus() {
return AudioCD.isPlaying();
}
@@ -141,7 +158,18 @@ void DrasculaEngine::playFile(const char *fname) {
if (_arj.open(fname)) {
int soundSize = _arj.size();
byte *soundData = (byte *)malloc(soundSize);
- _arj.seek(32);
+
+ if (!(!strcmp(fname, "3.als") && soundSize == 145166 && _lang != kSpanish)) {
+ _arj.seek(32);
+ } else {
+ // WORKAROUND: File 3.als with English speech files has a big silence at
+ // its beginning and end. We seek past the silence at the beginning,
+ // and ignore the silence at the end
+ // Fixes bug #2111815 - "DRASCULA: Voice delayed"
+ _arj.seek(73959, SEEK_SET);
+ soundSize = 117158 - 73959;
+ }
+
_arj.read(soundData, soundSize);
_arj.close();
diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp
index a89c5ff734..7bf55b7c40 100644
--- a/engines/drascula/talk.cpp
+++ b/engines/drascula/talk.cpp
@@ -36,9 +36,8 @@ void DrasculaEngine::talkInit(const char *filename) {
playFile(filename);
}
-bool DrasculaEngine::isTalkFinished(int* length) {
- byte key = getScan();
- if (key != 0)
+bool DrasculaEngine::isTalkFinished() {
+ if (getScan() != 0)
stopSound();
if (soundIsActive())
return false;
@@ -55,13 +54,12 @@ bool DrasculaEngine::isTalkFinished(int* length) {
void DrasculaEngine::talk_igor(int index, int talkerType) {
char filename[20];
sprintf(filename, "I%i.als", index);
- const char *said = _texti[_lang][index];
+ const char *said = _texti[index];
int x_talk0[8] = { 56, 82, 108, 134, 160, 186, 212, 238 };
int x_talk1[8] = { 56, 86, 116, 146, 176, 206, 236, 266 };
int x_talk3[4] = { 80, 102, 124, 146 };
int x_talk4[4] = { 119, 158, 197, 236 };
int face = 0;
- int length = strlen(said);
color_abc(kColorWhite);
@@ -70,11 +68,11 @@ void DrasculaEngine::talk_igor(int index, int talkerType) {
do {
if (talkerType == kIgorDch || talkerType == kIgorFront) {
face = _rnd->getRandomNumber(7);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
} else if (talkerType == kIgorSeated || talkerType == kIgorWig) {
face = _rnd->getRandomNumber(3);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
}
@@ -119,7 +117,7 @@ void DrasculaEngine::talk_igor(int index, int talkerType) {
updateScreen();
pause(3);
}
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
if ((talkerType == kIgorFront && currentChapter == 6) ||
talkerType == kIgorDoor || talkerType == kIgorSeated || talkerType == kIgorWig) {
@@ -127,7 +125,7 @@ void DrasculaEngine::talk_igor(int index, int talkerType) {
}
if (talkerType == kIgorDch || (talkerType == kIgorFront && currentChapter == 1)) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
placeIgor();
placeDrascula();
}
@@ -136,12 +134,11 @@ void DrasculaEngine::talk_igor(int index, int talkerType) {
// Talker type 0: talk_dr_izq, 1: talk_dr_dch
void DrasculaEngine::talk_drascula(int index, int talkerType) {
- const char *said = _textd[_lang][index];
+ const char *said = _textd[index];
char filename[20];
sprintf(filename, "d%i.als", index);
int x_talk[8] = { 1, 40, 79, 118, 157, 196, 235, 274 };
int face;
- int length = strlen(said);
int offset = (talkerType == 0) ? 0 : 7;
int offset2 = (talkerType == 0) ? 90 : 58;
@@ -152,7 +149,7 @@ void DrasculaEngine::talk_drascula(int index, int talkerType) {
do {
face = _rnd->getRandomNumber(7);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
@@ -176,10 +173,10 @@ void DrasculaEngine::talk_drascula(int index, int talkerType) {
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
if (talkerType == 0)
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
if (talkerType == 1 && currentChapter == 6)
updateRoom();
@@ -193,8 +190,41 @@ void DrasculaEngine::talk_drascula(int index, int talkerType) {
updateScreen();
}
+void DrasculaEngine::talk_drascula_big(int index) {
+ char filename[20];
+ sprintf(filename, "d%i.als", index);
+ const char *said = _textd[index];
+ int x_talk[4] = {47, 93, 139, 185};
+ int face;
+ int l = 0;
+
+ color_abc(kColorRed);
+
+ talkInit(filename);
+
+ do {
+ face = _rnd->getRandomNumber(3);
+ copyBackground();
+ copyBackground(interf_x[l] + 24, interf_y[l], 0, 45, 39, 31, drawSurface2, screenSurface);
+ copyBackground(x_talk[face], 1, 171, 68, 45, 48, drawSurface2, screenSurface);
+ l++;
+ if (l == 7)
+ l = 0;
+
+ if (withVoices == 0)
+ centerText(said, 191, 69);
+
+ updateScreen();
+
+ pause(3);
+
+ byte key = getScan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ } while (!isTalkFinished());
+}
+
void DrasculaEngine::talk_solo(const char *said, const char *filename) {
- int length = strlen(said);
if (currentChapter == 1)
color_abc(color_solo);
@@ -204,7 +234,7 @@ void DrasculaEngine::talk_solo(const char *said, const char *filename) {
talkInit(filename);
if (currentChapter == 6)
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
do {
if (withVoices == 0) {
@@ -216,10 +246,10 @@ void DrasculaEngine::talk_solo(const char *said, const char *filename) {
centerText(said, 173, 92);
}
updateScreen();
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
if (currentChapter == 6) {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
}
}
@@ -231,15 +261,14 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) {
// Line 82 is a special case
if (index != 82)
- said = _textt[_lang][index];
+ said = _textt[index];
else {
sprintf(filename, "d%i.als", index);
- said = _textd[_lang][index];
+ said = _textd[index];
}
int x_talk[9] = { 1, 23, 45, 67, 89, 111, 133, 155, 177 };
int face;
- int length = strlen(said);
color_abc(kColorMaroon);
@@ -260,7 +289,7 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) {
face = _rnd->getRandomNumber(5);
}
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
@@ -277,7 +306,7 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) {
updateScreen();
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
updateRoom();
updateScreen();
@@ -286,10 +315,9 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) {
void DrasculaEngine::talk_bj(int index) {
char filename[20];
sprintf(filename, "BJ%i.als", index);
- const char *said = _textbj[_lang][index];
+ const char *said = _textbj[index];
int x_talk[5] = { 64, 92, 120, 148, 176 };
int face;
- int length = strlen(said);
color_abc(kColorWhite);
@@ -299,7 +327,7 @@ void DrasculaEngine::talk_bj(int index) {
if (currentChapter != 5) {
face = _rnd->getRandomNumber(4);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
@@ -325,7 +353,7 @@ void DrasculaEngine::talk_bj(int index) {
updateScreen();
}
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
updateRoom();
updateScreen();
@@ -334,7 +362,7 @@ void DrasculaEngine::talk_bj(int index) {
void DrasculaEngine::talk(int index) {
char name[20];
sprintf(name, "%i.als", index);
- talk(_text[_lang][index], name);
+ talk(_text[index], name);
}
void DrasculaEngine::talk(const char *said, const char *filename) {
@@ -344,7 +372,6 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
int y_mask_talk = 170;
int face;
- int length = strlen(said);
if (currentChapter == 6) {
if (flags[0] == 0 && roomNumber == 102) {
@@ -375,7 +402,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
do {
face = _rnd->getRandomNumber(5);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
if (currentChapter == 2)
@@ -442,7 +469,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
updateScreen();
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
updateRoom();
updateScreen();
@@ -456,7 +483,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) {
void DrasculaEngine::talk_pianist(int index) {
char filename[20];
sprintf(filename, "P%i.als", index);
- const char* said = _textp[_lang][index];
+ const char* said = _textp[index];
int x_talk[4] = { 97, 145, 193, 241 };
int coords[7] = { 139, 228, 112, 47, 60, 221, 128 };
@@ -467,7 +494,7 @@ void DrasculaEngine::talk_pianist(int index) {
void DrasculaEngine::talk_drunk(int index) {
char filename[20];
sprintf(filename, "B%i.als", index);
- const char *said = _textb[_lang][index];
+ const char *said = _textb[index];
int x_talk[8] = { 1, 21, 41, 61, 81, 101, 121, 141 };
int coords[7] = { 29, 177, 50, 19, 19, 181, 54 };
@@ -498,13 +525,15 @@ void DrasculaEngine::talk_drunk(int index) {
}
}
-void DrasculaEngine::talk_vonBraun(int index) {
+// talker types:
+// 0: kVonBraunNormal
+// 1: KVonBraunDoor
+void DrasculaEngine::talk_vonBraun(int index, int talkerType) {
char filename[20];
sprintf(filename, "VB%i.als", index);
- const char *said = _textvb[_lang][index];
+ const char *said = _textvb[index];
int x_talk[6] = {1, 27, 53, 79, 105, 131};
int face;
- int length = strlen(said);
color_abc(kColorBrown);
@@ -513,50 +542,33 @@ void DrasculaEngine::talk_vonBraun(int index) {
copyBackground(vonBraunX + 5, 64, OBJWIDTH + 1, 0, 25, 27, bgSurface, drawSurface3);
do {
- if (trackVonBraun == 1) {
- face = _rnd->getRandomNumber(5);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
-
- moveCharacters();
- moveVonBraun();
+ if (talkerType == kVonBraunNormal) {
+ if (trackVonBraun == 1) {
+ face = _rnd->getRandomNumber(5);
+ copyBackground();
- copyBackground(OBJWIDTH + 1, 0, vonBraunX + 5, 64, 25, 27, drawSurface3, screenSurface);
- copyRect(x_talk[face], 34, vonBraunX + 5, 64, 25, 27, frontSurface, screenSurface);
- updateRefresh();
- }
+ moveCharacters();
+ moveVonBraun();
- if (withVoices == 0)
- centerText(said, vonBraunX, 66);
-
- updateScreen();
-
- pause(3);
- } while (!isTalkFinished(&length));
-
- updateRoom();
- updateScreen();
- if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0)
- playMusic(roomMusic);
-}
-
-void DrasculaEngine::talk_vonBraunpuerta(int index) {
- char filename[20];
- sprintf(filename, "VB%i.als", index);
- const char *said = _textvb[_lang][index];
- int length = strlen(said);
-
- color_abc(kColorBrown);
+ copyBackground(OBJWIDTH + 1, 0, vonBraunX + 5, 64, 25, 27, drawSurface3, screenSurface);
+ copyRect(x_talk[face], 34, vonBraunX + 5, 64, 25, 27, frontSurface, screenSurface);
+ updateRefresh();
+ }
- talkInit(filename);
+ if (withVoices == 0)
+ centerText(said, vonBraunX, 66);
- do {
- updateRoom();
+ updateScreen();
+ pause(3);
+ } else {
+ updateRoom();
- if (withVoices == 0)
- centerText(said, 150, 80);
+ if (withVoices == 0)
+ centerText(said, 150, 80);
- updateScreen();
- } while (!isTalkFinished(&length));
+ updateScreen();
+ }
+ } while (!isTalkFinished());
updateRoom();
updateScreen();
@@ -570,60 +582,56 @@ void DrasculaEngine::talk_blind(int index) {
// voice files start from 58, not 1
char filename[20];
sprintf(filename, "d%i.als", index + TEXTD_START - 1);
- const char *said = _textd[_lang][index + TEXTD_START - 1];
- const char *syncChar = _textd1[_lang][index - 1];
+ const char *said = _textd[index + TEXTD_START - 1];
+ const char *syncChar = _textd1[index - 1];
- byte *faceBuffer;
int p = 0;
- int pos_blind[6] = { 0, 2, 73, 1, 126, 149 };
- int length = strlen(said);
+ int bX = 0;
+ int h = 149;
color_abc(kColorBrown);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
talkInit(filename);
do {
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
- pos_blind[5] = 149;
+ copyBackground();
+ h = 149;
char c = toupper(syncChar[p]);
if (c == '0' || c == '2' || c == '4' || c == '6')
- pos_blind[0] = 1;
+ bX = 1;
else
- pos_blind[0] = 132;
+ bX = 132;
if (c == '0' || c == '1')
- faceBuffer = drawSurface3;
+ copyRect(bX, 2, 73, 1, 126, h, drawSurface3, screenSurface);
else if (c == '2' || c == '3')
- faceBuffer = extraSurface;
+ copyRect(bX, 2, 73, 1, 126, h, extraSurface, screenSurface);
else if (c == '4' || c == '5')
- faceBuffer = backSurface;
+ copyRect(bX, 2, 73, 1, 126, h, backSurface, screenSurface);
else {
- faceBuffer = frontSurface;
- pos_blind[5] = 146;
+ h = 146;
+ copyRect(bX, 2, 73, 1, 126, h, frontSurface, screenSurface);
}
- copyRectClip( pos_blind, faceBuffer, screenSurface);
-
if (withVoices == 0)
- centerText(said, 310, 71);
+ centerText(said, 260, 71);
updateScreen();
pause(2);
p++;
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
}
void DrasculaEngine::talk_hacker(int index) {
char filename[20];
sprintf(filename, "d%i.als", index);
- const char *said = _textd[_lang][index];
- int length = strlen(said);
+ const char *said = _textd[index];
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
color_abc(kColorYellow);
@@ -634,13 +642,13 @@ void DrasculaEngine::talk_hacker(int index) {
if (withVoices == 0)
centerText(said, 156, 170);
updateScreen();
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
}
void DrasculaEngine::talk_werewolf(int index) {
char filename[20];
sprintf(filename, "L%i.als", index);
- const char *said = _textl[_lang][index];
+ const char *said = _textl[index];
int x_talk[9] = {52, 79, 106, 133, 160, 187, 214, 241, 268};
int coords[7] = { 136, 198, 81, 26, 24, 203, 78 };
@@ -651,7 +659,7 @@ void DrasculaEngine::talk_werewolf(int index) {
void DrasculaEngine::talk_mus(int index) {
char filename[20];
sprintf(filename, "E%i.als", index);
- const char *said = _texte[_lang][index];
+ const char *said = _texte[index];
int x_talk[8] = { 16, 35, 54, 73, 92, 111, 130, 149};
int coords[7] = { 156, 190, 64, 18, 24, 197, 64 };
@@ -663,7 +671,6 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker
int x_talk[8] = {112, 138, 164, 190, 216, 242, 268, 294};
int x_talk2[5] = {122, 148, 174, 200, 226};
int face;
- int length = strlen(said);
flags[1] = 1;
@@ -683,7 +690,7 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker
else
face = _rnd->getRandomNumber(4);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
if (talkerType == 0)
@@ -703,10 +710,10 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker
updateScreen();
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
flags[1] = 0;
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
updateScreen();
}
@@ -714,10 +721,9 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker
void DrasculaEngine::talk_bj_bed(int index) {
char filename[20];
sprintf(filename, "BJ%i.als", index);
- const char *said = _textbj[_lang][index];
+ const char *said = _textbj[index];
int x_talk[5] = {51, 101, 151, 201, 251};
int face;
- int length = strlen(said);
color_abc(kColorWhite);
@@ -726,7 +732,7 @@ void DrasculaEngine::talk_bj_bed(int index) {
do {
face = _rnd->getRandomNumber(4);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
@@ -741,7 +747,7 @@ void DrasculaEngine::talk_bj_bed(int index) {
updateScreen();
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
updateRoom();
updateScreen();
@@ -750,11 +756,9 @@ void DrasculaEngine::talk_bj_bed(int index) {
void DrasculaEngine::talk_htel(int index) {
char filename[20];
sprintf(filename, "%i.als", index);
- const char *said = _text[_lang][index];
- char *faceBuffer;
+ const char *said = _text[index];
int x_talk[3] = {1, 94, 187};
int face, curScreen;
- int length = strlen(said);
color_abc(kColorYellow);
@@ -764,25 +768,23 @@ void DrasculaEngine::talk_htel(int index) {
face = _rnd->getRandomNumber(2);
curScreen = _rnd->getRandomNumber(2);
+ copyBackground();
+
if (face == 0 && curScreen == 0)
- faceBuffer = (char *)drawSurface3;
+ copyBackground(x_talk[face], 1, 45, 24, 92, 108, drawSurface3, screenSurface);
else if (curScreen == 1)
- faceBuffer = (char *)frontSurface;
+ copyBackground(x_talk[face], 1, 45, 24, 92, 108, frontSurface, screenSurface);
else
- faceBuffer = (char *)backSurface;
-
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
-
- copyBackground(x_talk[face], 1, 45, 24, 92, 108, (byte *)faceBuffer, screenSurface);
-
+ copyBackground(x_talk[face], 1, 45, 24, 92, 108, backSurface, screenSurface);
+
if (withVoices == 0)
centerText(said, 90, 50);
updateScreen();
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateScreen();
}
@@ -790,7 +792,6 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha
int talkOffset = 1;
int y_mask_talk = 170;
int p, face = 0;
- int length = strlen(said);
char buf[2];
color_abc(kColorYellow);
@@ -808,7 +809,7 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha
strncpy(buf, &syncChar[p], 1);
face = atoi(buf);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
if (currentChapter == 2)
@@ -863,7 +864,7 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha
p++;
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
if (currentChapter == 1 && musicStatus() == 0 && flags[11] == 0)
playMusic(roomMusic);
@@ -871,12 +872,11 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha
playMusic(roomMusic);
}
-void DrasculaEngine::talk_baul(int index) {
+void DrasculaEngine::talk_trunk(int index) {
char filename[20];
sprintf(filename, "d%i.als", index);
- const char *said = _text[_lang][index];
+ const char *said = _text[index];
int face = 0, cara_antes;
- int length = strlen(said);
cara_antes = flags[19];
@@ -896,57 +896,21 @@ void DrasculaEngine::talk_baul(int index) {
updateScreen();
pause(4);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
flags[19] = cara_antes;
updateRoom();
updateScreen();
}
-void DrasculaEngine::talk_dr_grande(int index) {
- char filename[20];
- sprintf(filename, "D%i.als", index);
- const char *said = _textd[_lang][index];
- int x_talk[4] = {47, 93, 139, 185};
- int face;
- int l = 0;
- int length = strlen(said);
-
- color_abc(kColorRed);
-
- talkInit(filename);
-
- do {
- face = _rnd->getRandomNumber(3);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
- copyBackground(interf_x[l] + 24, interf_y[l], 0, 45, 39, 31, drawSurface2, screenSurface);
- copyBackground(x_talk[face], 1, 171, 68, 45, 48, drawSurface2, screenSurface);
- l++;
- if (l == 7)
- l = 0;
-
- if (withVoices == 0)
- centerText(said, 191, 69);
-
- updateScreen();
-
- pause(3);
-
- byte key = getScan();
- if (key == Common::KEYCODE_ESCAPE)
- term_int = 1;
- } while (!isTalkFinished(&length));
-}
-
void DrasculaEngine::talk_generic(const char* said, const char* filename, int* faces, int faceCount, int* coords, byte* surface) {
int face;
- int length = strlen(said);
talkInit(filename);
do {
face = _rnd->getRandomNumber(faceCount - 1);
- copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface);
+ copyBackground();
updateRefresh_pre();
copyBackground(faces[face], coords[0], coords[1], coords[2],
coords[3], coords[4], surface, screenSurface);
@@ -959,7 +923,27 @@ void DrasculaEngine::talk_generic(const char* said, const char* filename, int* f
updateScreen();
pause(3);
- } while (!isTalkFinished(&length));
+ } while (!isTalkFinished());
+
+ updateRoom();
+ updateScreen();
+}
+
+
+void DrasculaEngine::grr() {
+ color_abc(kColorDarkGreen);
+
+ playFile("s10.als");
+
+ updateRoom();
+ copyBackground(253, 110, 150, 65, 20, 30, drawSurface3, screenSurface);
+
+ if (withVoices == 0)
+ centerText("groaaarrrrgghhhh!", 153, 65);
+
+ updateScreen();
+
+ while (!isTalkFinished());
updateRoom();
updateScreen();
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 757a77f82b..1d3368b10d 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -36,7 +36,10 @@
#include "common/savefile.h"
#include "common/system.h"
#include "gui/message.h"
+#include "gui/newgui.h"
#include "sound/mixer.h"
+#include "engines/dialogs.h"
+#include "engines/metaengine.h"
#ifdef _WIN32_WCE
extern bool isSmartphone(void);
@@ -53,8 +56,9 @@ Engine::Engine(OSystem *syst)
_eventMan(_system->getEventManager()),
_saveFileMan(_system->getSavefileManager()),
_targetName(ConfMan.getActiveDomainName()),
- _gameDataPath(ConfMan.get("path")),
- _pauseLevel(0) {
+ _gameDataDir(ConfMan.get("path")),
+ _pauseLevel(0),
+ _mainMenuDialog(NULL) {
g_engine = this;
_autosavePeriod = ConfMan.getInt("autosave_period");
@@ -72,7 +76,8 @@ Engine::Engine(OSystem *syst)
Engine::~Engine() {
_mixer->stopAll();
-
+
+ delete _mainMenuDialog;
g_engine = NULL;
}
@@ -145,12 +150,12 @@ void Engine::checkCD() {
char buffer[MAXPATHLEN];
int i;
- if (strlen(_gameDataPath.c_str()) == 0) {
+ if (_gameDataDir.getPath().empty()) {
// That's it! I give up!
if (getcwd(buffer, MAXPATHLEN) == NULL)
return;
} else
- strncpy(buffer, _gameDataPath.c_str(), MAXPATHLEN);
+ strncpy(buffer, _gameDataDir.getPath().c_str(), MAXPATHLEN);
for (i = 0; i < MAXPATHLEN - 1; i++) {
if (buffer[i] == '\\')
@@ -210,3 +215,50 @@ void Engine::pauseEngineIntern(bool pause) {
// By default, just (un)pause all digital sounds
_mixer->pauseAll(pause);
}
+
+void Engine::mainMenuDialog() {
+ if (!_mainMenuDialog)
+ _mainMenuDialog = new MainMenuDialog(this);
+ runDialog(*_mainMenuDialog);
+ syncSoundSettings();
+}
+
+int Engine::runDialog(Dialog &dialog) {
+
+ pauseEngine(true);
+
+ int result = dialog.runModal();
+
+ pauseEngine(false);
+
+ return result;
+}
+
+void 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");
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
+}
+
+void Engine::quitGame() {
+ Common::Event event;
+
+ event.type = Common::EVENT_QUIT;
+ _eventMan->pushEvent(event);
+}
+
+bool Engine::hasFeature(int f) {
+ const EnginePlugin *plugin = 0;
+ Common::String gameid = ConfMan.get("gameid");
+ gameid.toLowercase();
+ EngineMan.findGame(gameid, &plugin);
+
+ return ( (*plugin)->hasFeature((MetaEngine::MetaEngineFeature)f) );
+}
+
diff --git a/engines/engine.h b/engines/engine.h
index 73d529cc62..81e4e6187c 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -25,10 +25,13 @@
#ifndef ENGINES_ENGINE_H
#define ENGINES_ENGINE_H
+#include "common/events.h"
+#include "common/fs.h"
#include "common/scummsys.h"
#include "common/str.h"
class OSystem;
+
namespace Audio {
class Mixer;
}
@@ -39,8 +42,11 @@ namespace Common {
}
namespace GUI {
class Debugger;
+ class Dialog;
}
+using GUI::Dialog;
+
class Engine {
public:
OSystem *_system;
@@ -50,9 +56,13 @@ public:
protected:
Common::EventManager *_eventMan;
Common::SaveFileManager *_saveFileMan;
+
+ Dialog *_mainMenuDialog;
+ virtual int runDialog(Dialog &dialog);
const Common::String _targetName; // target name for saves
- const Common::String _gameDataPath;
+
+ const Common::FilesystemNode _gameDataDir;
private:
/**
@@ -82,7 +92,7 @@ public:
* Start the main engine loop.
* The return value is not yet used, but could indicate whether the user
* wants to return to the launch or to fully quit ScummVM.
- * @return a result code
+ * @return 0 for success, else an error code.
*/
virtual int go() = 0;
@@ -109,10 +119,32 @@ public:
void pauseEngine(bool pause);
/**
+ * Quit the engine, sends a Quit event to the Event Manager
+ */
+ void quitGame();
+
+ /**
* Return whether the engine is currently paused or not.
*/
bool isPaused() const { return _pauseLevel != 0; }
+ /**
+ * Return whether or not the ENGINE should quit
+ */
+ bool quit() const { return (_eventMan->shouldQuit() || _eventMan->shouldRTL()); }
+
+ /** Run the Global Main Menu Dialog
+ */
+ virtual void mainMenuDialog();
+
+ /** Sync the engine's sound settings with the config manager
+ */
+ virtual void syncSoundSettings();
+
+ /** Determine whether the engine supports the specified MetaEngine feature
+ */
+ virtual bool hasFeature(int f);
+
public:
/** Setup the backend's graphics mode. */
diff --git a/base/game.cpp b/engines/game.cpp
index e65c891dc7..b3cb140e0a 100644
--- a/base/game.cpp
+++ b/engines/game.cpp
@@ -23,7 +23,7 @@
*
*/
-#include "base/game.h"
+#include "engines/game.h"
#include "base/plugins.h"
#include "graphics/surface.h"
@@ -69,9 +69,48 @@ void GameDescriptor::updateDesc(const char *extra) {
}
void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
- if (_thumbnail && _thumbnail != t) {
- _thumbnail->free();
- delete _thumbnail;
+ if (_thumbnail.get() == t)
+ return;
+
+ _thumbnail = Common::SharedPtr<Graphics::Surface>(t, Graphics::SharedPtrSurfaceDeleter());
+}
+
+bool SaveStateDescriptor::getBool(const Common::String &key) const {
+ if (contains(key)) {
+ Common::String value = getVal(key);
+ if (value.equalsIgnoreCase("true") ||
+ value.equalsIgnoreCase("yes") ||
+ value.equals("1"))
+ return true;
+ if (value.equalsIgnoreCase("false") ||
+ value.equalsIgnoreCase("no") ||
+ value.equals("0"))
+ return false;
+ error("SaveStateDescriptor: %s '%s' has unknown value '%s' for boolean '%s'",
+ save_slot().c_str(), description().c_str(), value.c_str(), key.c_str());
}
- _thumbnail = t;
+ return false;
+}
+
+void SaveStateDescriptor::setDeletableFlag(bool state) {
+ setVal("is_deletable", state ? "true" : "false");
+}
+
+void SaveStateDescriptor::setSaveDate(int year, int month, int day) {
+ char buffer[32];
+ snprintf(buffer, 32, "%.2d.%.2d.%.4d", day, month, year);
+ setVal("save_date", buffer);
+}
+
+void SaveStateDescriptor::setSaveTime(int hour, int min) {
+ char buffer[32];
+ snprintf(buffer, 32, "%.2d:%.2d", hour, min);
+ setVal("save_time", buffer);
}
+
+void SaveStateDescriptor::setPlayTime(int hours, int minutes) {
+ char buffer[32];
+ snprintf(buffer, 32, "%.2d:%.2d", hours, minutes);
+ setVal("play_time", buffer);
+}
+
diff --git a/base/game.h b/engines/game.h
index d81f2afb8a..a1eed7acd9 100644
--- a/base/game.h
+++ b/engines/game.h
@@ -23,12 +23,13 @@
*
*/
-#ifndef BASE_GAME_H
-#define BASE_GAME_H
+#ifndef ENGINES_GAME_H
+#define ENGINES_GAME_H
#include "common/str.h"
#include "common/array.h"
#include "common/hash-str.h"
+#include "common/ptr.h"
namespace Graphics {
struct Surface;
@@ -119,15 +120,16 @@ public:
*/
class SaveStateDescriptor : public Common::StringMap {
protected:
- Graphics::Surface *_thumbnail; // can be NULL
+ Common::SharedPtr<Graphics::Surface> _thumbnail; // can be 0
+
public:
- SaveStateDescriptor() : _thumbnail(0) {
+ SaveStateDescriptor() : _thumbnail() {
setVal("save_slot", "-1"); // FIXME: default to 0 (first slot) or to -1 (invalid slot) ?
setVal("description", "");
setVal("filename", "");
}
- SaveStateDescriptor(int s, const Common::String &d, const Common::String &f) : _thumbnail(0) {
+ SaveStateDescriptor(int s, const Common::String &d, const Common::String &f) : _thumbnail() {
char buf[16];
sprintf(buf, "%d", s);
setVal("save_slot", buf);
@@ -135,16 +137,12 @@ public:
setVal("filename", f);
}
- SaveStateDescriptor(const Common::String &s, const Common::String &d, const Common::String &f) : _thumbnail(0) {
+ SaveStateDescriptor(const Common::String &s, const Common::String &d, const Common::String &f) : _thumbnail() {
setVal("save_slot", s);
setVal("description", d);
setVal("filename", f);
}
- ~SaveStateDescriptor() {
- setThumbnail(0);
- }
-
/** The saveslot id, as it would be passed to the "-x" command line switch. */
Common::String &save_slot() { return getVal("save_slot"); }
@@ -163,21 +161,47 @@ public:
/** The filename of the savestate, for use with the SaveFileManager API (read-only variant). */
const Common::String &filename() const { return getVal("filename"); }
+ /** Optional entries only included when querying via MetaEngine::querySaveMetaInfo */
+
+ /**
+ * Returns the value of a given key as boolean.
+ * It accepts 'true', 'yes' and '1' for true and
+ * 'false', 'no' and '0' for false.
+ * (FIXME:) On unknown value it errors out ScummVM.
+ * On unknown key it returns false as default.
+ */
+ bool getBool(const Common::String &key) const;
+
+ /**
+ * Sets the 'is_deletable' key, which indicates, if the
+ * given savestate is safe for deletion.
+ */
+ void setDeletableFlag(bool state);
+
/**
* Return a thumbnail graphics surface representing the savestate visually
* This is usually a scaled down version of the game graphics. The size
* should be either 160x100 or 160x120 pixels, depending on the aspect
* ratio of the game. If another ratio is required, contact the core team.
- *
- * TODO: it is probably a bad idea to read this for *all* games at once,
- * at least on low-end devices. So this info should probably normally only
- * be included optionally. I.e. only upon a query for a specific savegame...
- * To this end, add a getFullSaveStateInfo(target, slot) to the plugin API.
*/
- const Graphics::Surface *getThumbnail() const { return _thumbnail; }
-
+ const Graphics::Surface *getThumbnail() const { return _thumbnail.get(); }
void setThumbnail(Graphics::Surface *t);
+
+ /**
+ * Sets the 'save_date' key properly, based on the given values
+ */
+ void setSaveDate(int year, int month, int day);
+
+ /**
+ * Sets the 'save_time' key properly, based on the given values
+ */
+ void setSaveTime(int hour, int min);
+
+ /**
+ * Sets the 'play_time' key properly, based on the given values
+ */
+ void setPlayTime(int hours, int minutes);
};
/** List of savestates. */
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index bcf566d134..d154a01de9 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -62,38 +62,40 @@ DataStream::~DataStream() {
}
}
-uint32 DataStream::pos() const {
+int32 DataStream::pos() const {
if (_stream)
return _stream->pos();
- uint32 resPos = _io->getChunkPos(_handle);
- if (resPos != 0xFFFFFFFF)
+ int32 resPos = _io->getChunkPos(_handle);
+ if (resPos != -1)
return resPos;
return _io->file_getHandle(_handle)->pos();
}
-uint32 DataStream::size() const {
+int32 DataStream::size() const {
if (_stream)
return _stream->size();
return _size;
}
-void DataStream::seek(int32 offset, int whence) {
+bool DataStream::seek(int32 offset, int whence) {
if (_stream)
- _stream->seek(offset, whence);
+ return _stream->seek(offset, whence);
else if ((_handle < 50) || (_handle >= 128))
- _io->file_getHandle(_handle)->seek(offset, whence);
- else
- _io->seekChunk(_handle, offset, whence);
+ return _io->file_getHandle(_handle)->seek(offset, whence);
+ else {
+ _io->seekChunk(_handle, offset, whence);
+ return true;
+ }
}
bool DataStream::eos() const {
if (_stream)
return _stream->eos();
- return pos() >= size();
+ return pos() >= size(); // FIXME (eos definition change)
}
uint32 DataStream::read(void *dataPtr, uint32 dataSize) {
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index 4b4c79d1eb..c67dc89df8 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -45,10 +45,10 @@ public:
DataStream(byte *buf, uint32 dSize, bool dispose = true);
virtual ~DataStream();
- virtual uint32 pos() const;
- virtual uint32 size() const;
+ virtual int32 pos() const;
+ virtual int32 size() const;
- virtual void seek(int32 offset, int whence = SEEK_SET);
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
virtual bool eos() const;
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 63a0f8f45b..2b0c015677 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -57,6 +57,7 @@ static const PlainGameDescriptor gobGames[] = {
{"inca2", "Inca II: Wiracocha"},
{"woodruff", "The Bizarre Adventures of Woodruff and the Schnibble"},
{"dynasty", "The Last Dynasty"},
+ {"urban", "Urban Runner"},
{0, 0}
};
@@ -277,6 +278,19 @@ static const GOBGameDescription gameDescriptions[] = {
kFeaturesNone,
"intro"
},
+ {
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595),
+ UNK_LANG,
+ kPlatformPC,
+ Common::ADGF_DEMO
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ "intro"
+ },
{ // Supplied by raina in the forums
{
"gob1",
@@ -900,6 +914,19 @@ static const GOBGameDescription gameDescriptions[] = {
kFeaturesNone,
"intro"
},
+ { // Supplied by kizkoool in bugreport #2089734
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ "intro"
+ },
{ // Supplied by glorfindel in bugreport #1722142
{
"bargon",
@@ -1043,6 +1070,84 @@ static const GOBGameDescription gameDescriptions[] = {
kFeaturesCD,
"intro"
},
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ { // Supplied by SiRoCs in bug report #2093672
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
{
{
"lostintime",
@@ -1190,6 +1295,19 @@ static const GOBGameDescription gameDescriptions[] = {
kFeaturesAdlib,
"intro"
},
+ { // Supplied by SiRoCs in bug report #2098621
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesAdlib,
+ "intro"
+ },
{
{
"gob3",
@@ -1762,6 +1880,19 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640,
"intro"
},
+ { // Supplied by goodoldgeorg in bug report #2098838
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979),
+ PL_POL,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
{
{
"dynasty",
@@ -1771,7 +1902,7 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- kGameTypeWoodruff,
+ kGameTypeDynasty,
kFeatures640,
"intro"
},
@@ -1784,7 +1915,20 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- kGameTypeWoodruff,
+ kGameTypeDynasty,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeUrban,
kFeatures640,
"intro"
},
@@ -1972,9 +2116,15 @@ public:
return "Goblins Games (C) Coktel Vision";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
};
+bool GobMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL);
+}
+
bool GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Gob::GOBGameDescription *gd = (const Gob::GOBGameDescription *)desc;
if (gd) {
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index 8a7de9bdaa..7136646018 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -323,7 +323,38 @@ void Draw::adjustCoords(char adjust, int16 *coord1, int16 *coord2) {
}
}
-void Draw::drawString(char *str, int16 x, int16 y, int16 color1, int16 color2,
+int Draw::stringLength(const char *str, int16 fontIndex) {
+ static const int8 dword_8F74C[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ if ((fontIndex < 0) || (fontIndex > 7) || !_fonts[fontIndex])
+ return 0;
+
+ int len = 0;
+
+ if (_vm->_global->_language == 10) {
+
+ for (int i = 0; str[i] != 0; i++) {
+ if (((unsigned char) str[i+1]) < 128) {
+ len += dword_8F74C[4];
+ i++;
+ } else
+ len += _fonts[fontIndex]->itemWidth;
+ }
+
+ } else {
+
+ if (_fonts[fontIndex]->extraData)
+ while (*str != 0)
+ len += *(_fonts[fontIndex]->extraData + (*str++ - _fonts[fontIndex]->startItem));
+ else
+ len = (strlen(str) * _fonts[fontIndex]->itemWidth);
+
+ }
+
+ return len;
+}
+
+void Draw::drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2,
int16 transp, SurfaceDesc *dest, Video::FontDesc *font) {
while (*str != '\0') {
@@ -337,7 +368,7 @@ void Draw::drawString(char *str, int16 x, int16 y, int16 color1, int16 color2,
}
void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right,
- int16 bottom, char *str, int16 fontIndex, int16 color) {
+ int16 bottom, const char *str, int16 fontIndex, int16 color) {
adjustCoords(1, &left, &top);
adjustCoords(1, &right, &bottom);
diff --git a/engines/gob/draw.h b/engines/gob/draw.h
index 9ba589aa53..897208a42d 100644
--- a/engines/gob/draw.h
+++ b/engines/gob/draw.h
@@ -69,7 +69,7 @@ public:
int16 _destSurface;
char _letterToPrint;
- char *_textToPrint;
+ const char *_textToPrint;
int16 _backDeltaX;
int16 _backDeltaY;
@@ -146,10 +146,11 @@ public:
void adjustCoords(char adjust, uint16 *coord1, uint16 *coord2) {
adjustCoords(adjust, (int16 *) coord1, (int16 *) coord2);
}
- void drawString(char *str, int16 x, int16 y, int16 color1, int16 color2,
+ int stringLength(const char *str, int16 fontIndex);
+ void drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2,
int16 transp, SurfaceDesc *dest, Video::FontDesc *font);
void printTextCentered(int16 id, int16 left, int16 top, int16 right,
- int16 bottom, char *str, int16 fontIndex, int16 color);
+ int16 bottom, const char *str, int16 fontIndex, int16 color);
int32 getSpriteRectSize(int16 index);
void forceBlit(bool backwards = false);
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index 66deea8ec4..0ecbc81358 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -63,7 +63,7 @@ void Game_v1::playTot(int16 skipPlay) {
strcpy(savedTotName, _curTotFile);
if (skipPlay <= 0) {
- while (!_vm->_quitRequested) {
+ while (!_vm->quit()) {
for (int i = 0; i < 4; i++) {
_vm->_draw->_fontToSprite[i].sprite = -1;
_vm->_draw->_fontToSprite[i].base = -1;
@@ -997,7 +997,7 @@ void Game_v1::collisionsBlock(void) {
WRITE_VAR(16, 0);
_activeCollResId = 0;
}
- while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->_quitRequested);
+ while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->quit());
if (((uint16) _activeCollResId & ~0x8000) == collResId) {
collStackPos = 0;
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index adf75176ab..7d9419b592 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -70,7 +70,7 @@ void Game_v2::playTot(int16 skipPlay) {
strcpy(savedTotName, _curTotFile);
if (skipPlay <= 0) {
- while (!_vm->_quitRequested) {
+ while (!_vm->quit()) {
if (_vm->_inter->_variables)
_vm->_draw->animateCursor(4);
@@ -438,7 +438,7 @@ int16 Game_v2::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId,
timeKey = _vm->_util->getTimeKey();
while (1) {
- if (_vm->_inter->_terminate || _vm->_quitRequested) {
+ if (_vm->_inter->_terminate || _vm->quit()) {
if (handleMouse)
_vm->_draw->blitCursor();
return 0;
@@ -1043,7 +1043,7 @@ void Game_v2::collisionsBlock(void) {
WRITE_VAR(16, 0);
_activeCollResId = 0;
}
- while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->_quitRequested);
+ while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->quit());
if ((_activeCollResId & 0xFFF) == collResId) {
collStackPos = 0;
@@ -1465,7 +1465,7 @@ int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height,
key = checkCollisions(handleMouse, -300, collResId, collIndex);
if ((key != 0) || (*collResId != 0) ||
- _vm->_inter->_terminate || _vm->_quitRequested)
+ _vm->_inter->_terminate || _vm->quit())
break;
if (*pTotTime > 0) {
@@ -1479,7 +1479,7 @@ int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height,
}
if ((key == 0) || (*collResId != 0) ||
- _vm->_inter->_terminate || _vm->_quitRequested)
+ _vm->_inter->_terminate || _vm->quit())
return 0;
switch (key) {
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 34443251d8..7e364e891d 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -24,7 +24,6 @@
*/
#include "common/endian.h"
-#include "common/events.h"
#include "base/plugins.h"
#include "common/config-manager.h"
@@ -62,7 +61,9 @@ const Common::Language GobEngine::_gobToScummVMLang[] = {
Common::EN_USA,
Common::NL_NLD,
Common::KO_KOR,
- Common::HB_ISR
+ Common::HB_ISR,
+ Common::PT_BRA,
+ Common::JA_JPN
};
GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
@@ -82,7 +83,6 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
_copyProtection = ConfMan.getBool("copy_protection");
- _quitRequested = false;
Common::addSpecialDebugLevel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level");
Common::addSpecialDebugLevel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level");
@@ -115,12 +115,8 @@ int GobEngine::go() {
return 0;
}
-void GobEngine::shutdown() {
- _quitRequested = true;
-}
-
const char *GobEngine::getLangDesc(int16 language) const {
- if ((language < 0) || (language > 8))
+ if ((language < 0) || (language > 10))
language = 2;
return Common::getLanguageDescription(_gobToScummVMLang[language]);
}
@@ -244,6 +240,12 @@ int GobEngine::init() {
case Common::HB_ISR:
_global->_language = 8;
break;
+ case Common::PT_BRA:
+ _global->_language = 9;
+ break;
+ case Common::JA_JPN:
+ _global->_language = 10;
+ break;
default:
// Default to English
_global->_language = 2;
@@ -387,6 +389,34 @@ bool GobEngine::initGameParts() {
_saveLoad = new SaveLoad_v4(this, _targetName.c_str());
break;
+ case kGameTypeDynasty:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v5(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v4(this);
+ _goblin = new Goblin_v4(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v4(this, _targetName.c_str());
+ break;
+
+ case kGameTypeUrban:
+ _init = new Init_v3(this);
+ _video = new Video_v6(this);
+ _inter = new Inter_v6(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v4(this);
+ _goblin = new Goblin_v4(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v4(this, _targetName.c_str());
+ break;
+
default:
deinitGameParts();
return false;
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 041658baea..39950e3261 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -93,7 +93,9 @@ enum GameType {
kGameTypeBargon,
kGameTypeWeen,
kGameTypeLostInTime,
- kGameTypeInca2
+ kGameTypeInca2,
+ kGameTypeDynasty,
+ kGameTypeUrban
};
enum Features {
@@ -209,7 +211,6 @@ public:
char *_startTot0;
bool _copyProtection;
bool _noMusic;
- bool _quitRequested;
Global *_global;
Util *_util;
@@ -229,8 +230,6 @@ public:
SaveLoad *_saveLoad;
VideoPlayer *_vidPlayer;
- void shutdown();
-
const char *getLangDesc(int16 language) const;
void validateLanguage();
void validateVideoMode(int16 videoMode);
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
index 5add0b9cea..55758cdfdc 100644
--- a/engines/gob/goblin.cpp
+++ b/engines/gob/goblin.cpp
@@ -652,7 +652,7 @@ void Goblin::adjustDest(int16 posX, int16 posY) {
if ((_vm->_map->getPass(_pressedMapX, _pressedMapY) == 0) &&
((_gobAction == 0) ||
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0))) {
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY) == 0))) {
resDelta = -1;
resDeltaDir = 0;
@@ -727,17 +727,17 @@ void Goblin::adjustDest(int16 posX, int16 posY) {
void Goblin::adjustTarget(void) {
if ((_gobAction == 4) &&
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0)) {
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY) == 0)) {
if ((_pressedMapY > 0) &&
- (_vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX] != 0)) {
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY - 1) != 0)) {
_pressedMapY--;
} else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) &&
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY) != 0)) {
_pressedMapX++;
} else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) &&
(_pressedMapY > 0) &&
- (_vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX + 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY - 1) != 0)) {
_pressedMapY--;
_pressedMapX++;
}
@@ -747,7 +747,7 @@ void Goblin::adjustTarget(void) {
}
void Goblin::targetDummyItem(Gob_Object *gobDesc) {
- if (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0 &&
+ if (_vm->_map->getItem(_pressedMapX, _pressedMapY) == 0 &&
_vm->_map->getPass(_pressedMapX, _pressedMapY) == 1) {
if (gobDesc->curLookDir == 0) {
_vm->_map->_itemPoses[0].x = _pressedMapX;
@@ -771,7 +771,7 @@ void Goblin::targetItem(void) {
Gob_Object *itemDesc;
if ((_gobAction == 3) || (_gobAction == 4)) {
- items = _vm->_map->_itemsMap[_pressedMapY][_pressedMapX];
+ items = _vm->_map->getItem(_pressedMapX, _pressedMapY);
if ((_gobAction == 4) && ((items & 0xFF00) != 0) &&
(_objects[_itemToObject[(items & 0xFF00) >> 8]]->pickable == 1)) {
_destItemId = (items & 0xFF00) >> 8;
@@ -802,40 +802,40 @@ void Goblin::targetItem(void) {
_gobDestX = _vm->_map->_itemPoses[_destItemId].x;
} else if ((items & 0xFF00) != 0) {
if (_vm->_map->_itemPoses[_destItemId].orient == 4) {
- if ((_vm->_map->_itemsMap[_pressedMapY][_pressedMapX - 1] & 0xFF00) ==
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] & 0xFF00)) {
+ if ((_vm->_map->getItem(_pressedMapX - 1, _pressedMapY) & 0xFF00) ==
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY) & 0xFF00)) {
_pressedMapX--;
_vm->_map->_destX = _pressedMapX;
_gobDestX = _pressedMapX;
}
} else if (_vm->_map->_itemPoses[_destItemId].orient == 0) {
- if ((_vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1] & 0xFF00) ==
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] & 0xFF00)) {
+ if ((_vm->_map->getItem(_pressedMapX + 1, _pressedMapY) & 0xFF00) ==
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY) & 0xFF00)) {
_pressedMapX++;
_vm->_map->_destX = _pressedMapX;
_gobDestX = _pressedMapX;
}
}
- if ((_vm->_map->_itemsMap[_pressedMapY + 1][_pressedMapX] & 0xFF00) ==
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] & 0xFF00)) {
+ if ((_vm->_map->getItem(_pressedMapX, _pressedMapY + 1) & 0xFF00) ==
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY) & 0xFF00)) {
_pressedMapY++;
_vm->_map->_destY = _pressedMapY;
_gobDestY = _pressedMapY;
}
} else {
if (_vm->_map->_itemPoses[_destItemId].orient == 4) {
- if ((_vm->_map->_itemsMap[_pressedMapY][_pressedMapX - 1]) ==
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX])) {
+ if ((_vm->_map->getItem(_pressedMapX - 1, _pressedMapY)) ==
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY))) {
_pressedMapX--;
_vm->_map->_destX = _pressedMapX;
_gobDestX = _pressedMapX;
}
} else if (_vm->_map->_itemPoses[_destItemId].orient == 0) {
- if ((_vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1]) ==
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX])) {
+ if ((_vm->_map->getItem(_pressedMapX + 1, _pressedMapY)) ==
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY))) {
_pressedMapX++;
_vm->_map->_destX = _pressedMapX;
_gobDestX = _pressedMapX;
@@ -843,8 +843,8 @@ void Goblin::targetItem(void) {
}
if (_pressedMapY < (_vm->_map->_mapHeight-1)) {
- if ((_vm->_map->_itemsMap[_pressedMapY + 1][_pressedMapX]) ==
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX])) {
+ if ((_vm->_map->getItem(_pressedMapX, _pressedMapY + 1)) ==
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY))) {
_pressedMapY++;
_vm->_map->_destY = _pressedMapY;
_gobDestY = _pressedMapY;
@@ -931,37 +931,37 @@ void Goblin::moveFindItem(int16 posX, int16 posY) {
_pressedMapX = CLIP(posX / 12, 0, _vm->_map->_mapWidth - 1);
_pressedMapY = CLIP(posY / 6, 0, _vm->_map->_mapHeight - 1);
- if ((_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0) && (i < 20)) {
+ if ((_vm->_map->getItem(_pressedMapX, _pressedMapY) == 0) && (i < 20)) {
if ((_pressedMapY < (_vm->_map->_mapHeight - 1)) &&
- (_vm->_map->_itemsMap[_pressedMapY + 1][_pressedMapX] != 0)) {
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY + 1) != 0)) {
_pressedMapY++;
} else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) &&
(_pressedMapY < (_vm->_map->_mapHeight - 1)) &&
- (_vm->_map->_itemsMap[_pressedMapY + 1][_pressedMapX + 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY + 1) != 0)) {
_pressedMapX++;
_pressedMapY++;
} else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) &&
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY) != 0)) {
_pressedMapX++;
} else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) &&
(_pressedMapY > 0) &&
- (_vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX + 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY - 1) != 0)) {
_pressedMapX++;
_pressedMapY--;
} else if ((_pressedMapY > 0) &&
- (_vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX] != 0)) {
+ (_vm->_map->getItem(_pressedMapX, _pressedMapY - 1) != 0)) {
_pressedMapY--;
} else if ((_pressedMapY > 0) && (_pressedMapX > 0) &&
- (_vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX - 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX - 1, _pressedMapY - 1) != 0)) {
_pressedMapY--;
_pressedMapX--;
} else if ((_pressedMapX > 0) &&
- (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX - 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX - 1, _pressedMapY) != 0)) {
_pressedMapX--;
} else if ((_pressedMapX > 0) &&
(_pressedMapY < (_vm->_map->_mapHeight - 1)) &&
- (_vm->_map->_itemsMap[_pressedMapY + 1][_pressedMapX - 1] != 0)) {
+ (_vm->_map->getItem(_pressedMapX - 1, _pressedMapY + 1) != 0)) {
_pressedMapX--;
_pressedMapY++;
}
@@ -1384,11 +1384,11 @@ void Goblin::pickItem(int16 indexToPocket, int16 idToPocket) {
for (int y = 0; y < _vm->_map->_mapHeight; y++) {
for (int x = 0; x < _vm->_map->_mapWidth; x++) {
if (_itemByteFlag == 1) {
- if (((_vm->_map->_itemsMap[y][x] & 0xFF00) >> 8) == idToPocket)
- _vm->_map->_itemsMap[y][x] &= 0xFF;
+ if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == idToPocket)
+ _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF);
} else {
- if ((_vm->_map->_itemsMap[y][x] & 0xFF) == idToPocket)
- _vm->_map->_itemsMap[y][x] &= 0xFF00;
+ if ((_vm->_map->getItem(x, y) & 0xFF) == idToPocket)
+ _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF00);
}
}
}
@@ -1494,18 +1494,16 @@ void Goblin::swapItems(int16 indexToPick, int16 idToPick) {
if (_itemByteFlag == 0) {
for (y = 0; y < _vm->_map->_mapHeight; y++) {
for (x = 0; x < _vm->_map->_mapWidth; x++) {
- if ((_vm->_map->_itemsMap[y][x] & 0xFF) == idToPick)
- _vm->_map->_itemsMap[y][x] =
- (_vm->_map->_itemsMap[y][x] & 0xFF00) + idToPlace;
+ if ((_vm->_map->getItem(x, y) & 0xFF) == idToPick)
+ _vm->_map->setItem(x, y, (_vm->_map->getItem(x, y) & 0xFF00) + idToPlace);
}
}
} else {
for (y = 0; y < _vm->_map->_mapHeight; y++) {
for (x = 0; x < _vm->_map->_mapWidth; x++) {
- if (((_vm->_map->_itemsMap[y][x] & 0xFF00) >> 8) == idToPick)
- _vm->_map->_itemsMap[y][x] =
- (_vm->_map->_itemsMap[y][x] & 0xFF) + (idToPlace << 8);
+ if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == idToPick)
+ _vm->_map->setItem(x, y, (_vm->_map->getItem(x, y) & 0xFF) + (idToPlace << 8));
}
}
}
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 02e7f99cbd..4973bd756d 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -259,7 +259,7 @@ void Inter::funcBlock(int16 retFlag) {
if (executeFuncOpcode(cmd2, cmd, params))
return;
- if (_vm->_quitRequested)
+ if (_vm->quit())
break;
if (_break) {
@@ -279,7 +279,7 @@ void Inter::funcBlock(int16 retFlag) {
void Inter::callSub(int16 retFlag) {
byte block;
- while (!_vm->_quitRequested && _vm->_global->_inter_execPtr &&
+ while (!_vm->quit() && _vm->_global->_inter_execPtr &&
(_vm->_global->_inter_execPtr != _vm->_game->_totFileData)) {
block = *_vm->_global->_inter_execPtr;
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index b684be6c07..fe31722c6c 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -529,6 +529,102 @@ protected:
void o4_playVmdOrMusic();
};
+class Inter_v5 : public Inter_v4 {
+public:
+ Inter_v5(GobEngine *vm);
+ virtual ~Inter_v5() {}
+
+protected:
+ typedef void (Inter_v5::*OpcodeDrawProcV5)();
+ typedef bool (Inter_v5::*OpcodeFuncProcV5)(OpFuncParams &);
+ typedef void (Inter_v5::*OpcodeGoblinProcV5)(OpGobParams &);
+ struct OpcodeDrawEntryV5 {
+ OpcodeDrawProcV5 proc;
+ const char *desc;
+ };
+ struct OpcodeFuncEntryV5 {
+ OpcodeFuncProcV5 proc;
+ const char *desc;
+ };
+ struct OpcodeGoblinEntryV5 {
+ OpcodeGoblinProcV5 proc;
+ const char *desc;
+ };
+ const OpcodeDrawEntryV5 *_opcodesDrawV5;
+ const OpcodeFuncEntryV5 *_opcodesFuncV5;
+ const OpcodeGoblinEntryV5 *_opcodesGoblinV5;
+ static const int _goblinFuncLookUp[][2];
+
+ virtual void setupOpcodes();
+ virtual void executeDrawOpcode(byte i);
+ virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
+ virtual void executeGoblinOpcode(int i, OpGobParams &params);
+ virtual const char *getOpcodeDrawDesc(byte i);
+ virtual const char *getOpcodeFuncDesc(byte i, byte j);
+ virtual const char *getOpcodeGoblinDesc(int i);
+
+ byte _byte_8AA14;
+
+ void o5_deleteFile();
+
+ bool o5_istrlen(OpFuncParams &params);
+
+ void o5_spaceShooter(OpGobParams &params);
+ void o5_getSystemCDSpeed(OpGobParams &params);
+ void o5_getSystemRAM(OpGobParams &params);
+ void o5_getSystemCPUSpeed(OpGobParams &params);
+ void o5_getSystemDrawSpeed(OpGobParams &params);
+ void o5_totalSystemSpecs(OpGobParams &params);
+ void o5_saveSystemSpecs(OpGobParams &params);
+ void o5_loadSystemSpecs(OpGobParams &params);
+
+ void o5_gob92(OpGobParams &params);
+ void o5_gob95(OpGobParams &params);
+ void o5_gob96(OpGobParams &params);
+ void o5_gob97(OpGobParams &params);
+ void o5_gob98(OpGobParams &params);
+ void o5_gob100(OpGobParams &params);
+ void o5_gob200(OpGobParams &params);
+};
+
+class Inter_v6 : public Inter_v5 {
+public:
+ Inter_v6(GobEngine *vm);
+ virtual ~Inter_v6() {}
+
+protected:
+ typedef void (Inter_v6::*OpcodeDrawProcV6)();
+ typedef bool (Inter_v6::*OpcodeFuncProcV6)(OpFuncParams &);
+ typedef void (Inter_v6::*OpcodeGoblinProcV6)(OpGobParams &);
+ struct OpcodeDrawEntryV6 {
+ OpcodeDrawProcV6 proc;
+ const char *desc;
+ };
+ struct OpcodeFuncEntryV6 {
+ OpcodeFuncProcV6 proc;
+ const char *desc;
+ };
+ struct OpcodeGoblinEntryV6 {
+ OpcodeGoblinProcV6 proc;
+ const char *desc;
+ };
+ const OpcodeDrawEntryV6 *_opcodesDrawV6;
+ const OpcodeFuncEntryV6 *_opcodesFuncV6;
+ const OpcodeGoblinEntryV6 *_opcodesGoblinV6;
+ static const int _goblinFuncLookUp[][2];
+
+ virtual void setupOpcodes();
+ virtual void executeDrawOpcode(byte i);
+ virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
+ virtual void executeGoblinOpcode(int i, OpGobParams &params);
+ virtual const char *getOpcodeDrawDesc(byte i);
+ virtual const char *getOpcodeFuncDesc(byte i, byte j);
+ virtual const char *getOpcodeGoblinDesc(int i);
+
+ bool o6_loadCursor(OpFuncParams &params);
+ bool o6_evaluateStore(OpFuncParams &params);
+};
+
} // End of namespace Gob
#endif // GOB_INTER_H
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index d493fb00d3..d23841efd6 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -750,7 +750,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
for (i = 320; i >= 0; i--) {
_vm->_util->setScrollOffset(i, 0);
if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) ||
- _vm->_quitRequested) {
+ _vm->quit()) {
_vm->_palAnim->fade(0, -2, 0);
_vm->_video->clearSurf(_vm->_draw->_frontSurface);
memset((char *) _vm->_draw->_vgaPalette, 0, 768);
@@ -760,7 +760,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
break;
}
}
- if (!_vm->_quitRequested)
+ if (!_vm->quit())
_vm->_util->setScrollOffset(0, 0);
surface = 0;
if (VAR(57) == ((uint32) -1))
@@ -799,7 +799,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
_vm->_util->longDelay(_vm->_util->getRandom(200));
}
if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) ||
- _vm->_quitRequested) {
+ _vm->quit()) {
_vm->_sound->blasterStop(10);
_vm->_palAnim->fade(0, -2, 0);
_vm->_video->clearSurf(_vm->_draw->_frontSurface);
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 865d188a2e..1e01cd9048 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1234,7 +1234,7 @@ bool Inter_v1::o1_repeatUntil(OpFuncParams &params) {
funcBlock(1);
_vm->_global->_inter_execPtr = blockPtr + size + 1;
flag = evalBoolResult();
- } while (!flag && !_break && !_terminate && !_vm->_quitRequested);
+ } while (!flag && !_break && !_terminate && !_vm->quit());
_nestLevel[0]--;
@@ -1269,7 +1269,7 @@ bool Inter_v1::o1_whileDo(OpFuncParams &params) {
} else
_vm->_global->_inter_execPtr += size;
- if (_break || _terminate || _vm->_quitRequested) {
+ if (_break || _terminate || _vm->quit()) {
_vm->_global->_inter_execPtr = blockPtr;
_vm->_global->_inter_execPtr += size;
break;
@@ -2443,10 +2443,10 @@ void Inter_v1::o1_getItem(OpGobParams &params) {
int16 xPos = load16();
int16 yPos = load16();
- if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0)
- params.retVarPtr = (uint32) ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8);
+ if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0)
+ params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8);
else
- params.retVarPtr = (uint32) _vm->_map->_itemsMap[yPos][xPos];
+ params.retVarPtr = (uint32) _vm->_map->getItem(xPos, yPos);
}
void Inter_v1::o1_manipulateMapIndirect(OpGobParams &params) {
@@ -2468,10 +2468,10 @@ void Inter_v1::o1_getItemIndirect(OpGobParams &params) {
xPos = VAR(xPos);
yPos = VAR(yPos);
- if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0)
- params.retVarPtr = (uint32) ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8);
+ if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0)
+ params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8);
else
- params.retVarPtr = (uint32) _vm->_map->_itemsMap[yPos][xPos];
+ params.retVarPtr = (uint32) _vm->_map->getItem(xPos, yPos);
}
void Inter_v1::o1_setPassMap(OpGobParams &params) {
@@ -3025,88 +3025,88 @@ void Inter_v1::animPalette() {
void Inter_v1::manipulateMap(int16 xPos, int16 yPos, int16 item) {
for (int y = 0; y < _vm->_map->_mapHeight; y++) {
for (int x = 0; x < _vm->_map->_mapWidth; x++) {
- if ((_vm->_map->_itemsMap[y][x] & 0xFF) == item)
- _vm->_map->_itemsMap[y][x] &= 0xFF00;
- else if (((_vm->_map->_itemsMap[y][x] & 0xFF00) >> 8) == item)
- _vm->_map->_itemsMap[y][x] &= 0xFF;
+ if ((_vm->_map->getItem(x, y) & 0xFF) == item)
+ _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF00);
+ else if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == item)
+ _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF);
}
}
if (xPos < _vm->_map->_mapWidth - 1) {
if (yPos > 0) {
- if (((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0) ||
- ((_vm->_map->_itemsMap[yPos - 1][xPos] & 0xFF00) != 0) ||
- ((_vm->_map->_itemsMap[yPos][xPos + 1] & 0xFF00) != 0) ||
- ((_vm->_map->_itemsMap[yPos - 1][xPos + 1] & 0xFF00) != 0)) {
+ if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) ||
+ ((_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) != 0) ||
+ ((_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) != 0) ||
+ ((_vm->_map->getItem(xPos + 1, yPos - 1) & 0xFF00) != 0)) {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) + item;
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
- _vm->_map->_itemsMap[yPos - 1][xPos] =
- (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xFF00) + item;
+ _vm->_map->setItem(xPos, yPos - 1,
+ (_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) + item);
- _vm->_map->_itemsMap[yPos][xPos + 1] =
- (_vm->_map->_itemsMap[yPos][xPos + 1] & 0xFF00) + item;
+ _vm->_map->setItem(xPos + 1, yPos,
+ (_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) + item);
- _vm->_map->_itemsMap[yPos - 1][xPos + 1] =
- (_vm->_map->_itemsMap[yPos - 1][xPos + 1] & 0xFF00) + item;
+ _vm->_map->setItem(xPos + 1, yPos - 1,
+ (_vm->_map->getItem(xPos + 1, yPos - 1) & 0xFF00) + item);
} else {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
- _vm->_map->_itemsMap[yPos - 1][xPos] =
- (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos, yPos - 1,
+ (_vm->_map->getItem(xPos, yPos - 1) & 0xFF) + (item << 8));
- _vm->_map->_itemsMap[yPos][xPos + 1] =
- (_vm->_map->_itemsMap[yPos][xPos + 1] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos + 1, yPos,
+ (_vm->_map->getItem(xPos + 1, yPos) & 0xFF) + (item << 8));
- _vm->_map->_itemsMap[yPos - 1][xPos + 1] =
- (_vm->_map->_itemsMap[yPos - 1][xPos + 1] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos + 1, yPos - 1,
+ (_vm->_map->getItem(xPos + 1, yPos - 1) & 0xFF) + (item << 8));
}
} else {
- if (((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0) ||
- ((_vm->_map->_itemsMap[yPos][xPos + 1] & 0xFF00) != 0)) {
+ if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) ||
+ ((_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) != 0)) {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) + item;
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
- _vm->_map->_itemsMap[yPos][xPos + 1] =
- (_vm->_map->_itemsMap[yPos][xPos + 1] & 0xFF00) + item;
+ _vm->_map->setItem(xPos + 1, yPos,
+ (_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) + item);
} else {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
- _vm->_map->_itemsMap[yPos][xPos + 1] =
- (_vm->_map->_itemsMap[yPos][xPos + 1] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos + 1, yPos,
+ (_vm->_map->getItem(xPos + 1, yPos) & 0xFF) + (item << 8));
}
}
} else {
if (yPos > 0) {
- if (((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0) ||
- ((_vm->_map->_itemsMap[yPos - 1][xPos] & 0xFF00) != 0)) {
+ if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) ||
+ ((_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) != 0)) {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) + item;
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
- _vm->_map->_itemsMap[yPos - 1][xPos] =
- (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xFF00) + item;
+ _vm->_map->setItem(xPos, yPos - 1,
+ (_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) + item);
} else {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
- _vm->_map->_itemsMap[yPos - 1][xPos] =
- (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos, yPos - 1,
+ (_vm->_map->getItem(xPos, yPos - 1) & 0xFF) + (item << 8));
}
} else {
- if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0) {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) + item;
+ if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) {
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
} else {
- _vm->_map->_itemsMap[yPos][xPos] =
- (_vm->_map->_itemsMap[yPos][xPos] & 0xFF) + (item << 8);
+ _vm->_map->setItem(xPos, yPos,
+ (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
}
}
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 2f1d2ec0be..b245001653 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -24,6 +24,7 @@
*/
#include "common/endian.h"
+
#include "sound/mixer.h"
#include "sound/mods/infogrames.h"
@@ -1489,7 +1490,7 @@ void Inter_v2::o2_scroll() {
curX = startX;
curY = startY;
- while (!_vm->_quitRequested && ((curX != endX) || (curY != endY))) {
+ while (!_vm->quit() && ((curX != endX) || (curY != endY))) {
curX = stepX > 0 ? MIN(curX + stepX, (int) endX) :
MAX(curX + stepX, (int) endX);
curY = stepY > 0 ? MIN(curY + stepY, (int) endY) :
diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp
new file mode 100644
index 0000000000..6df76bda4a
--- /dev/null
+++ b/engines/gob/inter_v5.cpp
@@ -0,0 +1,1040 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/endian.h"
+#include "common/file.h"
+
+#include "gob/gob.h"
+#include "gob/inter.h"
+#include "gob/global.h"
+#include "gob/game.h"
+#include "gob/parse.h"
+#include "gob/draw.h"
+
+namespace Gob {
+
+#define OPCODE(x) _OPCODE(Inter_v5, x)
+
+const int Inter_v5::_goblinFuncLookUp[][2] = {
+ {0, 0},
+ {1, 0},
+ {80, 1},
+ {81, 2},
+ {82, 3},
+ {83, 4},
+ {84, 5},
+ {85, 6},
+ {86, 7},
+ {87, 0},
+ {88, 0},
+ {89, 0},
+ {90, 0},
+ {91, 0},
+ {92, 8},
+ {93, 0},
+ {94, 0},
+ {95, 9},
+ {96, 10},
+ {97, 11},
+ {98, 12},
+ {99, 0},
+ {100, 13},
+ {200, 14},
+ {30, 24},
+ {32, 25},
+ {33, 26},
+ {34, 27},
+ {35, 28},
+ {36, 29},
+ {37, 30},
+ {40, 31},
+ {41, 32},
+ {42, 33},
+ {43, 34},
+ {44, 35},
+ {50, 36},
+ {52, 37},
+ {53, 38},
+ {100, 39},
+ {152, 40},
+ {200, 41},
+ {201, 42},
+ {202, 43},
+ {203, 44},
+ {204, 45},
+ {250, 46},
+ {251, 47},
+ {252, 48},
+ {500, 49},
+ {502, 50},
+ {503, 51},
+ {600, 52},
+ {601, 53},
+ {602, 54},
+ {603, 55},
+ {604, 56},
+ {605, 57},
+ {1000, 58},
+ {1001, 59},
+ {1002, 60},
+ {1003, 61},
+ {1004, 62},
+ {1005, 63},
+ {1006, 64},
+ {1008, 65},
+ {1009, 66},
+ {1010, 67},
+ {1011, 68},
+ {1015, 69},
+ {2005, 70}
+};
+
+Inter_v5::Inter_v5(GobEngine *vm) : Inter_v4(vm) {
+ setupOpcodes();
+}
+
+void Inter_v5::setupOpcodes() {
+ static const OpcodeDrawEntryV5 opcodesDraw[256] = {
+ /* 00 */
+ OPCODE(o1_loadMult),
+ OPCODE(o2_playMult),
+ OPCODE(o2_freeMultKeys),
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_initCursor),
+ /* 08 */
+ OPCODE(o1_initCursorAnim),
+ OPCODE(o1_clearCursorAnim),
+ OPCODE(o2_setRenderFlags),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ OPCODE(o1_loadAnim),
+ OPCODE(o1_freeAnim),
+ OPCODE(o1_updateAnim),
+ OPCODE(o2_multSub),
+ /* 14 */
+ OPCODE(o2_initMult),
+ OPCODE(o1_freeMult),
+ OPCODE(o1_animate),
+ OPCODE(o2_loadMultObject),
+ /* 18 */
+ OPCODE(o1_getAnimLayerInfo),
+ OPCODE(o1_getObjAnimSize),
+ OPCODE(o1_loadStatic),
+ OPCODE(o1_freeStatic),
+ /* 1C */
+ OPCODE(o2_renderStatic),
+ OPCODE(o2_loadCurLayer),
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ OPCODE(o2_playCDTrack),
+ OPCODE(o2_waitCDTrackEnd),
+ OPCODE(o2_stopCD),
+ OPCODE(o2_readLIC),
+ /* 24 */
+ OPCODE(o2_freeLIC),
+ OPCODE(o2_getCDTrackPos),
+ {NULL, ""},
+ {NULL, ""},
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o2_loadFontToSprite),
+ OPCODE(o1_freeFontToSprite),
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ OPCODE(o2_totSub),
+ OPCODE(o2_switchTotSub),
+ OPCODE(o2_copyVars),
+ OPCODE(o2_pasteVars),
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 48 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 4C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 50 */
+ OPCODE(o2_loadMapObjects),
+ OPCODE(o2_freeGoblins),
+ OPCODE(o2_moveGoblin),
+ OPCODE(o2_writeGoblinPos),
+ /* 54 */
+ OPCODE(o2_stopGoblin),
+ OPCODE(o2_setGoblinState),
+ OPCODE(o2_placeGoblin),
+ {NULL, ""},
+ /* 58 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 5C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 60 */
+ {NULL, ""},
+ OPCODE(o5_deleteFile),
+ {NULL, ""},
+ {NULL, ""},
+ /* 64 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 68 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 6C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 70 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 74 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 78 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 7C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 80 */
+ OPCODE(o4_initScreen),
+ OPCODE(o2_scroll),
+ OPCODE(o2_setScrollOffset),
+ OPCODE(o4_playVmdOrMusic),
+ /* 84 */
+ OPCODE(o2_getImdInfo),
+ OPCODE(o2_openItk),
+ OPCODE(o2_closeItk),
+ OPCODE(o2_setImdFrontSurf),
+ /* 88 */
+ OPCODE(o2_resetImdFrontSurf),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 8C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 90 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 94 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 98 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 9C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* AC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* BC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* CC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* DC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* EC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* FC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""}
+ };
+
+ static const OpcodeFuncEntryV5 opcodesFunc[80] = {
+ /* 00 */
+ OPCODE(o1_callSub),
+ OPCODE(o1_callSub),
+ OPCODE(o1_printTotText),
+ OPCODE(o1_loadCursor),
+ /* 04 */
+ {NULL, ""},
+ OPCODE(o1_switch),
+ OPCODE(o1_repeatUntil),
+ OPCODE(o1_whileDo),
+ /* 08 */
+ OPCODE(o1_if),
+ OPCODE(o2_evaluateStore),
+ OPCODE(o1_loadSpriteToPos),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ OPCODE(o2_printText),
+ OPCODE(o1_loadTot),
+ OPCODE(o1_palLoad),
+ /* 14 */
+ OPCODE(o1_keyFunc),
+ OPCODE(o1_capturePush),
+ OPCODE(o1_capturePop),
+ OPCODE(o2_animPalInit),
+ /* 18 */
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
+ OPCODE(o3_getTotTextItemPart),
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_drawOperations),
+ OPCODE(o1_setcmdCount),
+ /* 20 */
+ OPCODE(o1_return),
+ OPCODE(o1_renewTimeInVars),
+ OPCODE(o1_speakerOn),
+ OPCODE(o1_speakerOff),
+ /* 24 */
+ OPCODE(o1_putPixel),
+ OPCODE(o2_goblinFunc),
+ OPCODE(o2_createSprite),
+ OPCODE(o1_freeSprite),
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o1_returnTo),
+ OPCODE(o1_loadSpriteContent),
+ OPCODE(o1_copySprite),
+ OPCODE(o1_fillRect),
+ /* 34 */
+ OPCODE(o1_drawLine),
+ OPCODE(o1_strToLong),
+ OPCODE(o1_invalidate),
+ OPCODE(o1_setBackDelta),
+ /* 38 */
+ OPCODE(o1_playSound),
+ OPCODE(o2_stopSound),
+ OPCODE(o2_loadSound),
+ OPCODE(o1_freeSoundSlot),
+ /* 3C */
+ OPCODE(o1_waitEndPlay),
+ OPCODE(o1_playComposition),
+ OPCODE(o2_getFreeMem),
+ OPCODE(o2_checkData),
+ /* 40 */
+ {NULL, ""},
+ OPCODE(o1_prepareStr),
+ OPCODE(o1_insertStr),
+ OPCODE(o1_cutStr),
+ /* 44 */
+ OPCODE(o1_strstr),
+ OPCODE(o5_istrlen),
+ OPCODE(o1_setMousePos),
+ OPCODE(o1_setFrameRate),
+ /* 48 */
+ OPCODE(o1_animatePalette),
+ OPCODE(o1_animateCursor),
+ OPCODE(o1_blitCursor),
+ OPCODE(o1_loadFont),
+ /* 4C */
+ OPCODE(o1_freeFont),
+ OPCODE(o2_readData),
+ OPCODE(o2_writeData),
+ OPCODE(o1_manageDataFile),
+ };
+
+ static const OpcodeGoblinEntryV5 opcodesGoblin[71] = {
+ /* 00 */
+ OPCODE(o5_spaceShooter),
+ OPCODE(o5_getSystemCDSpeed),
+ OPCODE(o5_getSystemRAM),
+ OPCODE(o5_getSystemCPUSpeed),
+ /* 04 */
+ OPCODE(o5_getSystemDrawSpeed),
+ OPCODE(o5_totalSystemSpecs),
+ OPCODE(o5_saveSystemSpecs),
+ OPCODE(o5_loadSystemSpecs),
+ /* 08 */
+ OPCODE(o5_gob92),
+ OPCODE(o5_gob95),
+ OPCODE(o5_gob96),
+ OPCODE(o5_gob97),
+ /* 0C */
+ OPCODE(o5_gob98),
+ OPCODE(o5_gob100),
+ OPCODE(o5_gob200),
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 14 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 18 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 24 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ };
+
+ _opcodesDrawV5 = opcodesDraw;
+ _opcodesFuncV5 = opcodesFunc;
+ _opcodesGoblinV5 = opcodesGoblin;
+}
+
+void Inter_v5::executeDrawOpcode(byte i) {
+ debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
+ i, i, getOpcodeDrawDesc(i));
+
+ OpcodeDrawProcV5 op = _opcodesDrawV5[i].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeDraw: %d", i);
+ else
+ (this->*op) ();
+}
+
+bool Inter_v5::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
+ debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d",
+ i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile,
+ (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData),
+ (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4));
+
+ if ((i > 4) || (j > 15)) {
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ return false;
+ }
+
+ OpcodeFuncProcV5 op = _opcodesFuncV5[i*16 + j].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ else
+ return (this->*op) (params);
+
+ return false;
+}
+
+void Inter_v5::executeGoblinOpcode(int i, OpGobParams &params) {
+ debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
+ i, i, getOpcodeGoblinDesc(i));
+
+ OpcodeGoblinProcV5 op = NULL;
+
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i) {
+ op = _opcodesGoblinV5[_goblinFuncLookUp[j][1]].proc;
+ break;
+ }
+
+ _vm->_global->_inter_execPtr -= 2;
+
+ if (op == NULL) {
+ warning("unimplemented opcodeGoblin: %d", i);
+
+ int16 paramCount = load16();
+ _vm->_global->_inter_execPtr += paramCount * 2;
+ } else {
+ params.extraData = i;
+
+ (this->*op) (params);
+ }
+}
+
+const char *Inter_v5::getOpcodeDrawDesc(byte i) {
+ return _opcodesDrawV5[i].desc;
+}
+
+const char *Inter_v5::getOpcodeFuncDesc(byte i, byte j) {
+ if ((i > 4) || (j > 15))
+ return "";
+
+ return _opcodesFuncV5[i*16 + j].desc;
+}
+
+const char *Inter_v5::getOpcodeGoblinDesc(int i) {
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i)
+ return _opcodesGoblinV5[_goblinFuncLookUp[j][1]].desc;
+ return "";
+}
+
+void Inter_v5::o5_deleteFile() {
+ evalExpr(0);
+
+ warning("Dynasty Stub: deleteFile \"%s\"", _vm->_global->_inter_resStr);
+}
+
+bool Inter_v5::o5_istrlen(OpFuncParams &params) {
+ int16 strVar1, strVar2;
+ int16 len;
+
+ if (*_vm->_global->_inter_execPtr == 0x80) {
+ _vm->_global->_inter_execPtr++;
+
+ strVar1 = _vm->_parse->parseVarIndex();
+ strVar2 = _vm->_parse->parseVarIndex();
+
+ len = _vm->_draw->stringLength(GET_VARO_STR(strVar1), READ_VARO_UINT16(strVar2));
+
+ } else {
+
+ strVar1 = _vm->_parse->parseVarIndex();
+ strVar2 = _vm->_parse->parseVarIndex();
+
+ if (_vm->_global->_language == 10) {
+ // Extra handling for Japanese strings
+
+ for (len = 0; READ_VARO_UINT8(strVar1) != 0; strVar1++, len++)
+ if (READ_VARO_UINT8(strVar1) >= 128)
+ strVar1++;
+
+ } else
+ len = strlen(GET_VARO_STR(strVar1));
+ }
+
+ WRITE_VAR_OFFSET(strVar2, len);
+ return false;
+}
+
+void Inter_v5::o5_spaceShooter(OpGobParams &params) {
+ int16 paramCount = load16();
+
+ warning("Dynasty Stub: Space shooter: %d, %d, %s",
+ params.extraData, paramCount, _vm->_game->_curTotFile);
+
+ if (paramCount < 4) {
+ warning("Space shooter variable counter < 4");
+ _vm->_global->_inter_execPtr += paramCount * 2;
+ return;
+ }
+
+ uint32 var1 = load16() * 4;
+ uint32 var2 = load16() * 4;
+#if 1
+ load16();
+ load16();
+#else
+ uint32 var3 = load16() * 4;
+ uint16 var4 = load16();
+#endif
+
+ if (params.extraData != 0) {
+ WRITE_VARO_UINT32(var1, 0);
+ WRITE_VARO_UINT32(var2, 0);
+ } else {
+ if (paramCount < 5) {
+ warning("Space shooter variable counter < 5");
+ return;
+ }
+
+ _vm->_global->_inter_execPtr += (paramCount - 4) * 2;
+ }
+}
+
+void Inter_v5::o5_getSystemCDSpeed(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+
+ Video::FontDesc *font;
+ if ((font = _vm->_util->loadFont("SPEED.LET"))) {
+ _vm->_draw->drawString("100 %", 402, 89, 112, 144, 0, _vm->_draw->_backSurface, font);
+ _vm->_draw->forceBlit();
+
+ _vm->_util->freeFont(font);
+ }
+}
+
+void Inter_v5::o5_getSystemRAM(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+
+ Video::FontDesc *font;
+ if ((font = _vm->_util->loadFont("SPEED.LET"))) {
+ _vm->_draw->drawString("100 %", 402, 168, 112, 144, 0, _vm->_draw->_backSurface, font);
+ _vm->_draw->forceBlit();
+
+ _vm->_util->freeFont(font);
+ }
+}
+
+void Inter_v5::o5_getSystemCPUSpeed(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+
+ Video::FontDesc *font;
+ if ((font = _vm->_util->loadFont("SPEED.LET"))) {
+ _vm->_draw->drawString("100 %", 402, 248, 112, 144, 0, _vm->_draw->_backSurface, font);
+ _vm->_draw->forceBlit();
+
+ _vm->_util->freeFont(font);
+ }
+}
+
+void Inter_v5::o5_getSystemDrawSpeed(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+
+ Video::FontDesc *font;
+ if ((font = _vm->_util->loadFont("SPEED.LET"))) {
+ _vm->_draw->drawString("100 %", 402, 326, 112, 144, 0, _vm->_draw->_backSurface, font);
+ _vm->_draw->forceBlit();
+
+ _vm->_util->freeFont(font);
+ }
+}
+
+void Inter_v5::o5_totalSystemSpecs(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 100); // Fudging 100%
+
+ Video::FontDesc *font;
+ if ((font = _vm->_util->loadFont("SPEED.LET"))) {
+ _vm->_draw->drawString("100 %", 402, 405, 112, 144, 0, _vm->_draw->_backSurface, font);
+ _vm->_draw->forceBlit();
+
+ _vm->_util->freeFont(font);
+ }
+}
+
+void Inter_v5::o5_saveSystemSpecs(OpGobParams &params) {
+ warning("Dynasty Stub: Saving system specifications");
+
+ _vm->_global->_inter_execPtr += 2;
+
+/*
+ FILE *f = fopen("SAVE\\SPEED.INF", w);
+ fwrite(&_cdSpeed, sizeof(_cdSpeed), 1, f);
+ fwrite(&_ram, sizeof(_ram), 1, f);
+ fwrite(&_cpuSpeed, sizeof(_cpuSpeed), 1, f);
+ fwrite(&_drawSpeed, sizeof(_drawSpeed), 1, f);
+ fwrite(&_total, sizeof(_total), 1, f);
+ fclose(f);
+*/
+}
+
+void Inter_v5::o5_loadSystemSpecs(OpGobParams &params) {
+ warning("Dynasty Stub: Loading system specifications");
+
+ _vm->_global->_inter_execPtr += 2;
+
+/*
+ FILE *f = fopen("SAVE\\SPEED.INF", r);
+ fread(&_cdSpeed, sizeof(_cdSpeed), 1, f);
+ fread(&_ram, sizeof(_ram), 1, f);
+ fread(&_cpuSpeed, sizeof(_cpuSpeed), 1, f);
+ fread(&_drawSpeed, sizeof(_drawSpeed), 1, f);
+ fread(&_total, sizeof(_total), 1, f);
+ fclose(f);
+*/
+
+/*
+ // Calculating whether speed throttling is necessary?
+
+ var_E = MAX(_cdSpeed, 150);
+ var_E += (_ram << 3);
+ var_E += (_cpuSpeed << 3);
+ var_E /= 17;
+
+ byte_8A61E = (var_E > 81) ? 1 : 0;
+ byte_8A5E0 = (_total >= 95) ? 1 : 0;
+
+ if (byte_8A5E0 == 1) {
+ word_8AEE2 = 100;
+ byte_8AEE4 = 1;
+ byte_8AEE5 = 1;
+ word_8AEE6 = 0;
+ } else {
+ word_8AEE2 = 0;
+ byte_8AEE4 = 0;
+ byte_8AEE5 = 0;
+ word_8AEE6 = 40;
+ }
+*/
+}
+
+void Inter_v5::o5_gob92(OpGobParams &params) {
+ warning("Dynasty Stub: GobFunc 92");
+
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) byte_86B9E)) */);
+}
+
+void Inter_v5::o5_gob95(OpGobParams &params) {
+ warning("Dynasty Stub: GobFunc 95");
+
+ _vm->_global->_inter_execPtr += 2;
+
+ WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) word_8AEE6)) */);
+ WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) byte_8AEE5)) */);
+ WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) byte_8AEE4)) */);
+ WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) word_8AEE2)) */);
+}
+
+void Inter_v5::o5_gob96(OpGobParams &params) {
+ int16 word_8AEE6, word_85B50, word_8AEE2;
+ byte byte_8AEE5, byte_8AEE4;
+
+ _vm->_global->_inter_execPtr += 2;
+
+ word_8AEE6 = word_85B50 = READ_VAR_UINT16(load16());
+ byte_8AEE5 = READ_VAR_UINT8(load16());
+ byte_8AEE4 = READ_VAR_UINT8(load16());
+ word_8AEE2 = READ_VAR_UINT16(load16());
+
+ warning("Dynasty Stub: GobFunc 96: %d, %d, %d, %d",
+ word_8AEE6, byte_8AEE5, byte_8AEE4, word_8AEE2);
+
+ // .--- sub_194B0 ---
+
+ int16 word_8A8F0, word_8A8F2, word_8A8F4, word_8A8F6, word_8A8F8, word_8A8FA;
+
+ int16 word_8A62C = 1;
+ int16 word_8A63C, word_8A640, word_8B464, word_8B466;
+
+ byte byte_8A62E;
+
+ int16 var_2, var_4;
+
+ var_2 = word_85B50 + 31;
+ word_8A8F0 = word_8A8F2 = var_2;
+ word_8A8F4 = word_85B50;
+
+ var_4 = 315 - word_85B50;
+ word_8A8F6 = word_8A8F8 = var_4;
+
+ word_8A8FA = 479 - word_85B50;
+
+ if (word_8A62C == 0) {
+ word_8A63C = word_8A8F0;
+ word_8A640 = word_8A8F6;
+ word_8B464 = word_8A8F0;
+ word_8B466 = word_8A8F6;
+ } else if (word_8A62C == 1) {
+ word_8A63C = word_85B50;
+ word_8A640 = word_8A8FA;
+ word_8B464 = word_85B50;
+ word_8B466 = word_8A8FA;
+ } else if (word_8A62C == 2) {
+ word_8A63C = word_8A8F4;
+ word_8A640 = word_8A8FA;
+ word_8B464 = word_8A8F4;
+ word_8B466 = word_8A8FA;
+ } else if (word_8A62C == 3) {
+ word_8A63C = word_8A8F4;
+ word_8A640 = word_8A8FA;
+ word_8B464 = word_8A8F4;
+ word_8B466 = word_8A8FA;
+ } else if (word_8A62C == 4) {
+ word_8A63C = word_8A8F4;
+ word_8A640 = word_8A8FA;
+ word_8B464 = word_8A8F4;
+ word_8B466 = word_8A8FA;
+ }
+
+ byte_8A62E = 1;
+
+// '--- ---
+
+}
+
+void Inter_v5::o5_gob97(OpGobParams &params) {
+ _byte_8AA14 = 1;
+
+ _vm->_global->_inter_execPtr += 2;
+}
+
+void Inter_v5::o5_gob98(OpGobParams &params) {
+ _byte_8AA14 = 0;
+
+ _vm->_global->_inter_execPtr += 2;
+}
+
+void Inter_v5::o5_gob100(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ uint16 var1 = READ_VAR_UINT16(load16());
+ uint16 var2 = READ_VAR_UINT16(load16());
+ uint16 var3 = READ_VAR_UINT16(load16());
+ uint16 var4 = READ_VAR_UINT16(load16());
+
+ warning("Dynasty Stub: GobFunc 100: %d, %d, %d, %d", var1, var2, var3, var4);
+
+ var3 = (var3 + var1) - 1;
+ var4 = (var4 + var2) - 1;
+}
+
+void Inter_v5::o5_gob200(OpGobParams &params) {
+ _vm->_global->_inter_execPtr += 2;
+
+ uint16 var1 = load16(); // index into the spritesArray
+ uint16 var2 = load16();
+ uint16 var3 = load16();
+
+ warning("Dynasty Stub: GobFunc 200: %d, %d, %d", var1, var2, var3);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp
new file mode 100644
index 0000000000..d27bcc64b5
--- /dev/null
+++ b/engines/gob/inter_v6.cpp
@@ -0,0 +1,866 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/endian.h"
+#include "common/file.h"
+
+#include "gob/gob.h"
+#include "gob/inter.h"
+#include "gob/global.h"
+#include "gob/game.h"
+#include "gob/parse.h"
+#include "gob/draw.h"
+
+namespace Gob {
+
+#define OPCODE(x) _OPCODE(Inter_v6, x)
+
+const int Inter_v6::_goblinFuncLookUp[][2] = {
+ {0, 0},
+ {1, 0},
+ {80, 1},
+ {81, 2},
+ {82, 3},
+ {83, 4},
+ {84, 5},
+ {85, 6},
+ {86, 7},
+ {87, 0},
+ {88, 0},
+ {89, 0},
+ {90, 0},
+ {91, 0},
+ {92, 8},
+ {93, 0},
+ {94, 0},
+ {95, 9},
+ {96, 10},
+ {97, 11},
+ {98, 12},
+ {99, 0},
+ {100, 13},
+ {200, 14},
+ {30, 24},
+ {32, 25},
+ {33, 26},
+ {34, 27},
+ {35, 28},
+ {36, 29},
+ {37, 30},
+ {40, 31},
+ {41, 32},
+ {42, 33},
+ {43, 34},
+ {44, 35},
+ {50, 36},
+ {52, 37},
+ {53, 38},
+ {100, 39},
+ {152, 40},
+ {200, 41},
+ {201, 42},
+ {202, 43},
+ {203, 44},
+ {204, 45},
+ {250, 46},
+ {251, 47},
+ {252, 48},
+ {500, 49},
+ {502, 50},
+ {503, 51},
+ {600, 52},
+ {601, 53},
+ {602, 54},
+ {603, 55},
+ {604, 56},
+ {605, 57},
+ {1000, 58},
+ {1001, 59},
+ {1002, 60},
+ {1003, 61},
+ {1004, 62},
+ {1005, 63},
+ {1006, 64},
+ {1008, 65},
+ {1009, 66},
+ {1010, 67},
+ {1011, 68},
+ {1015, 69},
+ {2005, 70}
+};
+
+Inter_v6::Inter_v6(GobEngine *vm) : Inter_v5(vm) {
+ setupOpcodes();
+}
+
+void Inter_v6::setupOpcodes() {
+ static const OpcodeDrawEntryV6 opcodesDraw[256] = {
+ /* 00 */
+ OPCODE(o1_loadMult),
+ OPCODE(o2_playMult),
+ OPCODE(o2_freeMultKeys),
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_initCursor),
+ /* 08 */
+ OPCODE(o1_initCursorAnim),
+ OPCODE(o1_clearCursorAnim),
+ OPCODE(o2_setRenderFlags),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ OPCODE(o1_loadAnim),
+ OPCODE(o1_freeAnim),
+ OPCODE(o1_updateAnim),
+ OPCODE(o2_multSub),
+ /* 14 */
+ OPCODE(o2_initMult),
+ OPCODE(o1_freeMult),
+ OPCODE(o1_animate),
+ OPCODE(o2_loadMultObject),
+ /* 18 */
+ OPCODE(o1_getAnimLayerInfo),
+ OPCODE(o1_getObjAnimSize),
+ OPCODE(o1_loadStatic),
+ OPCODE(o1_freeStatic),
+ /* 1C */
+ OPCODE(o2_renderStatic),
+ OPCODE(o2_loadCurLayer),
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ OPCODE(o2_playCDTrack),
+ OPCODE(o2_waitCDTrackEnd),
+ OPCODE(o2_stopCD),
+ OPCODE(o2_readLIC),
+ /* 24 */
+ OPCODE(o2_freeLIC),
+ OPCODE(o2_getCDTrackPos),
+ {NULL, ""},
+ {NULL, ""},
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o2_loadFontToSprite),
+ OPCODE(o1_freeFontToSprite),
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ OPCODE(o2_totSub),
+ OPCODE(o2_switchTotSub),
+ OPCODE(o2_copyVars),
+ OPCODE(o2_pasteVars),
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 48 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 4C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 50 */
+ OPCODE(o2_loadMapObjects),
+ OPCODE(o2_freeGoblins),
+ OPCODE(o2_moveGoblin),
+ OPCODE(o2_writeGoblinPos),
+ /* 54 */
+ OPCODE(o2_stopGoblin),
+ OPCODE(o2_setGoblinState),
+ OPCODE(o2_placeGoblin),
+ {NULL, ""},
+ /* 58 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 5C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 60 */
+ {NULL, ""},
+ OPCODE(o5_deleteFile),
+ {NULL, ""},
+ {NULL, ""},
+ /* 64 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 68 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 6C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 70 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 74 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 78 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 7C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 80 */
+ OPCODE(o4_initScreen),
+ OPCODE(o2_scroll),
+ OPCODE(o2_setScrollOffset),
+ OPCODE(o4_playVmdOrMusic),
+ /* 84 */
+ OPCODE(o2_getImdInfo),
+ OPCODE(o2_openItk),
+ OPCODE(o2_closeItk),
+ OPCODE(o2_setImdFrontSurf),
+ /* 88 */
+ OPCODE(o2_resetImdFrontSurf),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 8C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 90 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 94 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 98 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 9C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* AC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* BC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* CC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* DC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* EC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* FC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""}
+ };
+
+ static const OpcodeFuncEntryV6 opcodesFunc[80] = {
+ /* 00 */
+ OPCODE(o1_callSub),
+ OPCODE(o1_callSub),
+ OPCODE(o1_printTotText),
+ OPCODE(o6_loadCursor),
+ /* 04 */
+ {NULL, ""},
+ OPCODE(o1_switch),
+ OPCODE(o1_repeatUntil),
+ OPCODE(o1_whileDo),
+ /* 08 */
+ OPCODE(o1_if),
+ OPCODE(o6_evaluateStore),
+ OPCODE(o1_loadSpriteToPos),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ OPCODE(o2_printText),
+ OPCODE(o1_loadTot),
+ OPCODE(o1_palLoad),
+ /* 14 */
+ OPCODE(o1_keyFunc),
+ OPCODE(o1_capturePush),
+ OPCODE(o1_capturePop),
+ OPCODE(o2_animPalInit),
+ /* 18 */
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
+ OPCODE(o3_getTotTextItemPart),
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_drawOperations),
+ OPCODE(o1_setcmdCount),
+ /* 20 */
+ OPCODE(o1_return),
+ OPCODE(o1_renewTimeInVars),
+ OPCODE(o1_speakerOn),
+ OPCODE(o1_speakerOff),
+ /* 24 */
+ OPCODE(o1_putPixel),
+ OPCODE(o2_goblinFunc),
+ OPCODE(o2_createSprite),
+ OPCODE(o1_freeSprite),
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o1_returnTo),
+ OPCODE(o1_loadSpriteContent),
+ OPCODE(o1_copySprite),
+ OPCODE(o1_fillRect),
+ /* 34 */
+ OPCODE(o1_drawLine),
+ OPCODE(o1_strToLong),
+ OPCODE(o1_invalidate),
+ OPCODE(o1_setBackDelta),
+ /* 38 */
+ OPCODE(o1_playSound),
+ OPCODE(o2_stopSound),
+ OPCODE(o2_loadSound),
+ OPCODE(o1_freeSoundSlot),
+ /* 3C */
+ OPCODE(o1_waitEndPlay),
+ OPCODE(o1_playComposition),
+ OPCODE(o2_getFreeMem),
+ OPCODE(o2_checkData),
+ /* 40 */
+ {NULL, ""},
+ OPCODE(o1_prepareStr),
+ OPCODE(o1_insertStr),
+ OPCODE(o1_cutStr),
+ /* 44 */
+ OPCODE(o1_strstr),
+ OPCODE(o5_istrlen),
+ OPCODE(o1_setMousePos),
+ OPCODE(o1_setFrameRate),
+ /* 48 */
+ OPCODE(o1_animatePalette),
+ OPCODE(o1_animateCursor),
+ OPCODE(o1_blitCursor),
+ OPCODE(o1_loadFont),
+ /* 4C */
+ OPCODE(o1_freeFont),
+ OPCODE(o2_readData),
+ OPCODE(o2_writeData),
+ OPCODE(o1_manageDataFile),
+ };
+
+ static const OpcodeGoblinEntryV6 opcodesGoblin[71] = {
+ /* 00 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 08 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 14 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 18 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 24 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ };
+
+ _opcodesDrawV6 = opcodesDraw;
+ _opcodesFuncV6 = opcodesFunc;
+ _opcodesGoblinV6 = opcodesGoblin;
+}
+
+void Inter_v6::executeDrawOpcode(byte i) {
+ debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
+ i, i, getOpcodeDrawDesc(i));
+
+ OpcodeDrawProcV6 op = _opcodesDrawV6[i].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeDraw: %d", i);
+ else
+ (this->*op) ();
+}
+
+bool Inter_v6::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
+ debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d",
+ i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile,
+ (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData),
+ (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4));
+
+ if ((i > 4) || (j > 15)) {
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ return false;
+ }
+
+ OpcodeFuncProcV6 op = _opcodesFuncV6[i*16 + j].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ else
+ return (this->*op) (params);
+
+ return false;
+}
+
+void Inter_v6::executeGoblinOpcode(int i, OpGobParams &params) {
+ debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
+ i, i, getOpcodeGoblinDesc(i));
+
+ OpcodeGoblinProcV6 op = NULL;
+
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i) {
+ op = _opcodesGoblinV6[_goblinFuncLookUp[j][1]].proc;
+ break;
+ }
+
+ _vm->_global->_inter_execPtr -= 2;
+
+ if (op == NULL) {
+ warning("unimplemented opcodeGoblin: %d", i);
+
+ int16 paramCount = load16();
+ _vm->_global->_inter_execPtr += paramCount * 2;
+ } else {
+ params.extraData = i;
+
+ (this->*op) (params);
+ }
+}
+
+const char *Inter_v6::getOpcodeDrawDesc(byte i) {
+ return _opcodesDrawV6[i].desc;
+}
+
+const char *Inter_v6::getOpcodeFuncDesc(byte i, byte j) {
+ if ((i > 4) || (j > 15))
+ return "";
+
+ return _opcodesFuncV6[i*16 + j].desc;
+}
+
+const char *Inter_v6::getOpcodeGoblinDesc(int i) {
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i)
+ return _opcodesGoblinV6[_goblinFuncLookUp[j][1]].desc;
+ return "";
+}
+
+bool Inter_v6::o6_loadCursor(OpFuncParams &params) {
+ Game::TotResItem *itemPtr;
+ int16 width, height;
+ byte *dataBuf;
+ int32 offset;
+ int16 id;
+ int8 index;
+
+ id = load16();
+
+ if (id == -1) {
+ byte str[10];
+
+ for (int i = 0; i < 9; i++)
+ str[i] = *_vm->_global->_inter_execPtr++;
+
+ str[9] = '\0';
+
+ uint16 var1 = load16();
+ int8 var2 = *_vm->_global->_inter_execPtr++;
+
+ warning("Urban Stub: loadCursor %d: \"%s\", %d, %d", id, str, var1, var2);
+
+ } else if (id == -2) {
+
+ uint16 var1 = load16();
+ uint16 var2 = load16();
+ int8 var3 = *_vm->_global->_inter_execPtr++;
+
+ warning("Urban Stub: loadCursor %d: %d, %d, %d", id, var1, var2, var3);
+
+ } else {
+ index = (int8) *_vm->_global->_inter_execPtr++;
+
+ if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth())
+ return false;
+
+ itemPtr = &_vm->_game->_totResourceTable->items[id];
+ offset = itemPtr->offset;
+
+ if (offset < 0) {
+ offset = (-offset - 1) * 4;
+ dataBuf = _vm->_game->_imFileData +
+ (int32) READ_LE_UINT32(_vm->_game->_imFileData + offset);
+ } else
+ dataBuf = _vm->_game->_totResourceTable->dataPtr + szGame_TotResTable +
+ szGame_TotResItem * _vm->_game->_totResourceTable->itemsCount +
+ offset;
+
+ width = itemPtr->width;
+ height = itemPtr->height;
+
+ _vm->_video->fillRect(_vm->_draw->_cursorSprites,
+ index * _vm->_draw->_cursorWidth, 0,
+ index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1,
+ _vm->_draw->_cursorHeight - 1, 0);
+
+ _vm->_video->drawPackedSprite(dataBuf, width, height,
+ index * _vm->_draw->_cursorWidth, 0, 0, _vm->_draw->_cursorSprites);
+ _vm->_draw->_cursorAnimLow[index] = 0;
+ }
+
+ return false;
+}
+
+bool Inter_v6::o6_evaluateStore(OpFuncParams &params) {
+ byte *savedPos;
+ int16 varOff;
+ int16 token;
+ int16 result;
+ byte loopCount;
+ uint16 var_6, var_A;
+
+ varOff = _vm->_parse->parseVarIndex(&var_6, &var_A);
+
+ if (var_6 != 0) {
+ int16 var_4;
+
+ savedPos = _vm->_global->_inter_execPtr;
+
+ var_4 = _vm->_parse->parseVarIndex(&var_6, 0);
+
+ memcpy(_vm->_inter->_variables->getAddressOff8(varOff),
+ _vm->_inter->_variables->getAddressOff8(var_4), var_6 * 4);
+
+ _vm->_global->_inter_execPtr = savedPos;
+ evalExpr(&var_4);
+
+ return false;
+ }
+
+ if (*_vm->_global->_inter_execPtr == 98) {
+ _vm->_global->_inter_execPtr++;
+ loopCount = *_vm->_global->_inter_execPtr++;
+
+ for (int i = 0; i < loopCount; i++) {
+ uint8 c = *_vm->_global->_inter_execPtr++;
+ uint16 n = load16();
+
+ memset(_vm->_inter->_variables->getAddressOff8(varOff), c, n);
+
+ varOff += n;
+ }
+
+ return false;
+
+ } else if (*_vm->_global->_inter_execPtr == 99) {
+ _vm->_global->_inter_execPtr++;
+ loopCount = *_vm->_global->_inter_execPtr++;
+ } else
+ loopCount = 1;
+
+ for (int i = 0; i < loopCount; i++) {
+ token = evalExpr(&result);
+ switch (var_A) {
+ case 16:
+ case 18:
+ WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal);
+ break;
+
+ case 17:
+ case 27:
+ WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal);
+ break;
+
+ case 23:
+ case 26:
+ WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal);
+ break;
+
+ case 24:
+ WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal);
+ break;
+
+ case 25:
+ case 28:
+ if (token == 20)
+ WRITE_VARO_UINT8(varOff, result);
+ else
+ WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr);
+ break;
+ }
+ }
+
+ return false;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp
index 75867aaa6c..bb259800c0 100644
--- a/engines/gob/map.cpp
+++ b/engines/gob/map.cpp
@@ -77,10 +77,10 @@ Map::~Map() {
}
void Map::placeItem(int16 x, int16 y, int16 id) {
- if ((_itemsMap[y][x] & 0xFF00) != 0)
- _itemsMap[y][x] = (_itemsMap[y][x] & 0xFF00) | id;
+ if ((getItem(x, y) & 0xFF00) != 0)
+ setItem(x, y, (getItem(x, y) & 0xFF00) | id);
else
- _itemsMap[y][x] = (_itemsMap[y][x] & 0x00FF) | (id << 8);
+ setItem(x, y, (getItem(x, y) & 0x00FF) | (id << 8));
}
enum {
diff --git a/engines/gob/map.h b/engines/gob/map.h
index 8a94de8da9..4a211f205d 100644
--- a/engines/gob/map.h
+++ b/engines/gob/map.h
@@ -101,6 +101,9 @@ public:
void loadMapsInitGobs(void);
+ virtual int16 getItem(int x, int y) = 0;
+ virtual void setItem(int x, int y, int16 item) = 0;
+
virtual int8 getPass(int x, int y, int heightOff = -1) = 0;
virtual void setPass(int x, int y, int8 pass, int heightOff = -1) = 0;
@@ -127,6 +130,23 @@ public:
virtual void findNearestToDest(Mult::Mult_Object *obj);
virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y);
+ virtual int16 getItem(int x, int y) {
+ assert(_itemsMap);
+
+ x = CLIP<int>(x, 0, _mapWidth - 1);
+ y = CLIP<int>(y, 0, _mapHeight - 1);
+
+ return _itemsMap[y][x];
+ }
+ virtual void setItem(int x, int y, int16 item) {
+ assert(_itemsMap);
+
+ x = CLIP<int>(x, 0, _mapWidth - 1);
+ y = CLIP<int>(y, 0, _mapHeight - 1);
+
+ _itemsMap[y][x] = item;
+ }
+
virtual int8 getPass(int x, int y, int heightOff = -1) {
if (!_passMap)
return 0;
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 45048a0899..3ec542934f 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -30,6 +30,8 @@ MODULE_OBJS := \
inter_bargon.o \
inter_v3.o \
inter_v4.o \
+ inter_v5.o \
+ inter_v6.o \
map.o \
map_v1.o \
map_v2.o \
@@ -53,6 +55,7 @@ MODULE_OBJS := \
video.o \
video_v1.o \
video_v2.o \
+ video_v6.o \
sound/sound.o \
sound/sounddesc.o \
sound/pcspeaker.o \
diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp
index b9373d48b3..a502e92188 100644
--- a/engines/gob/mult.cpp
+++ b/engines/gob/mult.cpp
@@ -209,7 +209,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
_frame++;
_vm->_util->waitEndFrame();
- } while (!stop && !stopNoClear && !_vm->_quitRequested);
+ } while (!stop && !stopNoClear && !_vm->quit());
if (!stopNoClear) {
if (_animDataAllocated) {
diff --git a/engines/gob/palanim.cpp b/engines/gob/palanim.cpp
index 71e73adf53..4f2e921dcb 100644
--- a/engines/gob/palanim.cpp
+++ b/engines/gob/palanim.cpp
@@ -23,6 +23,7 @@
*
*/
+
#include "gob/gob.h"
#include "gob/palanim.h"
#include "gob/global.h"
@@ -131,7 +132,7 @@ void PalAnim::fade(Video::PalDesc *palDesc, int16 fadeV, int16 allColors) {
bool stop;
int16 i;
- if (_vm->_quitRequested)
+ if (_vm->quit())
return;
_fadeValue = (fadeV < 0) ? -fadeV : 2;
diff --git a/engines/gob/parse.h b/engines/gob/parse.h
index 7d451b5f79..15ec78b57f 100644
--- a/engines/gob/parse.h
+++ b/engines/gob/parse.h
@@ -33,7 +33,7 @@ public:
void skipExpr(char stopToken);
void printExpr(char stopToken);
void printVarIndex(void);
- virtual int16 parseVarIndex(void) = 0;
+ virtual int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0) = 0;
virtual int16 parseValExpr(byte stopToken = 99) = 0;
virtual int16 parseExpr(byte stopToken, byte *resultPtr) = 0;
@@ -60,7 +60,7 @@ public:
Parse_v1(GobEngine *vm);
virtual ~Parse_v1() {}
- virtual int16 parseVarIndex(void);
+ virtual int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0);
virtual int16 parseValExpr(byte stopToken = 99);
virtual int16 parseExpr(byte stopToken, byte *resultPtr);
};
@@ -70,7 +70,7 @@ public:
Parse_v2(GobEngine *vm);
virtual ~Parse_v2() {}
- virtual int16 parseVarIndex(void);
+ virtual int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0);
virtual int16 parseValExpr(byte stopToken = 99);
virtual int16 parseExpr(byte stopToken, byte *resultPtr);
};
diff --git a/engines/gob/parse_v1.cpp b/engines/gob/parse_v1.cpp
index 3c5f90c068..ed8868397a 100644
--- a/engines/gob/parse_v1.cpp
+++ b/engines/gob/parse_v1.cpp
@@ -35,7 +35,7 @@ namespace Gob {
Parse_v1::Parse_v1(GobEngine *vm) : Parse(vm) {
}
-int16 Parse_v1::parseVarIndex() {
+int16 Parse_v1::parseVarIndex(uint16 *arg_0, uint16 *arg_4) {
int16 temp2;
byte *arrDesc;
int16 dim;
diff --git a/engines/gob/parse_v2.cpp b/engines/gob/parse_v2.cpp
index a2e6b8fb37..347a253204 100644
--- a/engines/gob/parse_v2.cpp
+++ b/engines/gob/parse_v2.cpp
@@ -35,7 +35,7 @@ namespace Gob {
Parse_v2::Parse_v2(GobEngine *vm) : Parse_v1(vm) {
}
-int16 Parse_v2::parseVarIndex() {
+int16 Parse_v2::parseVarIndex(uint16 *arg_0, uint16 *arg_4) {
int16 temp2;
byte *arrDesc;
int16 dim;
@@ -44,8 +44,74 @@ int16 Parse_v2::parseVarIndex() {
int16 temp;
int16 offset;
int16 val;
+ uint32 varPos = 0;
operation = *_vm->_global->_inter_execPtr++;
+
+ while ((operation == 14) || (operation == 15)) {
+ if (operation == 14) {
+ uint16 n = _vm->_inter->load16();
+ varPos += n * 4;
+
+ if (arg_0)
+ *arg_0 = READ_LE_UINT16(_vm->_global->_inter_execPtr);
+ if (arg_4)
+ *arg_4 = 14;
+
+ _vm->_global->_inter_execPtr += 2;
+ if (*_vm->_global->_inter_execPtr == 97)
+ _vm->_global->_inter_execPtr++;
+ } else if (operation == 15) {
+ uint16 n = _vm->_inter->load16();
+ varPos += n * 4;
+
+ uint16 var_0C = _vm->_inter->load16();
+ if (arg_0)
+ *arg_0 = var_0C;
+ if (arg_4)
+ *arg_4 = 15;
+
+ uint8 var_A = *_vm->_global->_inter_execPtr++;
+
+ byte *var_12 = _vm->_global->_inter_execPtr;
+ _vm->_global->_inter_execPtr += var_A;
+
+ uint16 var_6 = 0;
+
+ for (int i = 0; i < var_A; i++) {
+ temp2 = parseValExpr(12);
+
+ //uint16 ax = sub_12063(temp2, var_12[i], varPos, 0);
+
+ uint16 ax;
+
+ if (temp2 < 0) {
+ ax = 0;
+ } else if (var_12[i] > temp2) {
+ ax = temp2;
+ } else {
+ ax = var_12[i] - 1;
+ }
+
+ var_6 = var_6 * var_12[i] + ax;
+ }
+
+ varPos += var_6 * var_0C * 4;
+
+ if (*_vm->_global->_inter_execPtr == 97)
+ _vm->_global->_inter_execPtr++;
+ }
+
+ warning("v5+ Stub: parseVarIndex operation %d, offset %d", operation, varPos);
+
+ operation = *_vm->_global->_inter_execPtr++;
+ }
+
+ if (arg_0)
+ *arg_0 = 0;
+ if (arg_4)
+ *arg_4 = operation;
+
debugC(5, kDebugParser, "var parse = %d", operation);
switch (operation) {
case 16:
@@ -62,24 +128,24 @@ int16 Parse_v2::parseVarIndex() {
offset = arrDesc[dim] * offset + temp2;
}
if (operation == 16)
- return temp + offset;
+ return varPos + temp + offset;
if (operation == 26)
- return (temp + offset) * 4;
+ return varPos + (temp + offset) * 4;
if (operation == 27)
- return (temp + offset) * 2;
+ return varPos + (temp + offset) * 2;
temp *= 4;
offset *= 4;
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
temp += parseValExpr(12);
}
- return offset * _vm->_global->_inter_animDataSize + temp;
+ return varPos + offset * _vm->_global->_inter_animDataSize + temp;
case 17:
- return _vm->_inter->load16() * 2;
+ return varPos + _vm->_inter->load16() * 2;
case 18:
- return _vm->_inter->load16();
+ return varPos + _vm->_inter->load16();
case 23:
case 24:
@@ -93,7 +159,7 @@ int16 Parse_v2::parseVarIndex() {
temp += val;
debugC(5, kDebugParser, "parse subscript = %d", val);
}
- return temp;
+ return varPos + temp;
default:
return 0;
@@ -116,6 +182,7 @@ int16 Parse_v2::parseValExpr(byte stopToken) {
int16 brackPos;
static int16 flag = 0;
int16 oldflag;
+ uint32 varPos = 0;
memset(values, 0, 20 * sizeof(int16));
@@ -130,11 +197,61 @@ int16 Parse_v2::parseValExpr(byte stopToken) {
valPtr = values - 1;
while (1) {
+ operation = *_vm->_global->_inter_execPtr++;
+
+ while ((operation == 14) || (operation == 15)) {
+ if (operation == 14) {
+ uint16 n = _vm->_inter->load16();
+ varPos += n * 4;
+
+ _vm->_global->_inter_execPtr += 2;
+ if (*_vm->_global->_inter_execPtr == 97)
+ _vm->_global->_inter_execPtr++;
+ } else if (operation == 15) {
+ uint16 n = _vm->_inter->load16();
+ varPos += n * 4;
+
+ uint16 var_0C = _vm->_inter->load16();
+ uint8 var_A = *_vm->_global->_inter_execPtr++;
+
+ byte *var_12 = _vm->_global->_inter_execPtr;
+ _vm->_global->_inter_execPtr += var_A;
+
+ uint16 var_6 = 0;
+
+ for (int i = 0; i < var_A; i++) {
+ temp2 = parseValExpr(12);
+
+ //uint16 ax = sub_12063(temp2, var_12[i], varPos, 0);
+
+ uint16 ax;
+
+ if (temp2 < 0) {
+ ax = 0;
+ } else if (var_12[i] > temp2) {
+ ax = temp2;
+ } else {
+ ax = var_12[i] - 1;
+ }
+
+ var_6 = var_6 * var_12[i] + ax;
+ }
+
+ varPos += var_6 * var_0C * 4;
+
+ if (*_vm->_global->_inter_execPtr == 97)
+ _vm->_global->_inter_execPtr++;
+ }
+
+ warning("v5+ Stub: parseValExpr operation %d, offset %d", operation, varPos);
+
+ operation = *_vm->_global->_inter_execPtr++;
+ }
+
stkPos++;
operPtr++;
valPtr++;
- operation = *_vm->_global->_inter_execPtr++;
if ((operation >= 16) && (operation <= 29)) {
*operPtr = 20;
switch (operation) {
@@ -152,29 +269,29 @@ int16 Parse_v2::parseValExpr(byte stopToken) {
offset = arrDesc[dim] * offset + temp2;
}
if (operation == 16)
- *valPtr = (int8) READ_VARO_UINT8(temp + offset);
+ *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset);
else if (operation == 26)
- *valPtr = (uint16) READ_VARO_UINT32(temp * 4 + offset * 4);
+ *valPtr = (uint16) READ_VARO_UINT32(varPos + temp * 4 + offset * 4);
else if (operation == 27)
- *valPtr = READ_VARO_UINT16(temp * 2 + offset * 2);
+ *valPtr = READ_VARO_UINT16(varPos + temp * 2 + offset * 2);
else if (operation == 28) {
_vm->_global->_inter_execPtr++;
temp2 = parseValExpr(12);
- *valPtr = READ_VARO_UINT8(temp * 4 +
+ *valPtr = READ_VARO_UINT8(varPos + temp * 4 +
offset * 4 * _vm->_global->_inter_animDataSize + temp2);
}
break;
case 17:
- *valPtr = READ_VARO_UINT16(_vm->_inter->load16() * 2);
+ *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2);
break;
case 18:
- *valPtr = (int8) READ_VARO_UINT8(_vm->_inter->load16());
+ *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16());
break;
case 19:
- *valPtr = (uint16) READ_LE_UINT32(_vm->_global->_inter_execPtr);
+ *valPtr = (uint16) READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr);
_vm->_global->_inter_execPtr += 4;
break;
@@ -191,14 +308,14 @@ int16 Parse_v2::parseValExpr(byte stopToken) {
break;
case 24:
- *valPtr = READ_VARO_UINT16(_vm->_inter->load16() * 4);
+ *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4);
break;
case 25:
temp = _vm->_inter->load16() * 4;
_vm->_global->_inter_execPtr++;
temp += parseValExpr(12);
- *valPtr = READ_VARO_UINT8(temp);
+ *valPtr = READ_VARO_UINT8(varPos + temp);
break;
case 29:
@@ -373,6 +490,7 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
bool var_1A;
int16 stkPos;
int16 brackStart;
+ uint32 varPos = 0;
memset(operStack, 0, 20);
@@ -381,10 +499,61 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
valPtr = values - 1;
while (1) {
+ operation = *_vm->_global->_inter_execPtr++;
+
+ while ((operation == 14) || (operation == 15)) {
+ if (operation == 14) {
+ uint16 n = _vm->_inter->load16();
+ varPos += n * 4;
+
+ _vm->_global->_inter_execPtr += 2;
+ if (*_vm->_global->_inter_execPtr == 97)
+ _vm->_global->_inter_execPtr++;
+ } else if (operation == 15) {
+ uint16 n = _vm->_inter->load16();
+ varPos += n * 4;
+
+ uint16 var_0C = _vm->_inter->load16();
+ uint8 var_A = *_vm->_global->_inter_execPtr++;
+
+ byte *var_12 = _vm->_global->_inter_execPtr;
+ _vm->_global->_inter_execPtr += var_A;
+
+ uint16 var_6 = 0;
+
+ for (int i = 0; i < var_A; i++) {
+ temp2 = parseValExpr(12);
+
+ //uint16 ax = sub_12063(temp2, var_12[i], varPos, 0);
+
+ uint16 ax;
+
+ if (temp2 < 0) {
+ ax = 0;
+ } else if (var_12[i] > temp2) {
+ ax = temp2;
+ } else {
+ ax = var_12[i] - 1;
+ }
+
+ var_6 = var_6 * var_12[i] + ax;
+ }
+
+ varPos += var_6 * var_0C * 4;
+
+ if (*_vm->_global->_inter_execPtr == 97)
+ _vm->_global->_inter_execPtr++;
+ }
+
+ warning("v5+ Stub: parseExpr operation %d, offset %d", operation, varPos);
+
+ operation = *_vm->_global->_inter_execPtr++;
+ }
+
stkPos++;
operPtr++;
valPtr++;
- operation = *_vm->_global->_inter_execPtr++;
+
if ((operation >= 16) && (operation <= 29)) {
switch (operation) {
case 16:
@@ -402,20 +571,20 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
offset = offset * arrDescPtr[dim] + temp2;
}
if (operation == 16)
- *valPtr = (int8) READ_VARO_UINT8(temp + offset);
+ *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset);
else if (operation == 26)
- *valPtr = READ_VARO_UINT32(temp * 4 + offset * 4);
+ *valPtr = READ_VARO_UINT32(varPos + temp * 4 + offset * 4);
else if (operation == 27)
- *valPtr = (int16) READ_VARO_UINT16(temp * 2 + offset * 2);
+ *valPtr = (int16) READ_VARO_UINT16(varPos + temp * 2 + offset * 2);
else if (operation == 28) {
*valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(
- temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0),
+ varPos + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
temp2 = parseValExpr(12);
*operPtr = 20;
- *valPtr = READ_VARO_UINT8(temp * 4 +
+ *valPtr = READ_VARO_UINT8(varPos + temp * 4 +
offset * 4 * _vm->_global->_inter_animDataSize + temp2);
}
}
@@ -423,17 +592,17 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
case 17:
*operPtr = 20;
- *valPtr = (int16) READ_VARO_UINT16(_vm->_inter->load16() * 2);
+ *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2);
break;
case 18:
*operPtr = 20;
- *valPtr = (int8) READ_VARO_UINT8(_vm->_inter->load16());
+ *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16());
break;
case 19:
*operPtr = 20;
- *valPtr = READ_LE_UINT32(_vm->_global->_inter_execPtr);
+ *valPtr = READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr);
_vm->_global->_inter_execPtr += 4;
break;
@@ -461,18 +630,18 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
case 24:
*operPtr = 20;
- *valPtr = (int16) READ_VARO_UINT16(_vm->_inter->load16() * 4);
+ *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4);
break;
case 25:
*operPtr = 22;
temp = _vm->_inter->load16() * 4;
- *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp, 0), kInterVar);
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(varPos + temp, 0), kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
temp += parseValExpr(12);
*operPtr = 20;
- *valPtr = READ_VARO_UINT8(temp);
+ *valPtr = READ_VARO_UINT8(varPos + temp);
}
break;
diff --git a/engines/gob/saveload.cpp b/engines/gob/saveload.cpp
index fa9f8ea7a9..e3212ac8ff 100644
--- a/engines/gob/saveload.cpp
+++ b/engines/gob/saveload.cpp
@@ -513,7 +513,7 @@ bool StagedSave::read() {
return false;
}
- uint32 saveSize = getSize();
+ int32 saveSize = getSize();
if (in->size() != saveSize) {
warning("Wrong size (%d != %d)", in->size(), saveSize);
return false;
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index 2d2bf8e043..7b93003791 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -369,7 +369,7 @@ void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) {
if (stopComp)
_blaster->endComposition();
- while (_blaster->isPlaying() && !_vm->_quitRequested) {
+ while (_blaster->isPlaying() && !_vm->quit()) {
if (interruptible && (_vm->_util->checkKey() == 0x11B)) {
WRITE_VAR(57, (uint32) -1);
return;
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 4987426fe0..fcf19f03dd 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -23,7 +23,6 @@
*
*/
-#include "common/events.h"
#include "gob/gob.h"
#include "gob/util.h"
@@ -72,7 +71,7 @@ void Util::longDelay(uint16 msecs) {
_vm->_video->waitRetrace();
processInput();
delay(15);
- } while (!_vm->_quitRequested &&
+ } while (!_vm->quit() &&
((g_system->getMillis() * _vm->_global->_speedFactor) < time));
}
@@ -118,9 +117,6 @@ void Util::processInput(bool scroll) {
break;
case Common::EVENT_KEYUP:
break;
- case Common::EVENT_QUIT:
- _vm->_quitRequested = true;
- break;
default:
break;
}
@@ -238,7 +234,9 @@ void Util::getMouseState(int16 *pX, int16 *pY, int16 *pButtons) {
}
void Util::setMousePos(int16 x, int16 y) {
- g_system->warpMouse(x + _vm->_video->_screenDeltaX, y + _vm->_video->_screenDeltaY);
+ x = CLIP<int>(x + _vm->_video->_screenDeltaX, 0, _vm->_width - 1);
+ y = CLIP<int>(y + _vm->_video->_screenDeltaY, 0, _vm->_height - 1);
+ g_system->warpMouse(x, y);
}
void Util::waitMouseUp(void) {
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 1338885588..e6baf9a67d 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -194,6 +194,15 @@ public:
virtual ~Video_v2() {}
};
+class Video_v6 : public Video_v2 {
+public:
+ virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight,
+ int16 x, int16 y, int16 transp, SurfaceDesc *destDesc);
+
+ Video_v6(GobEngine *vm);
+ virtual ~Video_v6() {}
+};
+
class VideoDriver {
public:
VideoDriver() {}
diff --git a/engines/gob/video_v6.cpp b/engines/gob/video_v6.cpp
new file mode 100644
index 0000000000..434406265e
--- /dev/null
+++ b/engines/gob/video_v6.cpp
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/endian.h"
+
+#include "gob/gob.h"
+#include "gob/video.h"
+
+namespace Gob {
+
+Video_v6::Video_v6(GobEngine *vm) : Video_v2(vm) {
+}
+
+char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight,
+ int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) {
+ if (!destDesc)
+ return 1;
+
+ _vm->validateVideoMode(destDesc->_vidMode);
+
+ if (sprBuf[0] != 1)
+ return 0;
+
+ if (sprBuf[1] != 3)
+ return 0;
+
+ sprBuf += 2;
+
+ srcWidth = READ_LE_UINT16(sprBuf);
+ sprBuf += 2;
+ srcHeight = READ_LE_UINT16(sprBuf);
+ sprBuf += 2;
+
+ if (sprBuf[0] == 0) {
+ SurfaceDesc sourceDesc(0x13, srcWidth, srcHeight, sprBuf + 3);
+ Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1,
+ srcHeight - 1, x, y, transp);
+ return 1;
+ } else {
+ warning("Urban Stub: spriteUncompressor()");
+ return 0;
+ }
+
+ return 1;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index aa47e6cf84..daf7bdd801 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -23,6 +23,7 @@
*
*/
+
#include "gob/videoplayer.h"
#include "gob/global.h"
#include "gob/util.h"
@@ -568,7 +569,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
_vm->_util->processInput();
- if (_vm->_quitRequested) {
+ if (_vm->quit()) {
_primaryVideo->getVideo()->disableSound();
return true;
}
diff --git a/engines/igor/parts/part_22.cpp b/engines/igor/parts/part_22.cpp
index 9727ae3e1a..7a7c26d477 100644
--- a/engines/igor/parts/part_22.cpp
+++ b/engines/igor/parts/part_22.cpp
@@ -74,7 +74,9 @@ void IgorEngine::PART_22_ACTION_101() {
void IgorEngine::PART_22_ACTION_102() {
_walkDataCurrentIndex = 0;
_walkCurrentFrame = 1;
- for (int i = 9; i >= 0; --i) {
+ int i = 0;
+
+ for (i = 9; i >= 0; --i) {
WalkData *wd = &_walkData[0];
wd->setPos(138, 123, 1, _walkCurrentFrame);
WalkData::setNextFrame(1, _walkCurrentFrame);
@@ -89,7 +91,7 @@ void IgorEngine::PART_22_ACTION_102() {
moveIgor(wd->posNum, wd->frameNum);
waitForTimer(15);
}
- int i = 16;
+ i = 16;
do {
if (compareGameTick(1, 16)) {
memcpy(_screenTextLayer + (i * 8 + 16) * 320, _screenLayer1 + (128 - i * 8) * 320, (i * 8 + 16) * 320);
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 0c6eb29665..7a377471c1 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -397,6 +397,18 @@ const KYRAGameDescription adGameDescs[] = {
KYRA2_FLOPPY_FLAGS
},
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA2_FLOPPY_FLAGS
+ },
+
{ // CD version
{
"kyra2",
@@ -1052,11 +1064,23 @@ public:
return "The Legend of Kyrandia (C) Westwood Studios";
}
+ bool hasFeature(MetaEngineFeature f) const;
bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
-
SaveStateList listSaves(const char *target) const;
+ void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
+bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSupportsMetaInfos) ||
+ (f == kSupportsThumbnails);
+}
+
bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const KYRAGameDescription *gd = (const KYRAGameDescription *)desc;
bool res = true;
@@ -1107,7 +1131,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const {
Common::StringList filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
@@ -1117,8 +1141,13 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) {
- if (Kyra::KyraEngine_v1::readSaveHeader(in, header) == Kyra::KyraEngine_v1::kRSHENoError)
+ if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) {
+ // Workaround for old savegames using 'German' as description for kyra3 start savegame (slot 0)
+ if (slotNum == 0 && header.gameID == Kyra::GI_KYRA3)
+ header.description = "New Game";
+
saveList.push_back(SaveStateDescriptor(slotNum, header.description, *file));
+ }
delete in;
}
}
@@ -1127,8 +1156,69 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const {
return saveList;
}
+void KyraMetaEngine::removeSaveState(const char *target, int slot) const {
+ // Slot 0 can't be deleted, it's for restarting the game(s)
+ if (slot == 0)
+ return;
+
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot);
+
+ saveFileMan->removeSavefile(filename.c_str());
+
+ Common::StringList filenames;
+ Common::String pattern = target;
+ pattern += ".???";
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ // Rename every slot greater than the deleted slot,
+ // Also do not rename quicksaves.
+ if (slotNum > slot && slotNum < 990) {
+ // FIXME: Our savefile renaming done here is inconsitent with what we do in
+ // GUI_v2::deleteMenu. While here we rename every slot with a greater equal
+ // number of the deleted slot to deleted slot, deleted slot + 1 etc.,
+ // we only rename the following slots in GUI_v2::deleteMenu until a slot
+ // is missing.
+ saveFileMan->renameSavefile(file->c_str(), filename.c_str());
+
+ filename = Kyra::KyraEngine_v1::getSavegameFilename(target, ++slot);
+ }
+ }
+
+}
+
+SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot);
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
+
+ if (in) {
+ Kyra::KyraEngine_v1::SaveHeader header;
+ Kyra::KyraEngine_v1::kReadSaveHeaderError error;
+
+ error = Kyra::KyraEngine_v1::readSaveHeader(in, true, header);
+ delete in;
+
+ if (error == Kyra::KyraEngine_v1::kRSHENoError) {
+ SaveStateDescriptor desc(slot, header.description, filename);
+
+ desc.setDeletableFlag(slot != 0);
+ desc.setThumbnail(header.thumbnail);
+
+ return desc;
+ }
+ }
+
+ return SaveStateDescriptor();
+}
+
#if PLUGIN_ENABLED_DYNAMIC(KYRA)
REGISTER_PLUGIN_DYNAMIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine);
#else
REGISTER_PLUGIN_STATIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine);
#endif
+
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index 96ea233025..6864bd9c4d 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -311,8 +311,6 @@ void GUI::updateSaveList() {
s1 -= '0';
s2 -= '0';
s3 -= '0';
- if (s1 == 9 && s2 == 9 && s3 == 9)
- continue;
_saveSlots.push_back(s1*100+s2*10+s3);
}
@@ -378,9 +376,6 @@ bool MainMenu::getInput() {
while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _vm->quitGame();
- break;
case Common::EVENT_LBUTTONUP:
return true;
default:
diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h
index 1361bdb399..7db8f52f16 100644
--- a/engines/kyra/gui.h
+++ b/engines/kyra/gui.h
@@ -32,6 +32,8 @@
#include "common/array.h"
#include "common/func.h"
+#include "graphics/surface.h"
+
namespace Kyra {
#define BUTTON_FUNCTOR(type, x, y) Button::Callback(new Common::Functor1Mem<Button*, int, type>(x, y))
@@ -153,6 +155,8 @@ public:
void processHighlights(Menu &menu, int mouseX, int mouseY);
+ // utilities for thumbnail creation
+ virtual void createScreenThumbnail(Graphics::Surface &dst) = 0;
protected:
KyraEngine_v1 *_vm;
Screen *_screen;
diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp
index 7d56743af5..a1391320f4 100644
--- a/engines/kyra/gui_hof.cpp
+++ b/engines/kyra/gui_hof.cpp
@@ -33,6 +33,8 @@
#include "common/savefile.h"
+#include "graphics/scaler.h"
+
namespace Kyra {
void KyraEngine_HoF::loadButtonShapes() {
@@ -512,7 +514,7 @@ void KyraEngine_HoF::bookLoop() {
showBookPage();
_bookShown = true;
- while (_bookShown && !_quitFlag) {
+ while (_bookShown && !quit()) {
checkInput(buttonList);
removeInputTop();
@@ -793,6 +795,12 @@ int GUI_HoF::optionsButton(Button *button) {
#pragma mark -
+void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) {
+ uint8 screenPal[768];
+ _screen->getRealPalette(1, screenPal);
+ ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, screenPal);
+}
+
void GUI_HoF::setupPalette() {
memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
@@ -996,7 +1004,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) {
if (_vm->_lang != lang) {
_reloadTemporarySave = true;
- _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 2 Savegame");
+ _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 2 Savegame", 0);
_vm->loadCCodeBuffer("C_CODE.XXX");
if (_vm->_flags.isTalkie)
_vm->loadOptionsBuffer("OPTIONS.XXX");
diff --git a/engines/kyra/gui_hof.h b/engines/kyra/gui_hof.h
index f64336a8f6..a9c0426a2b 100644
--- a/engines/kyra/gui_hof.h
+++ b/engines/kyra/gui_hof.h
@@ -41,6 +41,8 @@ public:
void initStaticData();
int optionsButton(Button *button);
+
+ void createScreenThumbnail(Graphics::Surface &dst);
private:
const char *getMenuTitle(const Menu &menu);
const char *getMenuItemTitle(const MenuItem &menuItem);
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index 47ce698e50..4efffb0eda 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -34,9 +34,10 @@
#include "common/config-manager.h"
#include "common/savefile.h"
-#include "common/events.h"
#include "common/system.h"
+#include "graphics/scaler.h"
+
namespace Kyra {
void KyraEngine_LoK::initMainButtonList() {
@@ -199,6 +200,18 @@ GUI_LoK::~GUI_LoK() {
delete[] _menu;
}
+void GUI_LoK::createScreenThumbnail(Graphics::Surface &dst) {
+ uint8 *screen = new uint8[Screen::SCREEN_W*Screen::SCREEN_H];
+ if (screen) {
+ _screen->queryPageFromDisk("SEENPAGE.TMP", 0, screen);
+
+ uint8 screenPal[768];
+ _screen->getRealPalette(2, screenPal);
+ ::createThumbnail(&dst, screen, Screen::SCREEN_W, Screen::SCREEN_H, screenPal);
+ }
+ delete[] screen;
+}
+
int GUI_LoK::processButtonList(Button *list, uint16 inputFlag, int8 mouseWheel) {
while (list) {
if (list->flags & 8) {
@@ -460,7 +473,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) {
updateAllMenuButtons();
}
- while (_displayMenu && !_vm->_quitFlag) {
+ while (_displayMenu && !_vm->quit()) {
Common::Point mouse = _vm->getMousePos();
processHighlights(_menu[_toplevelMenu], mouse.x, mouse.y);
processButtonList(_menuButtonList, 0, 0);
@@ -485,9 +498,6 @@ void GUI_LoK::getInput() {
_mouseWheel = 0;
while (_vm->_eventMan->pollEvent(event)) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _vm->quitGame();
- break;
case Common::EVENT_LBUTTONDOWN:
_vm->_mousePressFlag = true;
break;
@@ -583,7 +593,7 @@ int GUI_LoK::saveGameMenu(Button *button) {
_displaySubMenu = true;
_cancelSubMenu = false;
- while (_displaySubMenu && !_vm->_quitFlag) {
+ while (_displaySubMenu && !_vm->quit()) {
getInput();
Common::Point mouse = _vm->getMousePos();
processHighlights(_menu[2], mouse.x, mouse.y);
@@ -632,7 +642,7 @@ int GUI_LoK::loadGameMenu(Button *button) {
_vm->_gameToLoad = -1;
- while (_displaySubMenu && !_vm->_quitFlag) {
+ while (_displaySubMenu && !_vm->quit()) {
getInput();
Common::Point mouse = _vm->getMousePos();
processHighlights(_menu[2], mouse.x, mouse.y);
@@ -720,7 +730,7 @@ int GUI_LoK::saveGame(Button *button) {
}
redrawTextfield();
- while (_displaySubMenu && !_vm->_quitFlag) {
+ while (_displaySubMenu && !_vm->quit()) {
getInput();
updateSavegameString();
Common::Point mouse = _vm->getMousePos();
@@ -736,8 +746,12 @@ int GUI_LoK::saveGame(Button *button) {
} else {
if (_savegameOffset == 0 && _vm->_gameToLoad == 0)
_vm->_gameToLoad = getNextSavegameSlot();
- if (_vm->_gameToLoad > 0)
- _vm->saveGame(_vm->getSavegameFilename(_vm->_gameToLoad), _savegameName);
+ if (_vm->_gameToLoad > 0) {
+ Graphics::Surface thumb;
+ createScreenThumbnail(thumb);
+ _vm->saveGame(_vm->getSavegameFilename(_vm->_gameToLoad), _savegameName, &thumb);
+ thumb.free();
+ }
}
return 0;
@@ -796,7 +810,7 @@ bool GUI_LoK::quitConfirm(const char *str) {
_displaySubMenu = true;
_cancelSubMenu = true;
- while (_displaySubMenu && !_vm->_quitFlag) {
+ while (_displaySubMenu && !_vm->quit()) {
getInput();
Common::Point mouse = _vm->getMousePos();
processHighlights(_menu[1], mouse.x, mouse.y);
@@ -862,7 +876,7 @@ int GUI_LoK::gameControlsMenu(Button *button) {
_displaySubMenu = true;
_cancelSubMenu = false;
- while (_displaySubMenu && !_vm->_quitFlag) {
+ while (_displaySubMenu && !_vm->quit()) {
getInput();
Common::Point mouse = _vm->getMousePos();
processHighlights(_menu[5], mouse.x, mouse.y);
diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h
index 16b7ef9183..0ce718d7a7 100644
--- a/engines/kyra/gui_lok.h
+++ b/engines/kyra/gui_lok.h
@@ -103,6 +103,8 @@ public:
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel);
int buttonMenuCallback(Button *caller);
+
+ void createScreenThumbnail(Graphics::Surface &dst);
private:
void initStaticResource();
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index 6822b303c3..72f214f001 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -33,6 +33,8 @@
#include "common/savefile.h"
+#include "graphics/scaler.h"
+
namespace Kyra {
void KyraEngine_MR::loadButtonShapes() {
@@ -868,7 +870,7 @@ void KyraEngine_MR::processAlbum() {
albumNewPage();
_album.running = true;
- while (_album.running && !_quitFlag) {
+ while (_album.running && !quit()) {
updateInput();
checkInput(buttonList);
removeInputTop();
@@ -1138,6 +1140,12 @@ int KyraEngine_MR::albumClose(Button *caller) {
GUI_MR::GUI_MR(KyraEngine_MR *vm) : GUI_v2(vm), _vm(vm), _screen(vm->_screen) {
}
+void GUI_MR::createScreenThumbnail(Graphics::Surface &dst) {
+ uint8 screenPal[768];
+ _screen->getRealPalette(0, screenPal);
+ ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, screenPal);
+}
+
void GUI_MR::flagButtonEnable(Button *button) {
if (!button)
return;
@@ -1450,7 +1458,7 @@ int GUI_MR::gameOptions(Button *caller) {
if (_vm->_lang != lang) {
_reloadTemporarySave = true;
- _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 3 Savegame");
+ _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 3 Savegame", 0);
if (!_vm->loadLanguageFile("ITEMS.", _vm->_itemFile))
error("Couldn't load ITEMS");
if (!_vm->loadLanguageFile("SCORE.", _vm->_scoreFile))
diff --git a/engines/kyra/gui_mr.h b/engines/kyra/gui_mr.h
index 5bd3569031..a78d0559a6 100644
--- a/engines/kyra/gui_mr.h
+++ b/engines/kyra/gui_mr.h
@@ -47,6 +47,8 @@ public:
int redrawButtonCallback(Button *button);
int optionsButton(Button *button);
+
+ void createScreenThumbnail(Graphics::Surface &dst);
private:
void getInput();
diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp
index e4cec760fa..077e49ebcf 100644
--- a/engines/kyra/gui_v2.cpp
+++ b/engines/kyra/gui_v2.cpp
@@ -35,6 +35,7 @@ namespace Kyra {
GUI_v2::GUI_v2(KyraEngine_v2 *vm) : GUI(vm), _vm(vm), _screen(vm->screen_v2()) {
_backUpButtonList = _unknownButtonList = 0;
_buttonListChanged = false;
+ _lastScreenUpdate = 0;
_currentMenu = 0;
_isDeathMenu = false;
@@ -618,7 +619,12 @@ int GUI_v2::saveMenu(Button *caller) {
restorePage1(_vm->_screenBuffer);
restorePalette();
- _vm->saveGame(_vm->getSavegameFilename(_saveSlot), _saveDescription);
+
+ Graphics::Surface thumb;
+ createScreenThumbnail(thumb);
+ _vm->saveGame(_vm->getSavegameFilename(_saveSlot), _saveDescription, &thumb);
+ thumb.free();
+
_displayMenu = false;
_madeSave = true;
@@ -762,6 +768,7 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8
x2 -= getCharWidth(buffer[curPos]);
drawTextfieldBlock(x2, y2, c3);
_screen->updateScreen();
+ _lastScreenUpdate = _vm->_system->getMillis();
} else if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127 && curPos < bufferSize) {
if (x2 + getCharWidth(_keyPressed.ascii) + 7 < 0x11F) {
buffer[curPos] = _keyPressed.ascii;
@@ -771,6 +778,7 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8
drawTextfieldBlock(x2, y2, c3);
++curPos;
_screen->updateScreen();
+ _lastScreenUpdate = _vm->_system->getMillis();
}
}
@@ -818,17 +826,15 @@ int GUI_v2::getCharWidth(uint8 c) {
void GUI_v2::checkTextfieldInput() {
Common::Event event;
+ uint32 now = _vm->_system->getMillis();
+
bool running = true;
int keys = 0;
while (_vm->_eventMan->pollEvent(event) && running) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _vm->_quitFlag = true;
- break;
-
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL)
- _vm->_quitFlag = true;
+ _vm->quitGame();
else
_keyPressed = event.kbd;
running = false;
@@ -848,6 +854,7 @@ void GUI_v2::checkTextfieldInput() {
_vm->_mouseX = pos.x;
_vm->_mouseY = pos.y;
_screen->updateScreen();
+ _lastScreenUpdate = now;
} break;
default:
@@ -855,7 +862,13 @@ void GUI_v2::checkTextfieldInput() {
}
}
+ if (now - _lastScreenUpdate > 50) {
+ _vm->_system->updateScreen();
+ _lastScreenUpdate = now;
+ }
+
processButtonList(_menuButtonList, keys | 0x8000, 0);
+ _vm->_system->delayMillis(3);
}
void GUI_v2::drawTextfieldBlock(int x, int y, uint8 c) {
diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h
index 60b7f0ab86..88861ff905 100644
--- a/engines/kyra/gui_v2.h
+++ b/engines/kyra/gui_v2.h
@@ -213,6 +213,7 @@ protected:
// savename menu
bool _finishNameInput, _cancelNameInput;
Common::KeyState _keyPressed;
+ uint32 _lastScreenUpdate;
const char *nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 c2, uint8 c3, int bufferSize);
int finishSavename(Button *caller);
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index 33a8af91f1..76d6f6ea05 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -306,8 +306,10 @@ int KyraEngine_HoF::go() {
_res->loadFileList(_ingamePakList, _ingamePakListSize);
}
- if (_flags.platform == Common::kPlatformPC98)
+ if (_flags.platform == Common::kPlatformPC98) {
_res->loadPakFile("AUDIO.PAK");
+ _sound->loadSoundFile("sound.dat");
+ }
}
_menuDirectlyToLoad = (_menuChoice == 3) ? true : false;
@@ -434,7 +436,7 @@ void KyraEngine_HoF::startup() {
if (_gameToLoad == -1) {
snd_playWanderScoreViaMap(52, 1);
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
- saveGame(getSavegameFilename(0), "New Game");
+ saveGame(getSavegameFilename(0), "New Game", 0);
} else {
loadGame(getSavegameFilename(_gameToLoad));
}
@@ -452,17 +454,21 @@ void KyraEngine_HoF::startup() {
void KyraEngine_HoF::runLoop() {
_screen->updateScreen();
- _quitFlag = false;
_runFlag = true;
- while (!_quitFlag && _runFlag) {
+ while (!quit() && _runFlag) {
if (_deathHandler >= 0) {
removeHandItem();
delay(5);
_drawNoShapeFlag = 0;
_gui->optionsButton(0);
_deathHandler = -1;
+
+ if (!_runFlag || !quit())
+ break;
}
+ checkAutosave();
+
if (_system->getMillis() > _nextIdleAnim)
showIdleAnim();
@@ -1578,10 +1584,14 @@ void KyraEngine_HoF::snd_playSoundEffect(int track, int volume) {
int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]);
if (vocIndex != -1)
_sound->voicePlay(_ingameSoundList[vocIndex], true);
- else if (_flags.platform != Common::kPlatformFMTowns)
+ else if (_flags.platform == Common::kPlatformPC)
+ KyraEngine_v1::snd_playSoundEffect(track);
+
// TODO ?? Maybe there is a way to let users select whether they want
// voc, midi or adl sfx (even though it makes no sense to choose anything but voc).
- KyraEngine_v1::snd_playSoundEffect(track);
+ // The PC-98 version has support for non-pcm sound effects, but only for tracks
+ // which also have voc files. The syntax would be:
+ // KyraEngine_v1::snd_playSoundEffect(vocIndex);
}
#pragma mark -
@@ -1620,7 +1630,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run, int delayTime, in
_invWsa.timer = _system->getMillis();
if (run) {
- while (_invWsa.running && !skipFlag() && !_quitFlag) {
+ while (_invWsa.running && !skipFlag() && !quit()) {
update();
_system->delayMillis(10);
}
@@ -1994,7 +2004,7 @@ void KyraEngine_HoF::playTim(const char *filename) {
return;
_tim->resetFinishedFlag();
- while (!_quitFlag && !_tim->finished()) {
+ while (!quit() && !_tim->finished()) {
_tim->exec(tim, 0);
if (_chatText)
updateWithText();
diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h
index f6e887c648..dc4161f0c1 100644
--- a/engines/kyra/kyra_hof.h
+++ b/engines/kyra/kyra_hof.h
@@ -907,7 +907,7 @@ protected:
int _dbgPass;
// save/load specific
- void saveGame(const char *fileName, const char *saveName);
+ void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail);
void loadGame(const char *fileName);
};
diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp
index c852f6e3ee..f71cc8f409 100644
--- a/engines/kyra/kyra_lok.cpp
+++ b/engines/kyra/kyra_lok.cpp
@@ -26,7 +26,6 @@
#include "kyra/kyra_lok.h"
#include "common/file.h"
-#include "common/events.h"
#include "common/system.h"
#include "common/savefile.h"
@@ -119,8 +118,12 @@ KyraEngine_LoK::~KyraEngine_LoK() {
delete[] _characterList;
+ delete[] _roomTable;
+
delete[] _movFacingTable;
+ delete[] _defaultShapeTable;
+
delete[] _gui->_scrollUpButton.data0ShapePtr;
delete[] _gui->_scrollUpButton.data1ShapePtr;
delete[] _gui->_scrollUpButton.data2ShapePtr;
@@ -300,7 +303,7 @@ int KyraEngine_LoK::go() {
if (_gameToLoad == -1) {
setGameFlag(0xEF);
seq_intro();
- if (_quitFlag)
+ if (quit())
return 0;
if (_skipIntroFlag && _abortIntroFlag)
resetGameFlag(0xEF);
@@ -388,7 +391,7 @@ void KyraEngine_LoK::startup() {
_gui->buttonMenuCallback(0);
_menuDirectlyToLoad = false;
} else
- saveGame(getSavegameFilename(0), "New game");
+ saveGame(getSavegameFilename(0), "New game", 0);
} else {
_screen->setFont(Screen::FID_8_FNT);
loadGame(getSavegameFilename(_gameToLoad));
@@ -399,10 +402,12 @@ void KyraEngine_LoK::startup() {
void KyraEngine_LoK::mainLoop() {
debugC(9, kDebugLevelMain, "KyraEngine_LoK::mainLoop()");
- while (!_quitFlag) {
+ while (!quit()) {
int32 frameTime = (int32)_system->getMillis();
_skipFlag = false;
+ checkAutosave();
+
if (_currentCharacter->sceneId == 210) {
updateKyragemFading();
if (seq_playEnd() && _deathHandler != 8)
@@ -444,7 +449,7 @@ void KyraEngine_LoK::mainLoop() {
}
void KyraEngine_LoK::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) {
- while (_system->getMillis() < timestamp && !_quitFlag) {
+ while (_system->getMillis() < timestamp && !quit()) {
if (updateTimers)
_timer->update();
@@ -470,13 +475,13 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) {
else {
char savegameName[14];
sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0');
- saveGame(saveLoadSlot, savegameName);
+ saveGame(saveLoadSlot, savegameName, 0);
}
} else if (event.kbd.flags == Common::KBD_CTRL) {
if (event.kbd.keycode == 'd')
_debugger->attach();
else if (event.kbd.keycode == 'q')
- _quitFlag = true;
+ quitGame();
} else if (event.kbd.keycode == '.') {
_skipFlag = true;
} else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) {
@@ -488,9 +493,6 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) {
case Common::EVENT_MOUSEMOVE:
_animator->_updateScreen = true;
break;
- case Common::EVENT_QUIT:
- quitGame();
- break;
case Common::EVENT_LBUTTONDOWN:
_mousePressFlag = true;
break;
@@ -529,27 +531,24 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) {
if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE))
_skipFlag = false;
- if (amount > 0 && !_skipFlag && !_quitFlag)
+ if (amount > 0 && !_skipFlag && !quit())
_system->delayMillis(10);
if (_skipFlag)
_sound->voiceStop();
- } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag);
+ } while (!_skipFlag && _system->getMillis() < start + amount && !quit());
}
void KyraEngine_LoK::waitForEvent() {
bool finished = false;
Common::Event event;
- while (!finished && !_quitFlag) {
+ while (!finished && !quit()) {
while (_eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
finished = true;
break;
- case Common::EVENT_QUIT:
- quitGame();
- break;
case Common::EVENT_LBUTTONDOWN:
finished = true;
_skipFlag = true;
diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h
index 1def95ddbf..e6fc0dc774 100644
--- a/engines/kyra/kyra_lok.h
+++ b/engines/kyra/kyra_lok.h
@@ -214,7 +214,7 @@ public:
protected:
int32 _speechPlayTime;
- void saveGame(const char *fileName, const char *saveName);
+ void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail);
void loadGame(const char *fileName);
protected:
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index a61253199b..9d3171e723 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -263,7 +263,7 @@ int KyraEngine_MR::go() {
running = false;
}
- while (running && !_quitFlag) {
+ while (running && !quit()) {
_screen->_curPage = 0;
_screen->clearPage(0);
@@ -272,14 +272,14 @@ int KyraEngine_MR::go() {
// XXX
playMenuAudioFile();
- for (int i = 0; i < 64 && !_quitFlag; ++i) {
+ for (int i = 0; i < 64 && !quit(); ++i) {
uint32 nextRun = _system->getMillis() + 3 * _tickLength;
_menuAnim->displayFrame(i, 0);
_screen->updateScreen();
delayUntil(nextRun);
}
- for (int i = 64; i > 29 && !_quitFlag; --i) {
+ for (int i = 64; i > 29 && !quit(); --i) {
uint32 nextRun = _system->getMillis() + 3 * _tickLength;
_menuAnim->displayFrame(i, 0);
_screen->updateScreen();
@@ -684,7 +684,7 @@ void KyraEngine_MR::startup() {
assert(_invWsa);
_invWsa->open("MOODOMTR.WSA", 1, 0);
_invWsaFrame = 6;
- saveGame(getSavegameFilename(0), (const char*)getTableEntry(_optionsFile, 33));
+ saveGame(getSavegameFilename(0), "New Game", 0);
_soundDigital->beginFadeOut(_musicSoundChannel, 60);
delayWithTicks(60);
if (_gameToLoad == -1)
@@ -1001,14 +1001,19 @@ void KyraEngine_MR::runLoop() {
_eventList.clear();
_runFlag = true;
- while (_runFlag && !_quitFlag) {
+ while (_runFlag && !quit()) {
if (_deathHandler >= 0) {
removeHandItem();
delay(5);
_drawNoShapeFlag = 0;
_gui->optionsButton(0);
_deathHandler = -1;
+
+ if (quit())
+ break;
}
+
+ checkAutosave();
if (_system->getMillis() >= _nextIdleAnim)
showIdleAnim();
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index 5f9f6f91a3..a6fb9af20c 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -583,7 +583,7 @@ private:
int albumClose(Button *caller);
// save/load
- void saveGame(const char *fileName, const char *saveName);
+ void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail);
void loadGame(const char *fileName);
// opcodes
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index bc46d8e1f5..8162232935 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -52,8 +52,6 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
_gameSpeed = 60;
_tickLength = (uint8)(1000.0 / _gameSpeed);
- _quitFlag = false;
-
_speechFile = "";
_trackMap = 0;
_trackMapSize = 0;
@@ -183,6 +181,9 @@ int KyraEngine_v1::init() {
_gameToLoad = -1;
}
+ // Prevent autosave on game startup
+ _lastAutosave = _system->getMillis();
+
return 0;
}
@@ -200,12 +201,6 @@ KyraEngine_v1::~KyraEngine_v1() {
delete _debugger;
}
-void KyraEngine_v1::quitGame() {
- debugC(9, kDebugLevelMain, "KyraEngine_v1::quitGame()");
- _quitFlag = true;
- // Nothing to do here
-}
-
Common::Point KyraEngine_v1::getMousePos() const {
Common::Point mouse = _eventMan->getMousePos();
@@ -240,7 +235,7 @@ int KyraEngine_v1::resetGameFlag(int flag) {
}
void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) {
- while (_system->getMillis() < timestamp && !_quitFlag) {
+ while (_system->getMillis() < timestamp && !quit()) {
if (timestamp - _system->getMillis() >= 10)
delay(10, update, isMainLoop);
}
@@ -255,8 +250,8 @@ void KyraEngine_v1::delayWithTicks(int ticks) {
}
void KyraEngine_v1::registerDefaultSettings() {
- if (_flags.gameID != GI_KYRA3)
- ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98));
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
+ ConfMan.registerDefault("cdaudio", true);
if (_flags.fanLang != Common::UNK_LANG) {
// HACK/WORKAROUND: Since we can't use registerDefault here to overwrite
// the global subtitles settings, we're using this hack to enable subtitles
@@ -272,9 +267,10 @@ void KyraEngine_v1::readSettings() {
_configMusic = 0;
if (!ConfMan.getBool("music_mute")) {
- _configMusic = 1;
- if (_flags.gameID != GI_KYRA3 && ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98))
- _configMusic = 2;
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
+ _configMusic = ConfMan.getBool("cdaudio") ? 2 : 1;
+ else
+ _configMusic = 1;
}
_configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1;
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 738a3fc8ec..f4c2442c0e 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -118,8 +118,6 @@ public:
virtual void pauseEngineIntern(bool pause);
- bool quit() const { return _quitFlag; }
-
uint8 game() const { return _flags.gameID; }
const GameFlags &gameFlags() const { return _flags; }
@@ -153,9 +151,6 @@ public:
void setVolume(kVolumeEntry vol, uint8 value);
uint8 getVolume(kVolumeEntry vol);
- // quit handling
- virtual void quitGame();
-
// game flag handling
int setGameFlag(int flag);
int queryGameFlag(int flag) const;
@@ -178,9 +173,6 @@ protected:
virtual int go() = 0;
virtual int init();
- // quit Handling
- bool _quitFlag;
-
// intern
Resource *_res;
Sound *_sound;
@@ -279,7 +271,11 @@ protected:
// save/load
int _gameToLoad;
+ uint32 _lastAutosave;
+ void checkAutosave();
+
const char *getSavegameFilename(int num);
+ static Common::String getSavegameFilename(const Common::String &target, int num);
bool saveFileLoadable(int slot);
struct SaveHeader {
@@ -290,6 +286,8 @@ protected:
bool originalSave; // savegame from original interpreter
bool oldHeader; // old scummvm save header
+
+ Graphics::Surface *thumbnail;
};
enum kReadSaveHeaderError {
@@ -299,10 +297,12 @@ protected:
kRSHEIoError = 3
};
- static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, SaveHeader &header);
+ static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header);
+
+ virtual void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) = 0;
Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header);
- Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName) const;
+ Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const;
};
} // End of namespace Kyra
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 2e704f2aa2..e9ed91b539 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -159,7 +159,7 @@ void KyraEngine_v2::delay(uint32 amount, bool updateGame, bool isMainLoop) {
if (amount > 0)
_system->delayMillis(amount > 10 ? 10 : amount);
- } while (!skipFlag() && _system->getMillis() < start + amount && !_quitFlag);
+ } while (!skipFlag() && _system->getMillis() < start + amount && !quit());
}
int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) {
@@ -186,7 +186,7 @@ int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) {
} else {
char savegameName[14];
sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0');
- saveGame(saveLoadSlot, savegameName);
+ saveGame(saveLoadSlot, savegameName, 0);
}
} else if (event.kbd.flags == Common::KBD_CTRL) {
if (event.kbd.keycode == 'd')
@@ -238,15 +238,11 @@ void KyraEngine_v2::updateInput() {
while (_eventMan->pollEvent(event)) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _quitFlag = true;
- break;
-
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE)
_eventList.push_back(Event(event, true));
else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL)
- _quitFlag = true;
+ quitGame();
else
_eventList.push_back(event);
break;
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index 6fdf30fff8..e7f9634fc6 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -419,7 +419,7 @@ protected:
int o2_getVocHigh(EMCState *script);
// save/load specific
- virtual void saveGame(const char *fileName, const char *saveName) = 0;
+ virtual void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) = 0;
virtual void loadGame(const char *fileName) = 0;
};
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 6624dd91ea..053d8a4de9 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -183,15 +183,11 @@ void LoLEngine::updateInput() {
while (_eventMan->pollEvent(event)) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _quitFlag = true;
- break;
-
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE)
_eventList.push_back(Event(event, true));
else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL)
- _quitFlag = true;
+ quitGame();
else
_eventList.push_back(event);
break;
@@ -245,27 +241,21 @@ void LoLEngine::resetSkipFlag(bool removeEvent) {
void LoLEngine::setupPrologueData(bool load) {
static const char * const fileList[] = {
- "xxx/general.pak",
- "xxx/introvoc.pak",
- "xxx/startup.pak",
- "xxx/intro1.pak",
- "xxx/intro2.pak",
- "xxx/intro3.pak",
- "xxx/intro4.pak",
- "xxx/intro5.pak",
- "xxx/intro6.pak",
- "xxx/intro7.pak",
- "xxx/intro8.pak",
- "xxx/intro9.pak"
+ "GENERAL.PAK", "INTROVOC.PAK", "STARTUP.PAK", "INTRO1.PAK",
+ "INTRO2.PAK", "INTRO3.PAK", "INTRO4.PAK", "INTRO5.PAK",
+ "INTRO6.PAK", "INTRO7.PAK", "INTRO8.PAK", "INTRO9.PAK"
};
- char filepath[32];
- char *filename = filepath;
+ char filename[32];
for (uint i = 0; i < ARRAYSIZE(fileList); ++i) {
- strcpy(filename, fileList[i]);
- memcpy(filename, _languageExt[_lang], 3);
- if (!_flags.isTalkie)
- filename += 4;
+ filename[0] = '\0';
+
+ if (_flags.isTalkie) {
+ strcpy(filename, _languageExt[_lang]);
+ strcat(filename, "/");
+ }
+
+ strcat(filename, fileList[i]);
if (load) {
if (!_res->loadPakFile(filename))
@@ -307,7 +297,7 @@ void LoLEngine::showIntro() {
_screen->hideMouse();
uint32 palNextFadeStep = 0;
- while (!_tim->finished() && !_quitFlag && !skipFlag()) {
+ while (!_tim->finished() && !quit() && !skipFlag()) {
updateInput();
_tim->exec(intro, false);
_screen->checkedPageUpdate(8, 4);
@@ -385,14 +375,14 @@ int LoLEngine::chooseCharacter() {
_screen->fadePalette(_screen->getPalette(0), 30, 0);
bool kingIntro = true;
- while (!_quitFlag) {
+ while (!quit()) {
if (kingIntro)
kingSelectionIntro();
if (_charSelection < 0)
processCharacterSelection();
- if (_quitFlag)
+ if (quit())
break;
if (_charSelection == 100) {
@@ -413,11 +403,11 @@ int LoLEngine::chooseCharacter() {
}
}
- if (_quitFlag)
+ if (quit())
return -1;
uint32 waitTime = _system->getMillis() + 420 * _tickLength;
- while (waitTime > _system->getMillis() && !skipFlag() && !_quitFlag) {
+ while (waitTime > _system->getMillis() && !skipFlag() && !quit()) {
updateInput();
_system->delayMillis(10);
}
@@ -449,7 +439,7 @@ void LoLEngine::kingSelectionIntro() {
_chargenWSA->setDrawPage(0);
int index = 4;
- while (_sound->voiceIsPlaying("KING01") && _charSelection == -1 && !_quitFlag && !skipFlag()) {
+ while (_sound->voiceIsPlaying("KING01") && _charSelection == -1 && !quit() && !skipFlag()) {
index = MAX(index, 4);
_chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0);
@@ -460,7 +450,7 @@ void LoLEngine::kingSelectionIntro() {
_screen->updateScreen();
uint32 waitEnd = _system->getMillis() + 7 * _tickLength;
- while (waitEnd > _system->getMillis() && _charSelection == -1 && !_quitFlag && !skipFlag()) {
+ while (waitEnd > _system->getMillis() && _charSelection == -1 && !quit() && !skipFlag()) {
_charSelection = getCharSelection();
_system->delayMillis(10);
}
@@ -491,7 +481,7 @@ void LoLEngine::kingSelectionReminder() {
_chargenWSA->setDrawPage(0);
int index = 0;
- while (_sound->voiceIsPlaying("KING02") && _charSelection == -1 && !_quitFlag && index < 15) {
+ while (_sound->voiceIsPlaying("KING02") && _charSelection == -1 && !quit() && index < 15) {
_chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 0, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0);
_screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0);
@@ -500,7 +490,7 @@ void LoLEngine::kingSelectionReminder() {
_screen->updateScreen();
uint32 waitEnd = _system->getMillis() + 8 * _tickLength;
- while (waitEnd > _system->getMillis() && !_quitFlag) {
+ while (waitEnd > _system->getMillis() && !quit()) {
_charSelection = getCharSelection();
_system->delayMillis(10);
}
@@ -521,14 +511,14 @@ void LoLEngine::kingSelectionOutro() {
_chargenWSA->setDrawPage(0);
int index = 0;
- while (_sound->voiceIsPlaying("KING03") && !_quitFlag && !skipFlag()) {
+ while (_sound->voiceIsPlaying("KING03") && !quit() && !skipFlag()) {
index = MAX(index, 4);
_chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0);
_screen->updateScreen();
uint32 waitEnd = _system->getMillis() + 8 * _tickLength;
- while (waitEnd > _system->getMillis() && !_quitFlag && !skipFlag()) {
+ while (waitEnd > _system->getMillis() && !quit() && !skipFlag()) {
updateInput();
_system->delayMillis(10);
}
@@ -547,10 +537,10 @@ void LoLEngine::processCharacterSelection() {
debugC(9, kDebugLevelMain, "LoLEngine::processCharacterSelection()");
_charSelection = -1;
- while (!_quitFlag && _charSelection == -1) {
+ while (!quit() && _charSelection == -1) {
uint32 nextKingMessage = _system->getMillis() + 900 * _tickLength;
- while (nextKingMessage > _system->getMillis() && _charSelection == -1 && !_quitFlag) {
+ while (nextKingMessage > _system->getMillis() && _charSelection == -1 && !quit()) {
updateSelectionAnims();
_charSelection = getCharSelection();
_system->delayMillis(10);
@@ -595,22 +585,22 @@ int LoLEngine::selectionCharInfo(int character) {
switch (character) {
case 0:
- strcpy(filename, "face09.shp");
+ strcpy(filename, "FACE09.SHP");
vocFilename[3] = 'A';
break;
case 1:
- strcpy(filename, "face01.shp");
+ strcpy(filename, "FACE01.SHP");
vocFilename[3] = 'M';
break;
case 2:
- strcpy(filename, "face08.shp");
+ strcpy(filename, "FACE08.SHP");
vocFilename[3] = 'K';
break;
case 3:
- strcpy(filename, "face05.shp");
+ strcpy(filename, "FACE05.SHP");
vocFilename[3] = 'C';
break;
@@ -669,12 +659,12 @@ void LoLEngine::selectionCharInfoIntro(char *file) {
int index = 0;
file[4] = '0';
- while (_charSelectionInfoResult == -1 && !_quitFlag) {
+ while (_charSelectionInfoResult == -1 && !quit()) {
if (!_sound->voicePlay(file))
break;
int i = 0;
- while (_sound->voiceIsPlaying(file) && _charSelectionInfoResult == -1 && !_quitFlag) {
+ while (_sound->voiceIsPlaying(file) && _charSelectionInfoResult == -1 && !quit()) {
_screen->drawShape(0, _screen->getPtrToShape(_screen->getCPagePtr(9), _charInfoFrameTable[i]), 11, 130, 0, 0);
_screen->updateScreen();
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index ee54f8abbb..2ae4d71580 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -147,6 +147,9 @@ private:
void setHandItem(uint16) {}
void removeHandItem() {}
bool lineIsPassable(int, int) { return false; }
+
+ // save
+ void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) {}
};
} // end of namespace Kyra
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index e059a8ce4b..b38661ada5 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -23,6 +23,7 @@ MODULE_OBJS := \
kyra_mr.o \
lol.o \
resource.o \
+ resource_intern.o \
saveload.o \
saveload_lok.o \
saveload_hof.o \
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 5da6bb3873..0f0a643017 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -23,39 +23,46 @@
*
*/
+#include "kyra/resource.h"
+#include "kyra/resource_intern.h"
#include "common/config-manager.h"
#include "common/endian.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/func.h"
-
-#include "kyra/resource.h"
+#include "common/system.h"
namespace Kyra {
-Resource::Resource(KyraEngine_v1 *vm) : _loaders(), _map(), _vm(vm) {
+Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(new Common::SearchSet()), _protectedFiles(new Common::SearchSet()), _loaders(), _vm(vm) {
initializeLoaders();
+
+ Common::SharedPtr<Common::Archive> path(new Common::FSDirectory(ConfMan.get("path"), 2));
+ Common::SharedPtr<Common::Archive> extrapath(new Common::FSDirectory(ConfMan.get("extrapath")));
+
+ _files.add("path", path, 4);
+ _files.add("extrapath", extrapath, 4);
+ _vm->_system->addSysArchivesToSearchSet(_files, 3);
+ // compressed installer archives are added at level '2',
+ // but that's done in Resource::reset not here
+ _files.add("protected", _protectedFiles, 1);
+ _files.add("archives", _archiveFiles, 0);
}
Resource::~Resource() {
- _map.clear();
_loaders.clear();
-
- clearCompFileList();
- _compLoaders.clear();
}
bool Resource::reset() {
- clearCompFileList();
unloadAllPakFiles();
- FilesystemNode dir(ConfMan.get("path"));
+ Common::FilesystemNode dir(ConfMan.get("path"));
if (!dir.exists() || !dir.isDirectory())
error("invalid game path '%s'", dir.getPath().c_str());
- if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat()) {
+ if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat(this)) {
Common::String errorMessage = "You're missing the '" + StaticResource::staticDataFilename() + "' file or it got corrupted, (re)get it from the ScummVM website";
_vm->GUIErrorMessage(errorMessage);
error(errorMessage.c_str());
@@ -65,24 +72,14 @@ bool Resource::reset() {
// We only need kyra.dat for the demo.
if (_vm->gameFlags().isDemo)
return true;
-
- // only VRM file we need in the *whole* game for kyra1
- if (_vm->gameFlags().isTalkie)
- loadPakFile("CHAPTER1.VRM");
} else if (_vm->game() == GI_KYRA2) {
if (_vm->gameFlags().useInstallerPackage)
- tryLoadCompFiles();
+ _files.add("installer", loadInstallerArchive("WESTWOOD", "%03d", 6), 2);
// mouse pointer, fonts, etc. required for initializing
if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) {
loadPakFile("GENERAL.PAK");
} else {
- if (_vm->gameFlags().isTalkie) {
- // Add default file directories
- Common::File::addDefaultDirectory(ConfMan.get("path") + "hof_cd");
- Common::File::addDefaultDirectory(ConfMan.get("path") + "HOF_CD");
- }
-
loadPakFile("INTROGEN.PAK");
loadPakFile("OTHER.PAK");
}
@@ -94,23 +91,19 @@ bool Resource::reset() {
error("couldn't load file: 'WESTWOOD.001'");
}
- // Add default file directories
- Common::File::addDefaultDirectory(ConfMan.get("path") + "malcolm");
- Common::File::addDefaultDirectory(ConfMan.get("path") + "MALCOLM");
-
if (!loadFileList("FILEDATA.FDT"))
error("couldn't load file: 'FILEDATA.FDT'");
return true;
} else if (_vm->game() == GI_LOL) {
if (_vm->gameFlags().useInstallerPackage)
- tryLoadCompFiles();
+ _files.add("installer", loadInstallerArchive("WESTWOOD", "%d", 0), 2);
return true;
}
- FSList fslist;
- if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly))
+ Common::FSList fslist;
+ if (!dir.getChildren(fslist, Common::FilesystemNode::kListFilesOnly))
error("can't list files inside game path '%s'", dir.getPath().c_str());
if (_vm->game() == GI_KYRA1 && _vm->gameFlags().isTalkie) {
@@ -120,15 +113,13 @@ bool Resource::reset() {
"CAVE.APK", "DRAGON1.APK", "DRAGON2.APK", "LAGOON.APK"
};
- Common::for_each(list, list + ARRAYSIZE(list), Common::bind1st(Common::mem_fun(&Resource::loadPakFile), this));
-
- for (int i = 0; i < ARRAYSIZE(list); ++i) {
- ResFileMap::iterator iterator = _map.find(list[i]);
- if (iterator != _map.end())
- iterator->_value.prot = true;
+ for (uint i = 0; i < ARRAYSIZE(list); ++i) {
+ Common::ArchivePtr archive = loadArchive(list[i]);
+ if (archive)
+ _protectedFiles->add(list[i], archive, 0);
}
} else {
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
Common::String filename = file->getName();
filename.toUppercase();
@@ -149,113 +140,55 @@ bool Resource::reset() {
return true;
}
-bool Resource::loadPakFile(const Common::String &filename) {
- if (!isAccessable(filename))
- return false;
-
- ResFileMap::iterator iter = _map.find(filename);
- if (iter == _map.end())
- return false;
+bool Resource::loadPakFile(Common::String filename) {
+ filename.toUppercase();
- if (iter->_value.preload) {
- iter->_value.mounted = true;
+ if (_archiveFiles->hasArchive(filename) || _protectedFiles->hasArchive(filename))
return true;
- }
- const ResArchiveLoader *loader = getLoader(iter->_value.type);
- if (!loader) {
- error("no archive loader for file '%s' found which is of type %d", filename.c_str(), iter->_value.type);
+ Common::ArchivePtr archive = loadArchive(filename);
+ if (!archive)
return false;
- }
- Common::SeekableReadStream *stream = getFileStream(filename);
- if (!stream) {
- error("archive file '%s' not found", filename.c_str());
- return false;
- }
+ _archiveFiles->add(filename, archive, 0);
- iter->_value.mounted = true;
- iter->_value.preload = true;
- ResArchiveLoader::FileList files;
- loader->loadFile(filename, *stream, files);
- delete stream;
- stream = 0;
-
- for (ResArchiveLoader::FileList::iterator i = files.begin(); i != files.end(); ++i) {
- iter = _map.find(i->filename);
- if (iter == _map.end()) {
- // We do an internal check for a file in gamepath with same filename to
- // allow overwriting files inside archives with plain files inside the
- // game directory
- checkFile(i->filename);
-
- // A new file entry, so we just insert it into the file map.
- if (_map.find(i->filename) == _map.end())
- _map[i->filename] = i->entry;
- } else if (!iter->_value.parent.empty()) {
- if (!iter->_value.parent.equalsIgnoreCase(filename)) {
- ResFileMap::iterator oldParent = _map.find(iter->_value.parent);
- if (oldParent != _map.end()) {
- // Protected files and their embedded file entries do not get overwritten.
- if (!oldParent->_value.prot) {
- // If the old parent is not protected we mark it as not preload anymore,
- // since now no longer all of its embedded files are in the filemap.
- oldParent->_value.preload = false;
- _map[i->filename] = i->entry;
- }
- } else {
- // Old parent not found? That's strange... But we just overwrite the old
- // entry.
- _map[i->filename] = i->entry;
- }
- } else {
- // The old parent has the same filenames as the new archive, we are sure and overwrite the
- // old file entry, could be afterall that the preload flag of the new archive was
- // just unflagged.
- _map[i->filename] = i->entry;
- }
- }
- // 'else' case would mean here overwriting an existing file entry in the map without parent.
- // We don't support that though, so one can overwrite files from archives by putting
- // them in the gamepath.
- }
-
- detectFileTypes();
return true;
}
bool Resource::loadFileList(const Common::String &filedata) {
- Common::File f;
+ Common::SeekableReadStream *f = getFileStream(filedata);
- if (!f.open(filedata))
+ if (!f)
return false;
uint32 filenameOffset = 0;
- while ((filenameOffset = f.readUint32LE()) != 0) {
- uint32 offset = f.pos();
- f.seek(filenameOffset, SEEK_SET);
+ while ((filenameOffset = f->readUint32LE()) != 0) {
+ uint32 offset = f->pos();
+ f->seek(filenameOffset, SEEK_SET);
uint8 buffer[13];
- f.read(buffer, sizeof(buffer)-1);
+ f->read(buffer, sizeof(buffer)-1);
buffer[12] = 0;
- f.seek(offset + 16, SEEK_SET);
+ f->seek(offset + 16, SEEK_SET);
- Common::String filename = Common::String((char*)buffer);
+ Common::String filename = Common::String((char *)buffer);
filename.toUppercase();
if (filename.hasSuffix(".PAK")) {
- if (!isAccessable(filename) && _vm->gameFlags().isDemo) {
+ if (!exists(filename.c_str()) && _vm->gameFlags().isDemo) {
// the demo version supplied with Kyra3 does not
// contain all pak files listed in filedata.fdt
// so we don't do anything here if they are non
// existant.
} else if (!loadPakFile(filename)) {
+ delete f;
error("couldn't load file '%s'", filename.c_str());
return false;
}
}
}
+ delete f;
return true;
}
@@ -273,33 +206,21 @@ bool Resource::loadFileList(const char * const *filelist, uint32 numFiles) {
return true;
}
-void Resource::unloadPakFile(const Common::String &filename) {
- ResFileMap::iterator iter = _map.find(filename);
- if (iter != _map.end()) {
- if (!iter->_value.prot)
- iter->_value.mounted = false;
- }
-}
-
-void Resource::clearCompFileList() {
- for (CompFileMap::iterator i = _compFiles.begin(); i != _compFiles.end(); ++i)
- delete[] i->_value.data;
-
- _compFiles.clear();
+void Resource::unloadPakFile(Common::String filename) {
+ filename.toUppercase();
+ _archiveFiles->remove(filename);
+ // We do not remove files from '_protectedFiles' here, since
+ // those are protected against unloading.
}
-bool Resource::isInPakList(const Common::String &filename) {
- if (!isAccessable(filename))
- return false;
- ResFileMap::iterator iter = _map.find(filename);
- if (iter == _map.end())
- return false;
- return (iter->_value.type != ResFileEntry::kRaw);
+bool Resource::isInPakList(Common::String filename) {
+ filename.toUppercase();
+ return (_archiveFiles->hasArchive(filename) || _protectedFiles->hasArchive(filename));
}
void Resource::unloadAllPakFiles() {
- // remove all entries
- _map.clear();
+ _archiveFiles->clear();
+ _protectedFiles->clear();
}
uint8 *Resource::fileData(const char *file, uint32 *size) {
@@ -318,9 +239,7 @@ uint8 *Resource::fileData(const char *file, uint32 *size) {
}
bool Resource::exists(const char *file, bool errorOutOnFail) {
- if (Common::File::exists(file))
- return true;
- else if (isAccessable(file))
+ if (_files.hasFile(file))
return true;
else if (errorOutOnFail)
error("File '%s' can't be found", file);
@@ -328,21 +247,13 @@ bool Resource::exists(const char *file, bool errorOutOnFail) {
}
uint32 Resource::getFileSize(const char *file) {
- CompFileMap::iterator compEntry;
-
- if (Common::File::exists(file)) {
- Common::File f;
- if (f.open(file))
- return f.size();
- } else {
- if (!isAccessable(file))
- return 0;
+ Common::SeekableReadStream *stream = getFileStream(file);
+ if (!stream)
+ return 0;
- ResFileMap::const_iterator iter = _map.find(file);
- if (iter != _map.end())
- return iter->_value.size;
- }
- return 0;
+ uint32 size = stream->size();
+ delete stream;
+ return size;
}
bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) {
@@ -351,1181 +262,57 @@ bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) {
return false;
memset(buf, 0, maxSize);
- stream->read(buf, (maxSize <= stream->size()) ? maxSize : stream->size());
+ stream->read(buf, ((int32)maxSize <= stream->size()) ? maxSize : stream->size());
delete stream;
return true;
}
Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) {
- CompFileMap::iterator compEntry;
-
- if ((compEntry = _compFiles.find(file)) != _compFiles.end())
- return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false);
-
- if (!isAccessable(file))
- return 0;
-
- ResFileMap::const_iterator iter = _map.find(file);
- if (iter == _map.end())
- return 0;
-
- if (iter->_value.parent.empty()) {
- Common::File *stream = new Common::File();
- if (!stream->open(file)) {
- delete stream;
- stream = 0;
- error("Couldn't open file '%s'", file.c_str());
- }
- return stream;
- } else {
- Common::SeekableReadStream *parent = getFileStream(iter->_value.parent);
- assert(parent);
-
- ResFileMap::const_iterator parentIter = _map.find(iter->_value.parent);
- const ResArchiveLoader *loader = getLoader(parentIter->_value.type);
- assert(loader);
-
- return loader->loadFileFromArchive(file, parent, iter->_value);
- }
-
- return 0;
-}
-
-bool Resource::isAccessable(const Common::String &file) {
- checkFile(file);
-
- ResFileMap::const_iterator iter = _map.find(file);
- while (iter != _map.end()) {
- if (!iter->_value.parent.empty()) {
- iter = _map.find(iter->_value.parent);
- if (iter != _map.end()) {
- // parent can never be a non archive file
- if (iter->_value.type == ResFileEntry::kRaw)
- return false;
- // not mounted parent means not accessable
- else if (!iter->_value.mounted)
- return false;
- }
- } else {
- return true;
- }
- }
- return false;
-}
-
-void Resource::checkFile(const Common::String &file) {
- if (_map.find(file) == _map.end()) {
- CompFileMap::const_iterator iter;
-
- if ((iter = _compFiles.find(file)) != _compFiles.end()) {
- ResFileEntry entry;
- entry.parent = "";
- entry.size = iter->_value.size;
- entry.mounted = false;
- entry.preload = false;
- entry.prot = false;
- entry.type = ResFileEntry::kAutoDetect;
- entry.offset = 0;
- _map[file] = entry;
-
- detectFileTypes();
- } else if (Common::File::exists(file)) {
- Common::File temp;
- if (temp.open(file)) {
- ResFileEntry entry;
- entry.parent = "";
- entry.size = temp.size();
- entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0;
- entry.preload = false;
- entry.prot = false;
- entry.type = ResFileEntry::kAutoDetect;
- entry.offset = 0;
- _map[file] = entry;
- temp.close();
-
- detectFileTypes();
- }
- }
- }
-}
-
-void Resource::detectFileTypes() {
- for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) {
- if (!isAccessable(i->_key))
- continue;
-
- if (i->_value.type == ResFileEntry::kAutoDetect) {
- Common::SeekableReadStream *stream = 0;
- for (LoaderIterator l = _loaders.begin(); l != _loaders.end(); ++l) {
- if (!(*l)->checkFilename(i->_key))
- continue;
-
- if (!stream)
- stream = getFileStream(i->_key);
-
- if ((*l)->isLoadable(i->_key, *stream)) {
- i->_value.type = (*l)->getType();
- i->_value.mounted = false;
- i->_value.preload = false;
- break;
- }
- }
- delete stream;
- stream = 0;
-
- if (i->_value.type == ResFileEntry::kAutoDetect)
- i->_value.type = ResFileEntry::kRaw;
- }
- }
-}
-
-void Resource::tryLoadCompFiles() {
- for (CCompLoaderIterator i = _compLoaders.begin(); i != _compLoaders.end(); ++i) {
- if ((*i)->checkForFiles())
- (*i)->loadFile(_compFiles);
- }
-}
-
-#pragma mark -
-#pragma mark - ResFileLodaer
-#pragma mark -
-
-class ResLoaderPak : public ResArchiveLoader {
-public:
- bool checkFilename(Common::String filename) const;
- bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
- bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const;
- Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const;
-
- ResFileEntry::kType getType() const {
- return ResFileEntry::kPak;
- }
-};
-
-bool ResLoaderPak::checkFilename(Common::String filename) const {
- filename.toUppercase();
- return (filename.hasSuffix(".PAK") || filename.hasSuffix(".APK") || filename.hasSuffix(".VRM") || filename.hasSuffix(".TLK") || filename.equalsIgnoreCase(StaticResource::staticDataFilename()));
+ return _files.openFile(file);
}
-bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
- uint32 filesize = stream.size();
- uint32 offset = 0;
- bool switchEndian = false;
- bool firstFile = true;
-
- offset = stream.readUint32LE();
- if (offset > filesize) {
- switchEndian = true;
- offset = SWAP_BYTES_32(offset);
- }
-
- Common::String file = "";
- while (!stream.eos()) {
- // The start offset of a file should never be in the filelist
- if (offset < stream.pos() || offset > filesize)
- return false;
-
- byte c = 0;
-
- file = "";
-
- while (!stream.eos() && (c = stream.readByte()) != 0)
- file += c;
-
- if (stream.eos())
- return false;
+Common::ArchivePtr Resource::loadArchive(const Common::String &file) {
+ ArchiveMap::iterator cachedArchive = _archiveCache.find(file);
+ if (cachedArchive != _archiveCache.end())
+ return cachedArchive->_value;
- // Quit now if we encounter an empty string
- if (file.empty()) {
- if (firstFile)
- return false;
- else
+ Common::SeekableReadStream *stream = getFileStream(file);
+ if (!stream)
+ return Common::ArchivePtr();
+
+ Common::ArchivePtr archive;
+ for (LoaderList::const_iterator i = _loaders.begin(); i != _loaders.end(); ++i) {
+ if ((*i)->checkFilename(file)) {
+ if ((*i)->isLoadable(file, *stream)) {
+ stream->seek(0, SEEK_SET);
+ archive = Common::ArchivePtr((*i)->load(this, file, *stream));
break;
- }
-
- firstFile = false;
- offset = switchEndian ? stream.readUint32BE() : stream.readUint32LE();
-
- if (!offset || offset == filesize)
- break;
- }
-
- return true;
-}
-
-namespace {
-
-Common::String readString(Common::SeekableReadStream &stream) {
- Common::String result;
- char c = 0;
-
- while ((c = stream.readByte()) != 0)
- result += c;
-
- return result;
-}
-
-} // end of anonymous namespace
-
-bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const {
- uint32 filesize = stream.size();
-
- uint32 startoffset = 0, endoffset = 0;
- bool switchEndian = false;
- bool firstFile = true;
-
- startoffset = stream.readUint32LE();
- if (startoffset > filesize) {
- switchEndian = true;
- startoffset = SWAP_BYTES_32(startoffset);
- }
-
- Common::String file = "";
- while (!stream.eos()) {
- // The start offset of a file should never be in the filelist
- if (startoffset < stream.pos() || startoffset > filesize) {
- warning("PAK file '%s' is corrupted", filename.c_str());
- return false;
- }
-
- file = "";
- byte c = 0;
-
- while (!stream.eos() && (c = stream.readByte()) != 0)
- file += c;
-
- if (stream.eos()) {
- warning("PAK file '%s' is corrupted", filename.c_str());
- return false;
- }
-
- // Quit now if we encounter an empty string
- if (file.empty()) {
- if (firstFile) {
- warning("PAK file '%s' is corrupted", filename.c_str());
- return false;
} else {
- break;
- }
- }
-
- firstFile = false;
- endoffset = switchEndian ? stream.readUint32BE() : stream.readUint32LE();
-
- if (!endoffset)
- endoffset = filesize;
-
- if (startoffset != endoffset) {
- ResFileEntry entry;
- entry.size = endoffset - startoffset;
- entry.offset = startoffset;
- entry.parent = filename;
- entry.type = ResFileEntry::kAutoDetect;
- entry.mounted = false;
- entry.prot = false;
- entry.preload = false;
-
- files.push_back(File(file, entry));
- }
-
- if (endoffset == filesize)
- break;
-
- startoffset = endoffset;
- }
-
- FileList::const_iterator iter = Common::find(files.begin(), files.end(), Common::String("LINKLIST"));
- if (iter != files.end()) {
- stream.seek(iter->entry.offset, SEEK_SET);
-
- uint32 magic = stream.readUint32BE();
-
- if (magic != MKID_BE('SCVM'))
- error("LINKLIST file does not contain 'SCVM' header");
-
- uint32 links = stream.readUint32BE();
- for (uint i = 0; i < links; ++i) {
- Common::String linksTo = readString(stream);
- uint32 sources = stream.readUint32BE();
-
- iter = Common::find(files.begin(), files.end(), linksTo);
- if (iter == files.end())
- error("PAK file link destination '%s' not found", linksTo.c_str());
-
- for (uint j = 0; j < sources; ++j) {
- Common::String dest = readString(stream);
- files.push_back(File(dest, iter->entry));
- // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it
- iter = Common::find(files.begin(), files.end(), linksTo);
- }
- }
- }
-
- return true;
-}
-
-Common::SeekableReadStream *ResLoaderPak::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const {
- assert(archive);
-
- archive->seek(entry.offset, SEEK_SET);
- Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true);
- assert(stream);
- return stream;
-}
-
-class ResLoaderInsMalcolm : public ResArchiveLoader {
-public:
- bool checkFilename(Common::String filename) const;
- bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
- bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const;
- Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const;
-
- ResFileEntry::kType getType() const {
- return ResFileEntry::kInsMal;
- }
-};
-
-bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const {
- filename.toUppercase();
- if (!filename.hasSuffix(".001"))
- return false;
- return true;
-}
-
-bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
- stream.seek(3);
- uint32 size = stream.readUint32LE();
-
- if (size+7 > stream.size())
- return false;
-
- stream.seek(size+5, SEEK_SET);
- uint8 buffer[2];
- stream.read(&buffer, 2);
-
- return (buffer[0] == 0x0D && buffer[1] == 0x0A);
-}
-
-bool ResLoaderInsMalcolm::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const {
- Common::List<Common::String> filenames;
-
- // thanks to eriktorbjorn for this code (a bit modified though)
- stream.seek(3, SEEK_SET);
-
- // first file is the index table
- uint32 size = stream.readUint32LE();
- Common::String temp = "";
-
- for (uint32 i = 0; i < size; ++i) {
- byte c = stream.readByte();
-
- if (c == '\\') {
- temp = "";
- } else if (c == 0x0D) {
- // line endings are CRLF
- c = stream.readByte();
- assert(c == 0x0A);
- ++i;
-
- filenames.push_back(temp);
- } else {
- temp += (char)c;
- }
- }
-
- stream.seek(3, SEEK_SET);
-
- for (Common::List<Common::String>::iterator file = filenames.begin(); file != filenames.end(); ++file) {
- ResFileEntry entry;
- entry.parent = filename;
- entry.type = ResFileEntry::kAutoDetect;
- entry.mounted = false;
- entry.preload = false;
- entry.prot = false;
- entry.size = stream.readUint32LE();
- entry.offset = stream.pos();
- stream.seek(entry.size, SEEK_CUR);
- files.push_back(File(*file, entry));
- }
-
- return true;
-}
-
-Common::SeekableReadStream *ResLoaderInsMalcolm::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const {
- assert(archive);
-
- archive->seek(entry.offset, SEEK_SET);
- Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true);
- assert(stream);
- return stream;
-}
-
-class ResLoaderTlk : public ResArchiveLoader {
-public:
- bool checkFilename(Common::String filename) const;
- bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
- bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const;
- Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const;
-
- ResFileEntry::kType getType() const {
- return ResFileEntry::kTlk;
- }
-
-private:
- static bool sortTlkFileList(const File &l, const File &r);
- static FileList::const_iterator nextFile(const FileList &list, FileList::const_iterator iter);
-};
-
-bool ResLoaderTlk::checkFilename(Common::String filename) const {
- filename.toUppercase();
- return (filename.hasSuffix(".TLK"));
-}
-
-bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
- uint16 entries = stream.readUint16LE();
- uint32 entryTableSize = (entries * 8);
-
- if (entryTableSize + 2 > stream.size())
- return false;
-
- uint32 offset = 0;
-
- for (uint i = 0; i < entries; ++i) {
- stream.readUint32LE();
- offset = stream.readUint32LE();
-
- if (offset > stream.size())
- return false;
- }
-
- return true;
-}
-
-bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const {
- uint16 entries = stream.readUint16LE();
-
- for (uint i = 0; i < entries; ++i) {
- ResFileEntry entry;
- entry.parent = filename;
- entry.type = ResFileEntry::kAutoDetect;
- entry.mounted = false;
- entry.preload = false;
- entry.prot = false;
-
- uint32 resFilename = stream.readUint32LE();
- uint32 resOffset = stream.readUint32LE();
-
- entry.offset = resOffset+4;
-
- char realFilename[20];
- snprintf(realFilename, 20, "%.08u.AUD", resFilename);
-
- uint32 curOffset = stream.pos();
- stream.seek(resOffset, SEEK_SET);
- entry.size = stream.readUint32LE();
- stream.seek(curOffset, SEEK_SET);
-
- files.push_back(FileList::value_type(realFilename, entry));
- }
-
- return true;
-}
-
-Common::SeekableReadStream *ResLoaderTlk::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const {
- assert(archive);
-
- archive->seek(entry.offset, SEEK_SET);
- Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true);
- assert(stream);
- return stream;
-}
-
-#pragma mark -
-#pragma mark - CompFileLoader
-#pragma mark -
-
-class FileExpanderSource {
-public:
- FileExpanderSource(const uint8 *data, int dataSize) : _dataPtr(data), _endofBuffer(data + dataSize), _bitsLeft(8), _key(0), _index(0) {}
- ~FileExpanderSource() {}
-
- void advSrcRefresh();
- void advSrcBitsBy1();
- void advSrcBitsByIndex(uint8 newIndex);
-
- uint8 getKeyLower() { return _key & 0xff; }
- void setIndex(uint8 index) { _index = index; }
- uint16 getKeyMasked(uint8 newIndex);
- uint16 keyMaskedAlign(uint16 val);
-
- void copyBytes(uint8 *& dst);
-
-private:
- const uint8 *_dataPtr;
- const uint8 *_endofBuffer;
- uint16 _key;
- int8 _bitsLeft;
- uint8 _index;
-};
-
-void FileExpanderSource::advSrcBitsBy1() {
- _key >>= 1;
- if (!--_bitsLeft) {
- if (_dataPtr < _endofBuffer)
- _key = ((*_dataPtr++) << 8 ) | (_key & 0xff);
- _bitsLeft = 8;
- }
-}
-
-void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) {
- _index = newIndex;
- _bitsLeft -= _index;
- if (_bitsLeft <= 0) {
- _key >>= (_index + _bitsLeft);
- _index = -_bitsLeft;
- _bitsLeft = 8 - _index;
- if (_dataPtr < _endofBuffer)
- _key = (*_dataPtr++ << 8) | (_key & 0xff);
- }
- _key >>= _index;
-}
-
-uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) {
- static const uint8 mskTable[] = { 0x0F, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
- _index = newIndex;
- uint16 res = 0;
-
- if (_index > 8) {
- newIndex = _index - 8;
- res = (_key & 0xff) & mskTable[8];
- advSrcBitsByIndex(8);
- _index = newIndex;
- res |= (((_key & 0xff) & mskTable[_index]) << 8);
- advSrcBitsByIndex(_index);
- } else {
- res = (_key & 0xff) & mskTable[_index];
- advSrcBitsByIndex(_index);
- }
-
- return res;
-}
-
-void FileExpanderSource::copyBytes(uint8 *& dst) {
- advSrcBitsByIndex(_bitsLeft);
- uint16 r = (READ_LE_UINT16(_dataPtr) ^ _key) + 1;
- _dataPtr += 2;
-
- if (r)
- error("decompression failure");
-
- memcpy(dst, _dataPtr, _key);
- _dataPtr += _key;
- dst += _key;
-}
-
-uint16 FileExpanderSource::keyMaskedAlign(uint16 val) {
- val -= 0x101;
- _index = (val & 0xff) >> 2;
- int16 b = ((_bitsLeft << 8) | _index) - 1;
- _bitsLeft = b >> 8;
- _index = b & 0xff;
- uint16 res = (((val & 3) + 4) << _index) + 0x101;
- return res + getKeyMasked(_index);
-}
-
-void FileExpanderSource::advSrcRefresh() {
- _key = READ_LE_UINT16(_dataPtr);
- if (_dataPtr < _endofBuffer - 1)
- _dataPtr += 2;
- _bitsLeft = 8;
-}
-
-class FileExpander {
-public:
- FileExpander();
- ~FileExpander();
-
- bool process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 insize);
-
-private:
- void generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt);
- uint8 calcCmdAndIndex(const uint8 *tbl, int16 &para);
-
- FileExpanderSource *_src;
- uint8 *_tables[9];
- uint16 *_tables16[3];
-};
-
-FileExpander::FileExpander() : _src(0) {
- _tables[0] = new uint8[3914];
- assert(_tables[0]);
-
- _tables[1] = _tables[0] + 320;
- _tables[2] = _tables[0] + 352;
- _tables[3] = _tables[0] + 864;
- _tables[4] = _tables[0] + 2016;
- _tables[5] = _tables[0] + 2528;
- _tables[6] = _tables[0] + 2656;
- _tables[7] = _tables[0] + 2736;
- _tables[8] = _tables[0] + 2756;
-
- _tables16[0] = (uint16 *)(_tables[0] + 3268);
- _tables16[1] = (uint16 *)(_tables[0] + 3302);
- _tables16[2] = (uint16 *)(_tables[0] + 3338);
-}
-
-FileExpander::~FileExpander() {
- delete _src;
- delete[] _tables[0];
-}
-
-bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 compressedSize) {
- static const uint8 indexTable[] = {
- 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, 0x0A,
- 0x05, 0x0B, 0x04, 0x0C, 0x03, 0x0D, 0x02, 0x0E, 0x01, 0x0F
- };
-
- memset(_tables[0], 0, 3914);
-
- uint8 *d = dst;
- uint16 tableSize0 = 0;
- uint16 tableSize1 = 0;
- bool needrefresh = true;
- bool postprocess = false;
-
- _src = new FileExpanderSource(src, compressedSize);
-
- while (d < dst + outsize) {
-
- if (needrefresh) {
- needrefresh = false;
- _src->advSrcRefresh();
- }
-
- _src->advSrcBitsBy1();
-
- int mode = _src->getKeyMasked(2) - 1;
- if (mode == 1) {
- tableSize0 = _src->getKeyMasked(5) + 257;
- tableSize1 = _src->getKeyMasked(5) + 1;
- memset(_tables[7], 0, 19);
-
- const uint8 *itbl = indexTable;
- int numbytes = _src->getKeyMasked(4) + 4;
-
- while (numbytes--)
- _tables[7][*itbl++] = _src->getKeyMasked(3);
-
- generateTables(7, 8, 255, 19);
-
- int cnt = tableSize0 + tableSize1;
- uint8 *tmp = _tables[0];
-
- while (cnt) {
- uint16 cmd = _src->getKeyLower();
- cmd = READ_LE_UINT16(&_tables[8][cmd << 1]);
- _src->advSrcBitsByIndex(_tables[7][cmd]);
-
- if (cmd < 16) {
- *tmp++ = cmd;
- cnt--;
- } else {
- uint8 tmpI = 0;
- if (cmd == 16) {
- cmd = _src->getKeyMasked(2) + 3;
- tmpI = *(tmp - 1);
- } else if (cmd == 17) {
- cmd = _src->getKeyMasked(3) + 3;
- } else {
- cmd = _src->getKeyMasked(7) + 11;
- }
- _src->setIndex(tmpI);
- memset(tmp, tmpI, cmd);
- tmp += cmd;
-
- cnt -= cmd;
- if (cnt < 0)
- error("decompression failure");
- }
+ stream->seek(0, SEEK_SET);
}
-
- memcpy(_tables[1], _tables[0] + tableSize0, tableSize1);
- generateTables(0, 2, 3, tableSize0);
- generateTables(1, 4, 5, tableSize1);
- postprocess = true;
- } else if (mode < 0) {
- _src->copyBytes(d);
- postprocess = false;
- needrefresh = true;
- } else if (mode == 0){
- uint8 *d2 = _tables[0];
- memset(d2, 8, 144);
- memset(d2 + 144, 9, 112);
- memset(d2 + 256, 7, 24);
- memset(d2 + 280, 8, 8);
- d2 = _tables[1];
- memset(d2, 5, 32);
- tableSize0 = 288;
- tableSize1 = 32;
-
- generateTables(0, 2, 3, tableSize0);
- generateTables(1, 4, 5, tableSize1);
- postprocess = true;
- } else {
- error("decompression failure");
}
-
- if (!postprocess)
- continue;
-
- int16 cmd = 0;
-
- do {
- cmd = ((int16*) _tables[2])[_src->getKeyLower()];
- _src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]);
-
- if (cmd == 0x11d) {
- cmd = 0x200;
- } else if (cmd > 0x108) {
- cmd = _src->keyMaskedAlign(cmd);
- }
-
- if (!(cmd >> 8)) {
- *d++ = cmd & 0xff;
- } else if (cmd != 0x100) {
- cmd -= 0xfe;
- int16 offset = ((int16*) _tables[4])[_src->getKeyLower()];
- _src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]);
- if ((offset & 0xff) >= 4) {
- uint8 newIndex = ((offset & 0xff) >> 1) - 1;
- offset = (((offset & 1) + 2) << newIndex);
- offset += _src->getKeyMasked(newIndex);
- }
-
- uint8 *s2 = d - 1 - offset;
- if (s2 >= dst) {
- while (cmd--)
- *d++ = *s2++;
- } else {
- uint32 pos = dst - s2;
- s2 += (d - dst);
-
- if (pos < (uint32) cmd) {
- cmd -= pos;
- while (pos--)
- *d++ = *s2++;
- s2 = dst;
- }
- while (cmd--)
- *d++ = *s2++;
- }
- }
- } while (cmd != 0x100);
}
- delete _src;
- _src = 0;
-
- return true;
-}
-
-void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) {
- const uint8 *tbl1 = _tables[srcIndex];
- uint8 *tbl2 = _tables[dstIndex];
- const uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2];
-
- if (!cnt)
- return;
-
- const uint8 *s = tbl1;
- memset(_tables16[0], 0, 32);
-
- for (int i = 0; i < cnt; i++)
- _tables16[0][(*s++)]++;
-
- _tables16[1][1] = 0;
-
- for (uint16 i = 1, r = 0; i < 16; i++) {
- r = (r + _tables16[0][i]) << 1;
- _tables16[1][i + 1] = r;
- }
-
- if (_tables16[1][16]) {
- uint16 r = 0;
- for (uint16 i = 1; i < 16; i++)
- r += _tables16[0][i];
- if (r > 1)
- error("decompression failure");
- }
-
- s = tbl1;
- uint16 *d = _tables16[2];
- for (int i = 0; i < cnt; i++) {
- uint16 t = *s++;
- if (t) {
- _tables16[1][t]++;
- t = _tables16[1][t] - 1;
- }
- *d++ = t;
- }
-
- s = tbl1;
- d = _tables16[2];
- for (int i = 0; i < cnt; i++) {
- int8 t = ((int8)(*s++)) - 1;
- if (t > 0) {
- uint16 v1 = *d;
- uint16 v2 = 0;
-
- do {
- v2 = (v2 << 1) | (v1 & 1);
- v1 >>= 1;
- } while (--t && v1);
-
- t++;
- uint8 c1 = (v1 & 1);
- while (t--) {
- uint8 c2 = v2 >> 15;
- v2 = (v2 << 1) | c1;
- c1 = c2;
- };
-
- *d++ = v2;
- } else {
- d++;
- }
- }
-
- memset(tbl2, 0, 512);
-
- cnt--;
- s = tbl1 + cnt;
- d = &_tables16[2][cnt];
- uint16 * bt = (uint16*) tbl3;
- uint16 inc = 0;
- uint16 cnt2 = 0;
-
- do {
- uint8 t = *s--;
- uint16 *s2 = (uint16*) tbl2;
-
- if (t && t < 9) {
- inc = 1 << t;
- uint16 o = *d;
-
- do {
- s2[o] = cnt;
- o += inc;
- } while (!(o & 0xf00));
-
- } else if (t > 8) {
- if (!bt)
- error("decompression failure");
-
- t -= 8;
- uint8 shiftCnt = 1;
- uint8 v = (*d) >> 8;
- s2 = &((uint16*) tbl2)[*d & 0xff];
-
- do {
- if (!*s2) {
- *s2 = (uint16)(~cnt2);
- *(uint32*)&bt[cnt2] = 0;
- cnt2 += 2;
- }
-
- s2 = &bt[(uint16)(~*s2)];
- if (v & shiftCnt)
- s2++;
-
- shiftCnt <<= 1;
- } while (--t);
- *s2 = cnt;
- }
- d--;
- } while (--cnt >= 0);
-}
-
-uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 &para) {
- const uint16 *t = (const uint16*)tbl;
- _src->advSrcBitsByIndex(8);
- uint8 newIndex = 0;
- uint16 v = _src->getKeyLower();
-
- do {
- newIndex++;
- para = t[((~para) & 0xfffe) | (v & 1)];
- v >>= 1;
- } while (para < 0);
-
- return newIndex;
-}
-
-class CompLoaderInsHof : public CompArchiveLoader {
-public:
- CompLoaderInsHof() {
- _fileExtP = "%03d";
- _checkFile1 = "WESTWOOD.001";
- _checkFile2 = "WESTWOOD.002";
- _containerOffset = 6;
- }
+ delete stream;
- virtual bool checkForFiles() const;
- virtual bool loadFile(CompFileMap &loadTo) const;
-
-protected:
- struct Archive {
- Common::String filename;
- uint32 firstFile;
- uint32 startOffset;
- uint32 lastFile;
- uint32 endOffset;
- uint32 totalSize;
- };
-
- const char *_fileExtP;
- const char *_checkFile1;
- const char *_checkFile2;
- uint8 _containerOffset;
-};
-
-class CompLoaderInsLol : public CompLoaderInsHof {
-public:
- CompLoaderInsLol() {
- _fileExtP = "%d";
- _checkFile1 = "WESTWOOD.1";
- _checkFile2 = "WESTWOOD.2";
- _containerOffset = 0;
- }
-};
+ if (!archive)
+ return Common::ArchivePtr();
-bool CompLoaderInsHof::checkForFiles() const {
- return (Common::File::exists(_checkFile1) && Common::File::exists(_checkFile2));
+ _archiveCache[file] = archive;
+ return archive;
}
-bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
- Common::File tmpFile;
-
- uint32 pos = 0;
- uint32 bytesleft = 0;
- bool startFile = true;
-
- Common::String filenameBase = "WESTWOOD.";
- Common::String filenameTemp;
- char filenameExt[4];
-
- while (filenameBase.lastChar() != '.')
- filenameBase.deleteLastChar();
-
- Archive newArchive;
-
- Common::List<Archive> archives;
-
- for (int8 currentFile = 1; currentFile; currentFile++) {
- sprintf(filenameExt, _fileExtP, currentFile);
- filenameTemp = filenameBase + Common::String(filenameExt);
-
- if (!tmpFile.open(filenameTemp)) {
- debug(3, "couldn't open file '%s'\n", filenameTemp.c_str());
- break;
- }
-
- tmpFile.seek(pos);
- uint8 fileId = tmpFile.readByte();
- pos++;
-
- uint32 size = tmpFile.size() - 1;
- if (startFile) {
- size -= 4;
- if (fileId == currentFile) {
- size -= _containerOffset;
- pos += _containerOffset;
- tmpFile.seek(_containerOffset, SEEK_CUR);
- } else {
- size = size + 1 - pos;
- }
- newArchive.filename = filenameBase;
- bytesleft = newArchive.totalSize = tmpFile.readUint32LE();
- pos += 4;
- newArchive.firstFile = currentFile;
- newArchive.startOffset = pos;
- startFile = false;
- }
-
- uint32 cs = MIN(size, bytesleft);
- bytesleft -= cs;
-
- tmpFile.close();
-
- pos += cs;
- if (cs == size) {
- if (!bytesleft) {
- newArchive.lastFile = currentFile;
- newArchive.endOffset = --pos;
- archives.push_back(newArchive);
- currentFile = -1;
- } else {
- pos = 0;
- }
- } else {
- startFile = true;
- bytesleft = size - cs;
- newArchive.lastFile = currentFile--;
- newArchive.endOffset = --pos;
- archives.push_back(newArchive);
- }
- }
+Common::ArchivePtr Resource::loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset) {
+ ArchiveMap::iterator cachedArchive = _archiveCache.find(file);
+ if (cachedArchive != _archiveCache.end())
+ return cachedArchive->_value;
- FileExpander exp;
- CompFileEntry newEntry;
- uint32 insize = 0;
- uint32 outsize = 0;
- uint8 *inbuffer = 0;
- uint8 *outbuffer = 0;
- uint32 inPart1 = 0;
- uint32 inPart2 = 0;
- uint8 compressionType = 0;
- Common::String entryStr;
-
- pos = 0;
-
- const uint32 kExecSize = 0x0bba;
- const uint32 kHeaderSize = 30;
- const uint32 kHeaderSize2 = 46;
-
- for (Common::List<Archive>::iterator a = archives.begin(); a != archives.end(); ++a) {
- startFile = true;
- for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) {
- sprintf(filenameExt, _fileExtP, i);
- filenameTemp = a->filename + Common::String(filenameExt);
-
- if (!tmpFile.open(filenameTemp)) {
- debug(3, "couldn't open file '%s'\n", filenameTemp.c_str());
- break;
- }
-
- uint32 size = (i == a->lastFile) ? a->endOffset : tmpFile.size();
-
- if (startFile) {
- startFile = false;
- pos = a->startOffset + kExecSize;
- if (pos > size) {
- pos -= size;
- tmpFile.close();
- continue;
- }
- } else {
- if (inPart2) {
- tmpFile.seek(1);
- tmpFile.read(inbuffer + inPart1, inPart2);
- inPart2 = 0;
-
- if (compressionType > 0)
- exp.process(outbuffer, inbuffer, outsize, insize);
- else
- memcpy(outbuffer, inbuffer, outsize);
-
- delete[] inbuffer;
- inbuffer = 0;
- newEntry.data = outbuffer;
- newEntry.size = outsize;
- loadTo[entryStr] = newEntry;
- }
- pos++;
- }
+ Common::ArchivePtr archive(InstallerLoader::load(this, file, ext, offset));
+ if (!archive)
+ return Common::ArchivePtr();
- while (pos < size) {
- uint8 hdr[43];
- uint32 m = 0;
- tmpFile.seek(pos);
-
- if (pos + 42 > size) {
- m = size - pos;
- uint32 b = 42 - m;
-
- if (m >= 4) {
- uint32 id = tmpFile.readUint32LE();
- if (id == 0x06054B50) {
- startFile = true;
- break;
- } else {
- tmpFile.seek(pos);
- }
- }
-
- sprintf(filenameExt, _fileExtP, i + 1);
- filenameTemp = a->filename + Common::String(filenameExt);
-
- Common::File tmpFile2;
- tmpFile2.open(filenameTemp);
- tmpFile.read(hdr, m);
- tmpFile2.read(hdr + m, b);
- tmpFile2.close();
-
- } else {
- tmpFile.read(hdr, 42);
- }
-
- uint32 id = READ_LE_UINT32(hdr);
-
- if (id == 0x04034B50) {
- compressionType = hdr[8];
- insize = READ_LE_UINT32(hdr + 18);
- outsize = READ_LE_UINT32(hdr + 22);
-
- uint16 filestrlen = READ_LE_UINT16(hdr + 26);
- *(hdr + 30 + filestrlen) = 0;
- entryStr = Common::String((const char *)(hdr + 30));
- pos += (kHeaderSize + filestrlen - m);
- tmpFile.seek(pos);
-
- outbuffer = new uint8[outsize];
- if (!outbuffer)
- error("Out of memory: Can't uncompress installer files");
-
- if (!inbuffer) {
- inbuffer = new uint8[insize];
- if (!inbuffer)
- error("Out of memory: Can't uncompress installer files");
- }
-
- if ((pos + insize) > size) {
- // this is for files that are split between two archive files
- inPart1 = size - pos;
- inPart2 = insize - inPart1;
- tmpFile.read(inbuffer, inPart1);
- } else {
- tmpFile.read(inbuffer, insize);
- inPart2 = 0;
-
- if (compressionType > 0)
- exp.process(outbuffer, inbuffer, outsize, insize);
- else
- memcpy(outbuffer, inbuffer, outsize);
-
- delete[] inbuffer;
- inbuffer = 0;
- newEntry.data = outbuffer;
- newEntry.size = outsize;
- loadTo[entryStr] = newEntry;
- }
-
- pos += insize;
- if (pos > size) {
- pos -= size;
- break;
- }
- } else {
- uint32 filestrlen = READ_LE_UINT32(hdr + 28);
- pos += (kHeaderSize2 + filestrlen - m);
- }
- }
- tmpFile.close();
- }
- }
-
- archives.clear();
- return true;
+ _archiveCache[file] = archive;
+ return archive;
}
#pragma mark -
@@ -1534,17 +321,6 @@ void Resource::initializeLoaders() {
_loaders.push_back(LoaderList::value_type(new ResLoaderPak()));
_loaders.push_back(LoaderList::value_type(new ResLoaderInsMalcolm()));
_loaders.push_back(LoaderList::value_type(new ResLoaderTlk()));
-
- _compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsHof()));
- _compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsLol()));
-}
-
-const ResArchiveLoader *Resource::getLoader(ResFileEntry::kType type) const {
- for (CLoaderIterator i = _loaders.begin(); i != _loaders.end(); ++i) {
- if ((*i)->getType() == type)
- return (*i).get();
- }
- return 0;
}
} // end of namespace Kyra
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index d43f730e6b..799068d158 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -35,74 +35,16 @@
#include "common/hashmap.h"
#include "common/stream.h"
#include "common/ptr.h"
+#include "common/archive.h"
#include "kyra/kyra_v1.h"
#include "kyra/kyra_hof.h"
namespace Kyra {
-struct ResFileEntry {
- Common::String parent;
- uint32 size;
-
- bool preload;
- bool mounted;
- bool prot;
-
- enum kType {
- kRaw = 0,
- kPak = 1,
- kInsMal = 2,
- kTlk = 3,
- kAutoDetect
- };
- kType type;
- uint32 offset;
-};
-
-struct CompFileEntry {
- uint32 size;
- uint8 *data;
-};
-
-typedef Common::HashMap<Common::String, ResFileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ResFileMap;
-typedef Common::HashMap<Common::String, CompFileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CompFileMap;
class Resource;
-class ResArchiveLoader {
-public:
- struct File {
- File() : filename(), entry() {}
- File(const Common::String &f, const ResFileEntry &e) : filename(f), entry(e) {}
-
- bool operator ==(const Common::String &r) const {
- return filename.equalsIgnoreCase(r);
- }
-
- Common::String filename;
- ResFileEntry entry;
- };
- typedef Common::List<File> FileList;
-
- virtual ~ResArchiveLoader() {}
-
- virtual bool checkFilename(Common::String filename) const = 0;
- virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0;
- virtual bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const = 0;
- // parameter 'archive' can be deleted by this method and it may not be deleted from the caller
- virtual Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const = 0;
-
- virtual ResFileEntry::kType getType() const = 0;
-protected:
-};
-
-class CompArchiveLoader {
-public:
- virtual ~CompArchiveLoader() {}
-
- virtual bool checkForFiles() const = 0;
- virtual bool loadFile(CompFileMap &loadTo) const = 0;
-};
+class ResArchiveLoader;
class Resource {
public:
@@ -111,9 +53,9 @@ public:
bool reset();
- bool loadPakFile(const Common::String &filename);
- void unloadPakFile(const Common::String &filename);
- bool isInPakList(const Common::String &filename);
+ bool loadPakFile(Common::String filename);
+ void unloadPakFile(Common::String filename);
+ bool isInPakList(Common::String filename);
bool loadFileList(const Common::String &filedata);
bool loadFileList(const char * const *filelist, uint32 numFiles);
@@ -127,27 +69,20 @@ public:
bool loadFileToBuf(const char *file, void *buf, uint32 maxSize);
protected:
- void checkFile(const Common::String &file);
- bool isAccessable(const Common::String &file);
+ typedef Common::HashMap<Common::String, Common::ArchivePtr, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> ArchiveMap;
+ ArchiveMap _archiveCache;
+
+ Common::SearchSet _files;
+ Common::SharedPtr<Common::SearchSet> _archiveFiles;
+ Common::SharedPtr<Common::SearchSet> _protectedFiles;
- void detectFileTypes();
+ Common::ArchivePtr loadArchive(const Common::String &file);
+ Common::ArchivePtr loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset);
void initializeLoaders();
- const ResArchiveLoader *getLoader(ResFileEntry::kType type) const;
+
typedef Common::List<Common::SharedPtr<ResArchiveLoader> > LoaderList;
- typedef LoaderList::iterator LoaderIterator;
- typedef LoaderList::const_iterator CLoaderIterator;
LoaderList _loaders;
- ResFileMap _map;
-
- typedef Common::List<Common::SharedPtr<CompArchiveLoader> > CompLoaderList;
- typedef CompLoaderList::iterator CompLoaderIterator;
- typedef CompLoaderList::const_iterator CCompLoaderIterator;
- CompLoaderList _compLoaders;
- CompFileMap _compFiles;
-
- void tryLoadCompFiles();
- void clearCompFileList();
KyraEngine_v1 *_vm;
};
@@ -277,7 +212,7 @@ public:
StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _builtIn(0), _filenameTable(0) {}
~StaticResource() { deinit(); }
- static bool checkKyraDat();
+ static bool checkKyraDat(Resource *res);
bool init();
void deinit();
@@ -332,7 +267,7 @@ private:
void freeHofShapeAnimDataV2(void *&ptr, int &size);
const char *getFilename(const char *name);
- uint8 *getFile(const char *name, int &size);
+ Common::SeekableReadStream *getFile(const char *name);
enum kResTypes {
kLanguageList,
diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp
new file mode 100644
index 0000000000..f97319a43a
--- /dev/null
+++ b/engines/kyra/resource_intern.cpp
@@ -0,0 +1,1072 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "kyra/resource_intern.h"
+#include "kyra/resource.h"
+
+#include "common/stream.h"
+#include "common/endian.h"
+
+namespace Kyra {
+
+// Implementation of various Archive subclasses
+
+// -> PlainArchive implementation
+
+PlainArchive::PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files)
+ : _owner(owner), _filename(filename), _files() {
+ for (FileInputList::iterator i = files.begin(); i != files.end(); ++i) {
+ Entry entry;
+
+ entry.offset = i->offset;
+ entry.size = i->size;
+
+ _files[i->name] = entry;
+ }
+}
+
+bool PlainArchive::hasFile(const Common::String &name) {
+ return (_files.find(name) != _files.end());
+}
+
+int PlainArchive::getAllNames(Common::StringList &list) {
+ int count = 0;
+
+ for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) {
+ list.push_back(i->_key);
+ ++count;
+ }
+
+ return count;
+}
+
+Common::SeekableReadStream *PlainArchive::openFile(const Common::String &name) {
+ FileMap::const_iterator fDesc = _files.find(name);
+ if (fDesc == _files.end())
+ return 0;
+
+ Common::SeekableReadStream *parent = _owner->getFileStream(_filename);
+ if (!parent)
+ return 0;
+
+ return new Common::SeekableSubReadStream(parent, fDesc->_value.offset, fDesc->_value.offset + fDesc->_value.size, true);
+}
+
+// -> CachedArchive implementation
+
+CachedArchive::CachedArchive(const FileInputList &files)
+ : _files() {
+ for (FileInputList::iterator i = files.begin(); i != files.end(); ++i) {
+ Entry entry;
+
+ entry.data = i->data;
+ entry.size = i->size;
+
+ _files[i->name] = entry;
+ }
+}
+
+CachedArchive::~CachedArchive() {
+ for (FileMap::iterator i = _files.begin(); i != _files.end(); ++i)
+ delete[] i->_value.data;
+ _files.clear();
+}
+
+bool CachedArchive::hasFile(const Common::String &name) {
+ return (_files.find(name) != _files.end());
+}
+
+int CachedArchive::getAllNames(Common::StringList &list) {
+ int count = 0;
+
+ for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) {
+ list.push_back(i->_key);
+ ++count;
+ }
+
+ return count;
+}
+
+Common::SeekableReadStream *CachedArchive::openFile(const Common::String &name) {
+ FileMap::const_iterator fDesc = _files.find(name);
+ if (fDesc == _files.end())
+ return 0;
+
+ return new Common::MemoryReadStream(fDesc->_value.data, fDesc->_value.size, false);
+}
+
+// ResFileLoader implementations
+
+// -> ResLoaderPak implementation
+
+bool ResLoaderPak::checkFilename(Common::String filename) const {
+ filename.toUppercase();
+ return (filename.hasSuffix(".PAK") || filename.hasSuffix(".APK") || filename.hasSuffix(".VRM") || filename.hasSuffix(".TLK") || filename.equalsIgnoreCase(StaticResource::staticDataFilename()));
+}
+
+bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
+ int32 filesize = stream.size();
+ int32 offset = 0;
+ bool switchEndian = false;
+ bool firstFile = true;
+
+ offset = stream.readUint32LE();
+ if (offset > filesize) {
+ switchEndian = true;
+ offset = SWAP_BYTES_32(offset);
+ }
+
+ Common::String file;
+ while (!stream.eos()) {
+ // The start offset of a file should never be in the filelist
+ if (offset < stream.pos() || offset > filesize)
+ return false;
+
+ byte c = 0;
+
+ file.clear();
+
+ while (!stream.eos() && (c = stream.readByte()) != 0)
+ file += c;
+
+ if (stream.eos())
+ return false;
+
+ // Quit now if we encounter an empty string
+ if (file.empty()) {
+ if (firstFile)
+ return false;
+ else
+ break;
+ }
+
+ firstFile = false;
+ offset = switchEndian ? stream.readUint32BE() : stream.readUint32LE();
+
+ if (!offset || offset == filesize)
+ break;
+ }
+
+ return true;
+}
+
+namespace {
+
+Common::String readString(Common::SeekableReadStream &stream) {
+ Common::String result;
+ char c = 0;
+
+ while ((c = stream.readByte()) != 0)
+ result += c;
+
+ return result;
+}
+
+struct PlainArchiveListSearch {
+ PlainArchiveListSearch(const Common::String &search) : _search(search) {}
+
+ bool operator()(const PlainArchive::InputEntry &entry) {
+ return _search.equalsIgnoreCase(entry.name);
+ }
+ Common::String _search;
+};
+
+} // end of anonymous namespace
+
+Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const {
+ int32 filesize = stream.size();
+
+ int32 startoffset = 0, endoffset = 0;
+ bool switchEndian = false;
+ bool firstFile = true;
+
+ startoffset = stream.readUint32LE();
+ if (startoffset > filesize) {
+ switchEndian = true;
+ startoffset = SWAP_BYTES_32(startoffset);
+ }
+
+ PlainArchive::FileInputList files;
+
+ Common::String file;
+ while (!stream.eos()) {
+ // The start offset of a file should never be in the filelist
+ if (startoffset < stream.pos() || startoffset > filesize) {
+ warning("PAK file '%s' is corrupted", filename.c_str());
+ return false;
+ }
+
+ file.clear();
+ byte c = 0;
+
+ while (!stream.eos() && (c = stream.readByte()) != 0)
+ file += c;
+
+ if (stream.eos()) {
+ warning("PAK file '%s' is corrupted", filename.c_str());
+ return false;
+ }
+
+ // Quit now if we encounter an empty string
+ if (file.empty()) {
+ if (firstFile) {
+ warning("PAK file '%s' is corrupted", filename.c_str());
+ return false;
+ } else {
+ break;
+ }
+ }
+
+ firstFile = false;
+ endoffset = switchEndian ? stream.readUint32BE() : stream.readUint32LE();
+
+ if (!endoffset)
+ endoffset = filesize;
+
+ if (startoffset != endoffset) {
+ PlainArchive::InputEntry entry;
+ entry.size = endoffset - startoffset;
+ entry.offset = startoffset;
+ entry.name = file;
+
+ files.push_back(entry);
+ }
+
+ if (endoffset == filesize)
+ break;
+
+ startoffset = endoffset;
+ }
+
+ PlainArchive::FileInputList::const_iterator iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch("LINKLIST"));
+ if (iter != files.end()) {
+ stream.seek(iter->offset, SEEK_SET);
+
+ uint32 magic = stream.readUint32BE();
+
+ if (magic != MKID_BE('SCVM'))
+ error("LINKLIST file does not contain 'SCVM' header");
+
+ uint32 links = stream.readUint32BE();
+ for (uint i = 0; i < links; ++i) {
+ Common::String linksTo = readString(stream);
+ uint32 sources = stream.readUint32BE();
+
+ iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch(linksTo));
+ if (iter == files.end())
+ error("PAK file link destination '%s' not found", linksTo.c_str());
+
+ for (uint j = 0; j < sources; ++j) {
+ Common::String dest = readString(stream);
+ files.push_back(*iter);
+ // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it
+ iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch(linksTo));
+ }
+ }
+ }
+
+ return new PlainArchive(owner, filename, files);
+}
+
+// -> ResLoaderInsMalcolm implementation
+
+bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const {
+ filename.toUppercase();
+ if (!filename.hasSuffix(".001"))
+ return false;
+ return true;
+}
+
+bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
+ stream.seek(3, SEEK_SET);
+ int32 size = stream.readUint32LE();
+
+ if (size+7 > stream.size())
+ return false;
+
+ stream.seek(size+5, SEEK_SET);
+ uint8 buffer[2];
+ stream.read(&buffer, 2);
+
+ return (buffer[0] == 0x0D && buffer[1] == 0x0A);
+}
+
+Common::Archive *ResLoaderInsMalcolm::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const {
+ Common::List<Common::String> filenames;
+ PlainArchive::FileInputList files;
+
+ // thanks to eriktorbjorn for this code (a bit modified though)
+ stream.seek(3, SEEK_SET);
+
+ // first file is the index table
+ uint32 size = stream.readUint32LE();
+ Common::String temp;
+
+ for (uint32 i = 0; i < size; ++i) {
+ byte c = stream.readByte();
+
+ if (c == '\\') {
+ temp.clear();
+ } else if (c == 0x0D) {
+ // line endings are CRLF
+ c = stream.readByte();
+ assert(c == 0x0A);
+ ++i;
+
+ filenames.push_back(temp);
+ } else {
+ temp += (char)c;
+ }
+ }
+
+ stream.seek(3, SEEK_SET);
+
+ for (Common::List<Common::String>::iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ PlainArchive::InputEntry entry;
+ entry.size = stream.readUint32LE();
+ entry.offset = stream.pos();
+ entry.name = *file;
+ stream.seek(entry.size, SEEK_CUR);
+
+ files.push_back(entry);
+ }
+
+ return new PlainArchive(owner, filename, files);
+}
+
+bool ResLoaderTlk::checkFilename(Common::String filename) const {
+ filename.toUppercase();
+ return (filename.hasSuffix(".TLK"));
+}
+
+bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
+ uint16 entries = stream.readUint16LE();
+ int32 entryTableSize = (entries * 8);
+
+ if (entryTableSize + 2 > stream.size())
+ return false;
+
+ int32 offset = 0;
+
+ for (uint i = 0; i < entries; ++i) {
+ stream.readUint32LE();
+ offset = stream.readUint32LE();
+
+ if (offset > stream.size())
+ return false;
+ }
+
+ return true;
+}
+
+Common::Archive *ResLoaderTlk::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const {
+ uint16 entries = stream.readUint16LE();
+ PlainArchive::FileInputList files;
+
+ for (uint i = 0; i < entries; ++i) {
+ PlainArchive::InputEntry entry;
+
+ uint32 resFilename = stream.readUint32LE();
+ uint32 resOffset = stream.readUint32LE();
+
+ entry.offset = resOffset+4;
+
+ char realFilename[20];
+ snprintf(realFilename, 20, "%.08u.AUD", resFilename);
+ entry.name = realFilename;
+
+ uint32 curOffset = stream.pos();
+ stream.seek(resOffset, SEEK_SET);
+ entry.size = stream.readUint32LE();
+ stream.seek(curOffset, SEEK_SET);
+
+ files.push_back(entry);
+ }
+
+ return new PlainArchive(owner, filename, files);
+}
+
+// InstallerLoader implementation
+
+class FileExpanderSource {
+public:
+ FileExpanderSource(const uint8 *data, int dataSize) : _dataPtr(data), _endofBuffer(data + dataSize), _bitsLeft(8), _key(0), _index(0) {}
+ ~FileExpanderSource() {}
+
+ void advSrcRefresh();
+ void advSrcBitsBy1();
+ void advSrcBitsByIndex(uint8 newIndex);
+
+ uint8 getKeyLower() { return _key & 0xff; }
+ void setIndex(uint8 index) { _index = index; }
+ uint16 getKeyMasked(uint8 newIndex);
+ uint16 keyMaskedAlign(uint16 val);
+
+ void copyBytes(uint8 *& dst);
+
+private:
+ const uint8 *_dataPtr;
+ const uint8 *_endofBuffer;
+ uint16 _key;
+ int8 _bitsLeft;
+ uint8 _index;
+};
+
+void FileExpanderSource::advSrcBitsBy1() {
+ _key >>= 1;
+ if (!--_bitsLeft) {
+ if (_dataPtr < _endofBuffer)
+ _key = ((*_dataPtr++) << 8 ) | (_key & 0xff);
+ _bitsLeft = 8;
+ }
+}
+
+void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) {
+ _index = newIndex;
+ _bitsLeft -= _index;
+ if (_bitsLeft <= 0) {
+ _key >>= (_index + _bitsLeft);
+ _index = -_bitsLeft;
+ _bitsLeft = 8 - _index;
+ if (_dataPtr < _endofBuffer)
+ _key = (*_dataPtr++ << 8) | (_key & 0xff);
+ }
+ _key >>= _index;
+}
+
+uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) {
+ static const uint8 mskTable[] = { 0x0F, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
+ _index = newIndex;
+ uint16 res = 0;
+
+ if (_index > 8) {
+ newIndex = _index - 8;
+ res = (_key & 0xff) & mskTable[8];
+ advSrcBitsByIndex(8);
+ _index = newIndex;
+ res |= (((_key & 0xff) & mskTable[_index]) << 8);
+ advSrcBitsByIndex(_index);
+ } else {
+ res = (_key & 0xff) & mskTable[_index];
+ advSrcBitsByIndex(_index);
+ }
+
+ return res;
+}
+
+void FileExpanderSource::copyBytes(uint8 *& dst) {
+ advSrcBitsByIndex(_bitsLeft);
+ uint16 r = (READ_LE_UINT16(_dataPtr) ^ _key) + 1;
+ _dataPtr += 2;
+
+ if (r)
+ error("decompression failure");
+
+ memcpy(dst, _dataPtr, _key);
+ _dataPtr += _key;
+ dst += _key;
+}
+
+uint16 FileExpanderSource::keyMaskedAlign(uint16 val) {
+ val -= 0x101;
+ _index = (val & 0xff) >> 2;
+ int16 b = ((_bitsLeft << 8) | _index) - 1;
+ _bitsLeft = b >> 8;
+ _index = b & 0xff;
+ uint16 res = (((val & 3) + 4) << _index) + 0x101;
+ return res + getKeyMasked(_index);
+}
+
+void FileExpanderSource::advSrcRefresh() {
+ _key = READ_LE_UINT16(_dataPtr);
+ if (_dataPtr < _endofBuffer - 1)
+ _dataPtr += 2;
+ _bitsLeft = 8;
+}
+
+class FileExpander {
+public:
+ FileExpander();
+ ~FileExpander();
+
+ bool process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 insize);
+
+private:
+ void generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt);
+ uint8 calcCmdAndIndex(const uint8 *tbl, int16 &para);
+
+ FileExpanderSource *_src;
+ uint8 *_tables[9];
+ uint16 *_tables16[3];
+};
+
+FileExpander::FileExpander() : _src(0) {
+ _tables[0] = new uint8[3914];
+ assert(_tables[0]);
+
+ _tables[1] = _tables[0] + 320;
+ _tables[2] = _tables[0] + 352;
+ _tables[3] = _tables[0] + 864;
+ _tables[4] = _tables[0] + 2016;
+ _tables[5] = _tables[0] + 2528;
+ _tables[6] = _tables[0] + 2656;
+ _tables[7] = _tables[0] + 2736;
+ _tables[8] = _tables[0] + 2756;
+
+ _tables16[0] = (uint16 *)(_tables[0] + 3268);
+ _tables16[1] = (uint16 *)(_tables[0] + 3302);
+ _tables16[2] = (uint16 *)(_tables[0] + 3338);
+}
+
+FileExpander::~FileExpander() {
+ delete _src;
+ delete[] _tables[0];
+}
+
+bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 compressedSize) {
+ static const uint8 indexTable[] = {
+ 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, 0x0A,
+ 0x05, 0x0B, 0x04, 0x0C, 0x03, 0x0D, 0x02, 0x0E, 0x01, 0x0F
+ };
+
+ memset(_tables[0], 0, 3914);
+
+ uint8 *d = dst;
+ uint16 tableSize0 = 0;
+ uint16 tableSize1 = 0;
+ bool needrefresh = true;
+ bool postprocess = false;
+
+ _src = new FileExpanderSource(src, compressedSize);
+
+ while (d < dst + outsize) {
+
+ if (needrefresh) {
+ needrefresh = false;
+ _src->advSrcRefresh();
+ }
+
+ _src->advSrcBitsBy1();
+
+ int mode = _src->getKeyMasked(2) - 1;
+ if (mode == 1) {
+ tableSize0 = _src->getKeyMasked(5) + 257;
+ tableSize1 = _src->getKeyMasked(5) + 1;
+ memset(_tables[7], 0, 19);
+
+ const uint8 *itbl = indexTable;
+ int numbytes = _src->getKeyMasked(4) + 4;
+
+ while (numbytes--)
+ _tables[7][*itbl++] = _src->getKeyMasked(3);
+
+ generateTables(7, 8, 255, 19);
+
+ int cnt = tableSize0 + tableSize1;
+ uint8 *tmp = _tables[0];
+
+ while (cnt) {
+ uint16 cmd = _src->getKeyLower();
+ cmd = READ_LE_UINT16(&_tables[8][cmd << 1]);
+ _src->advSrcBitsByIndex(_tables[7][cmd]);
+
+ if (cmd < 16) {
+ *tmp++ = cmd;
+ cnt--;
+ } else {
+ uint8 tmpI = 0;
+ if (cmd == 16) {
+ cmd = _src->getKeyMasked(2) + 3;
+ tmpI = *(tmp - 1);
+ } else if (cmd == 17) {
+ cmd = _src->getKeyMasked(3) + 3;
+ } else {
+ cmd = _src->getKeyMasked(7) + 11;
+ }
+ _src->setIndex(tmpI);
+ memset(tmp, tmpI, cmd);
+ tmp += cmd;
+
+ cnt -= cmd;
+ if (cnt < 0)
+ error("decompression failure");
+ }
+ }
+
+ memcpy(_tables[1], _tables[0] + tableSize0, tableSize1);
+ generateTables(0, 2, 3, tableSize0);
+ generateTables(1, 4, 5, tableSize1);
+ postprocess = true;
+ } else if (mode < 0) {
+ _src->copyBytes(d);
+ postprocess = false;
+ needrefresh = true;
+ } else if (mode == 0){
+ uint8 *d2 = _tables[0];
+ memset(d2, 8, 144);
+ memset(d2 + 144, 9, 112);
+ memset(d2 + 256, 7, 24);
+ memset(d2 + 280, 8, 8);
+ d2 = _tables[1];
+ memset(d2, 5, 32);
+ tableSize0 = 288;
+ tableSize1 = 32;
+
+ generateTables(0, 2, 3, tableSize0);
+ generateTables(1, 4, 5, tableSize1);
+ postprocess = true;
+ } else {
+ error("decompression failure");
+ }
+
+ if (!postprocess)
+ continue;
+
+ int16 cmd = 0;
+
+ do {
+ cmd = ((int16*) _tables[2])[_src->getKeyLower()];
+ _src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]);
+
+ if (cmd == 0x11d) {
+ cmd = 0x200;
+ } else if (cmd > 0x108) {
+ cmd = _src->keyMaskedAlign(cmd);
+ }
+
+ if (!(cmd >> 8)) {
+ *d++ = cmd & 0xff;
+ } else if (cmd != 0x100) {
+ cmd -= 0xfe;
+ int16 offset = ((int16*) _tables[4])[_src->getKeyLower()];
+ _src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]);
+ if ((offset & 0xff) >= 4) {
+ uint8 newIndex = ((offset & 0xff) >> 1) - 1;
+ offset = (((offset & 1) + 2) << newIndex);
+ offset += _src->getKeyMasked(newIndex);
+ }
+
+ uint8 *s2 = d - 1 - offset;
+ if (s2 >= dst) {
+ while (cmd--)
+ *d++ = *s2++;
+ } else {
+ uint32 pos = dst - s2;
+ s2 += (d - dst);
+
+ if (pos < (uint32) cmd) {
+ cmd -= pos;
+ while (pos--)
+ *d++ = *s2++;
+ s2 = dst;
+ }
+ while (cmd--)
+ *d++ = *s2++;
+ }
+ }
+ } while (cmd != 0x100);
+ }
+
+ delete _src;
+ _src = 0;
+
+ return true;
+}
+
+void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) {
+ const uint8 *tbl1 = _tables[srcIndex];
+ uint8 *tbl2 = _tables[dstIndex];
+ const uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2];
+
+ if (!cnt)
+ return;
+
+ const uint8 *s = tbl1;
+ memset(_tables16[0], 0, 32);
+
+ for (int i = 0; i < cnt; i++)
+ _tables16[0][(*s++)]++;
+
+ _tables16[1][1] = 0;
+
+ for (uint16 i = 1, r = 0; i < 16; i++) {
+ r = (r + _tables16[0][i]) << 1;
+ _tables16[1][i + 1] = r;
+ }
+
+ if (_tables16[1][16]) {
+ uint16 r = 0;
+ for (uint16 i = 1; i < 16; i++)
+ r += _tables16[0][i];
+ if (r > 1)
+ error("decompression failure");
+ }
+
+ s = tbl1;
+ uint16 *d = _tables16[2];
+ for (int i = 0; i < cnt; i++) {
+ uint16 t = *s++;
+ if (t) {
+ _tables16[1][t]++;
+ t = _tables16[1][t] - 1;
+ }
+ *d++ = t;
+ }
+
+ s = tbl1;
+ d = _tables16[2];
+ for (int i = 0; i < cnt; i++) {
+ int8 t = ((int8)(*s++)) - 1;
+ if (t > 0) {
+ uint16 v1 = *d;
+ uint16 v2 = 0;
+
+ do {
+ v2 = (v2 << 1) | (v1 & 1);
+ v1 >>= 1;
+ } while (--t && v1);
+
+ t++;
+ uint8 c1 = (v1 & 1);
+ while (t--) {
+ uint8 c2 = v2 >> 15;
+ v2 = (v2 << 1) | c1;
+ c1 = c2;
+ };
+
+ *d++ = v2;
+ } else {
+ d++;
+ }
+ }
+
+ memset(tbl2, 0, 512);
+
+ cnt--;
+ s = tbl1 + cnt;
+ d = &_tables16[2][cnt];
+ uint16 * bt = (uint16*) tbl3;
+ uint16 inc = 0;
+ uint16 cnt2 = 0;
+
+ do {
+ uint8 t = *s--;
+ uint16 *s2 = (uint16*) tbl2;
+
+ if (t && t < 9) {
+ inc = 1 << t;
+ uint16 o = *d;
+
+ do {
+ s2[o] = cnt;
+ o += inc;
+ } while (!(o & 0xf00));
+
+ } else if (t > 8) {
+ if (!bt)
+ error("decompression failure");
+
+ t -= 8;
+ uint8 shiftCnt = 1;
+ uint8 v = (*d) >> 8;
+ s2 = &((uint16*) tbl2)[*d & 0xff];
+
+ do {
+ if (!*s2) {
+ *s2 = (uint16)(~cnt2);
+ *(uint32*)&bt[cnt2] = 0;
+ cnt2 += 2;
+ }
+
+ s2 = &bt[(uint16)(~*s2)];
+ if (v & shiftCnt)
+ s2++;
+
+ shiftCnt <<= 1;
+ } while (--t);
+ *s2 = cnt;
+ }
+ d--;
+ } while (--cnt >= 0);
+}
+
+uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 &para) {
+ const uint16 *t = (const uint16*)tbl;
+ _src->advSrcBitsByIndex(8);
+ uint8 newIndex = 0;
+ uint16 v = _src->getKeyLower();
+
+ do {
+ newIndex++;
+ para = t[((~para) & 0xfffe) | (v & 1)];
+ v >>= 1;
+ } while (para < 0);
+
+ return newIndex;
+}
+
+namespace {
+
+struct InsArchive {
+ Common::String filename;
+ uint32 firstFile;
+ uint32 startOffset;
+ uint32 lastFile;
+ uint32 endOffset;
+ uint32 totalSize;
+};
+
+} // end of anonymouse namespace
+
+Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &filename, const Common::String &extension, const uint8 containerOffset) {
+ uint32 pos = 0;
+ uint32 bytesleft = 0;
+ bool startFile = true;
+
+ Common::String filenameBase =filename;
+ Common::String filenameTemp;
+ char filenameExt[4];
+
+ if (filenameBase.lastChar() != '.')
+ filenameBase += '.';
+
+ InsArchive newArchive;
+ Common::List<InsArchive> archives;
+
+ Common::SeekableReadStream *tmpFile = 0;
+
+ for (int8 currentFile = 1; currentFile; currentFile++) {
+ sprintf(filenameExt, extension.c_str(), currentFile);
+ filenameTemp = filenameBase + Common::String(filenameExt);
+
+ if (!(tmpFile = owner->getFileStream(filenameTemp))) {
+ debug(3, "couldn't open file '%s'\n", filenameTemp.c_str());
+ break;
+ }
+
+ tmpFile->seek(pos, SEEK_SET);
+ uint8 fileId = tmpFile->readByte();
+ pos++;
+
+ uint32 size = tmpFile->size() - 1;
+ if (startFile) {
+ size -= 4;
+ if (fileId == currentFile) {
+ size -= containerOffset;
+ pos += containerOffset;
+ tmpFile->seek(containerOffset, SEEK_CUR);
+ } else {
+ size = size + 1 - pos;
+ }
+ newArchive.filename = filenameBase;
+ bytesleft = newArchive.totalSize = tmpFile->readUint32LE();
+ pos += 4;
+ newArchive.firstFile = currentFile;
+ newArchive.startOffset = pos;
+ startFile = false;
+ }
+
+ uint32 cs = MIN(size, bytesleft);
+ bytesleft -= cs;
+
+ delete tmpFile;
+ tmpFile = 0;
+
+ pos += cs;
+ if (cs == size) {
+ if (!bytesleft) {
+ newArchive.lastFile = currentFile;
+ newArchive.endOffset = --pos;
+ archives.push_back(newArchive);
+ currentFile = -1;
+ } else {
+ pos = 0;
+ }
+ } else {
+ startFile = true;
+ bytesleft = size - cs;
+ newArchive.lastFile = currentFile--;
+ newArchive.endOffset = --pos;
+ archives.push_back(newArchive);
+ }
+ }
+
+ FileExpander exp;
+ CachedArchive::InputEntry newEntry;
+ uint32 insize = 0;
+ uint32 outsize = 0;
+ uint8 *inbuffer = 0;
+ uint8 *outbuffer = 0;
+ uint32 inPart1 = 0;
+ uint32 inPart2 = 0;
+ uint8 compressionType = 0;
+ Common::String entryStr;
+
+ CachedArchive::FileInputList fileList;
+
+ pos = 0;
+
+ const uint32 kExecSize = 0x0bba;
+ const uint32 kHeaderSize = 30;
+ const uint32 kHeaderSize2 = 46;
+
+ for (Common::List<InsArchive>::iterator a = archives.begin(); a != archives.end(); ++a) {
+ startFile = true;
+ for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) {
+ sprintf(filenameExt, extension.c_str(), i);
+ filenameTemp = a->filename + Common::String(filenameExt);
+
+ if (!(tmpFile = owner->getFileStream(filenameTemp))) {
+ debug(3, "couldn't open file '%s'\n", filenameTemp.c_str());
+ break;
+ }
+
+ uint32 size = (i == a->lastFile) ? a->endOffset : tmpFile->size();
+
+ if (startFile) {
+ startFile = false;
+ pos = a->startOffset + kExecSize;
+ if (pos > size) {
+ pos -= size;
+ delete tmpFile;
+ tmpFile = 0;
+ continue;
+ }
+ } else {
+ if (inPart2) {
+ tmpFile->seek(1, SEEK_SET);
+ tmpFile->read(inbuffer + inPart1, inPart2);
+ inPart2 = 0;
+
+ if (compressionType > 0)
+ exp.process(outbuffer, inbuffer, outsize, insize);
+ else
+ memcpy(outbuffer, inbuffer, outsize);
+
+ delete[] inbuffer;
+ inbuffer = 0;
+ newEntry.data = outbuffer;
+ newEntry.size = outsize;
+ newEntry.name = entryStr;
+ fileList.push_back(newEntry);
+ }
+ pos++;
+ }
+
+ while (pos < size) {
+ uint8 hdr[43];
+ uint32 m = 0;
+ tmpFile->seek(pos, SEEK_SET);
+
+ if (pos + 42 > size) {
+ m = size - pos;
+ uint32 b = 42 - m;
+
+ if (m >= 4) {
+ uint32 id = tmpFile->readUint32LE();
+ if (id == 0x06054B50) {
+ startFile = true;
+ break;
+ } else {
+ tmpFile->seek(pos, SEEK_SET);
+ }
+ }
+
+ sprintf(filenameExt, extension.c_str(), i + 1);
+ filenameTemp = a->filename + Common::String(filenameExt);
+
+ Common::SeekableReadStream *tmpFile2 = owner->getFileStream(filenameTemp);
+ tmpFile->read(hdr, m);
+ tmpFile2->read(hdr + m, b);
+ delete tmpFile2;
+ } else {
+ tmpFile->read(hdr, 42);
+ }
+
+ uint32 id = READ_LE_UINT32(hdr);
+
+ if (id == 0x04034B50) {
+ compressionType = hdr[8];
+ insize = READ_LE_UINT32(hdr + 18);
+ outsize = READ_LE_UINT32(hdr + 22);
+
+ uint16 filestrlen = READ_LE_UINT16(hdr + 26);
+ *(hdr + 30 + filestrlen) = 0;
+ entryStr = Common::String((const char *)(hdr + 30));
+ pos += (kHeaderSize + filestrlen - m);
+ tmpFile->seek(pos, SEEK_SET);
+
+ outbuffer = new uint8[outsize];
+ if (!outbuffer)
+ error("Out of memory: Can't uncompress installer files");
+
+ if (!inbuffer) {
+ inbuffer = new uint8[insize];
+ if (!inbuffer)
+ error("Out of memory: Can't uncompress installer files");
+ }
+
+ if ((pos + insize) > size) {
+ // this is for files that are split between two archive files
+ inPart1 = size - pos;
+ inPart2 = insize - inPart1;
+ tmpFile->read(inbuffer, inPart1);
+ } else {
+ tmpFile->read(inbuffer, insize);
+ inPart2 = 0;
+
+ if (compressionType > 0)
+ exp.process(outbuffer, inbuffer, outsize, insize);
+ else
+ memcpy(outbuffer, inbuffer, outsize);
+
+ delete[] inbuffer;
+ inbuffer = 0;
+ newEntry.data = outbuffer;
+ newEntry.size = outsize;
+ newEntry.name = entryStr;
+ fileList.push_back(newEntry);
+ }
+
+ pos += insize;
+ if (pos > size) {
+ pos -= size;
+ break;
+ }
+ } else {
+ uint32 filestrlen = READ_LE_UINT32(hdr + 28);
+ pos += (kHeaderSize2 + filestrlen - m);
+ }
+ }
+ delete tmpFile;
+ tmpFile = 0;
+ }
+ }
+
+ archives.clear();
+ return new CachedArchive(fileList);
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h
new file mode 100644
index 0000000000..1335be5e4e
--- /dev/null
+++ b/engines/kyra/resource_intern.h
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 KYRA_RESOURCE_INTERN_H
+#define KYRA_RESOURCE_INTERN_H
+
+#include "common/archive.h"
+#include "common/hash-str.h"
+#include "common/hashmap.h"
+#include "common/str.h"
+#include "common/list.h"
+
+namespace Kyra {
+
+class Resource;
+
+class PlainArchive : public Common::Archive {
+public:
+ struct InputEntry {
+ Common::String name;
+
+ uint32 offset;
+ uint32 size;
+ };
+
+ typedef Common::List<InputEntry> FileInputList;
+
+ PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files);
+
+ bool hasFile(const Common::String &name);
+ int getAllNames(Common::StringList &list);
+ Common::SeekableReadStream *openFile(const Common::String &name);
+private:
+ struct Entry {
+ uint32 offset;
+ uint32 size;
+ };
+
+ typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+
+ Resource *_owner;
+ Common::String _filename;
+ FileMap _files;
+};
+
+class CachedArchive : public Common::Archive {
+public:
+ struct InputEntry {
+ Common::String name;
+
+ byte *data;
+ uint32 size;
+ };
+
+ typedef Common::List<InputEntry> FileInputList;
+
+ CachedArchive(const FileInputList &files);
+ ~CachedArchive();
+
+ bool hasFile(const Common::String &name);
+ int getAllNames(Common::StringList &list);
+ Common::SeekableReadStream *openFile(const Common::String &name);
+private:
+ struct Entry {
+ byte *data;
+ uint32 size;
+ };
+
+ typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+ FileMap _files;
+};
+
+
+class ResArchiveLoader {
+public:
+ virtual ~ResArchiveLoader() {}
+ virtual bool checkFilename(Common::String filename) const = 0;
+ virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0;
+ virtual Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const = 0;
+};
+
+class ResLoaderPak : public ResArchiveLoader {
+public:
+ bool checkFilename(Common::String filename) const;
+ bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
+ Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const;
+};
+
+class ResLoaderInsMalcolm : public ResArchiveLoader {
+public:
+ bool checkFilename(Common::String filename) const;
+ bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
+ Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const;
+};
+
+class ResLoaderTlk : public ResArchiveLoader {
+public:
+ bool checkFilename(Common::String filename) const;
+ bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const;
+ Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const;
+};
+
+class InstallerLoader {
+public:
+ static Common::Archive *load(Resource *owner, const Common::String &filename, const Common::String &extension, const uint8 offset);
+};
+
+} // end of namespace Kyra
+
+#endif
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index 31c5e15fa6..76089fdb2c 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -26,10 +26,11 @@
#include "common/endian.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "graphics/thumbnail.h"
#include "kyra/kyra_v1.h"
-#define CURRENT_SAVE_VERSION 13
+#define CURRENT_SAVE_VERSION 14
#define GF_FLOPPY (1 << 0)
#define GF_TALKIE (1 << 1)
@@ -37,11 +38,12 @@
namespace Kyra {
-KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header) {
+KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
uint32 type = in->readUint32BE();
header.originalSave = false;
header.oldHeader = false;
header.flags = 0;
+ header.thumbnail = 0;
if (type == MKID_BE('KYRA') || type == MKID_BE('ARYK')) { // old Kyra1 header ID
header.gameID = GI_KYRA1;
@@ -108,6 +110,19 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
if (header.version >= 2)
header.flags = in->readUint32BE();
+ if (header.version >= 14) {
+ if (loadThumbnail) {
+ header.thumbnail = new Graphics::Surface();
+ assert(header.thumbnail);
+ if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
+ delete header.thumbnail;
+ header.thumbnail = 0;
+ }
+ } else {
+ Graphics::skipThumbnailHeader(*in);
+ }
+ }
+
return (in->ioFailed() ? kRSHEIoError : kRSHENoError);
}
@@ -118,7 +133,7 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena
if (!(in = _saveFileMan->openForLoading(filename)))
return 0;
- kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, header);
+ kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header);
if (errorCode != kRSHENoError) {
if (errorCode == kRSHEInvalidType)
warning("No ScummVM Kyra engine savefile header.");
@@ -162,9 +177,9 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena
return in;
}
-Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName) const {
- debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s')", filename, saveName);
- if (_quitFlag)
+Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s', %p)", filename, saveName, (const void *)thumbnail);
+ if (quit())
return 0;
Common::WriteStream *out = 0;
@@ -191,20 +206,27 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con
return 0;
}
+ if (thumbnail)
+ Graphics::saveThumbnail(*out, *thumbnail);
+ else
+ Graphics::saveThumbnail(*out);
+
return out;
}
const char *KyraEngine_v1::getSavegameFilename(int num) {
static Common::String filename;
+ filename = getSavegameFilename(_targetName, num);
+ return filename.c_str();
+}
+Common::String KyraEngine_v1::getSavegameFilename(const Common::String &target, int num) {
assert(num >= 0 && num <= 999);
char extension[5];
- sprintf(extension, "%.3d", num);
+ sprintf(extension, "%03d", num);
- filename = _targetName + "." + extension;
-
- return filename.c_str();
+ return target + "." + extension;
}
bool KyraEngine_v1::saveFileLoadable(int slot) {
@@ -222,5 +244,12 @@ bool KyraEngine_v1::saveFileLoadable(int slot) {
return false;
}
+void KyraEngine_v1::checkAutosave() {
+ if (shouldPerformAutoSave(_lastAutosave)) {
+ saveGame(getSavegameFilename(999), "Autosave", 0);
+ _lastAutosave = _system->getMillis();
+ }
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp
index 954cbccfa9..be7a74e1c3 100644
--- a/engines/kyra/saveload_hof.cpp
+++ b/engines/kyra/saveload_hof.cpp
@@ -35,10 +35,10 @@
namespace Kyra {
-void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName) {
- debugC(9, kDebugLevelMain, "KyraEngine_HoF::saveGame('%s', '%s')", fileName, saveName);
+void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) {
+ debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb);
- Common::OutSaveFile *out = openSaveForWriting(fileName, saveName);
+ Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
if (!out) {
warning("Can't open file '%s', game not loadable", fileName);
return;
@@ -118,7 +118,7 @@ void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName) {
out->finalize();
// check for errors
- if (out->ioFailed())
+ if (out->err())
warning("Can't write file '%s'. (Disk full?)", fileName);
else
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
@@ -279,7 +279,7 @@ void KyraEngine_HoF::loadGame(const char *fileName) {
_sceneExit3 = in.readUint16();
_sceneExit4 = in.readUint16();
- if (saveFile->ioFailed())
+ if (saveFile->err() || saveFile->eos())
error("Load failed ('%s', '%s').", fileName, header.description.c_str());
else
debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp
index 8af73acc61..f0d9f1ba82 100644
--- a/engines/kyra/saveload_lok.cpp
+++ b/engines/kyra/saveload_lok.cpp
@@ -206,7 +206,7 @@ void KyraEngine_LoK::loadGame(const char *fileName) {
_mousePressFlag = false;
setMousePos(brandonX, brandonY);
- if (in->ioFailed())
+ if (in->err() || in->eos())
error("Load failed ('%s', '%s').", fileName, header.description.c_str());
else
debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
@@ -218,13 +218,13 @@ void KyraEngine_LoK::loadGame(const char *fileName) {
delete in;
}
-void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) {
- debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s')", fileName, saveName);
+void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) {
+ debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb);
- if (_quitFlag)
+ if (quit())
return;
- Common::OutSaveFile *out = openSaveForWriting(fileName, saveName);
+ Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
if (!out)
return;
@@ -289,7 +289,7 @@ void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) {
out->finalize();
// check for errors
- if (out->ioFailed())
+ if (out->err())
warning("Can't write file '%s'. (Disk full?)", fileName);
else
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp
index 51efc33723..0db82863ab 100644
--- a/engines/kyra/saveload_mr.cpp
+++ b/engines/kyra/saveload_mr.cpp
@@ -32,10 +32,10 @@
namespace Kyra {
-void KyraEngine_MR::saveGame(const char *fileName, const char *saveName) {
- debugC(9, kDebugLevelMain, "KyraEngine_MR::saveGame('%s', '%s')", fileName, saveName);
+void KyraEngine_MR::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) {
+ debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb);
- Common::OutSaveFile *out = openSaveForWriting(fileName, saveName);
+ Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
if (!out) {
warning("Can't open file '%s', game not loadable", fileName);
return;
@@ -112,7 +112,7 @@ void KyraEngine_MR::saveGame(const char *fileName, const char *saveName) {
out->finalize();
// check for errors
- if (out->ioFailed())
+ if (out->err())
warning("Can't write file '%s'. (Disk full?)", fileName);
else
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
@@ -283,7 +283,7 @@ void KyraEngine_MR::loadGame(const char *fileName) {
_sceneExit3 = in.readUint16();
_sceneExit4 = in.readUint16();
- if (saveFile->ioFailed())
+ if (saveFile->err() || saveFile->eos())
error("Load failed ('%s', '%s').", fileName, header.description.c_str());
else
debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp
index 62df683ea2..df9fccaab9 100644
--- a/engines/kyra/scene_hof.cpp
+++ b/engines/kyra/scene_hof.cpp
@@ -277,7 +277,7 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) {
int changedScene = 0;
const int *moveTableStart = moveTable;
_unk4 = 0;
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (*moveTable >= 0 && *moveTable <= 7) {
_mainCharacter.facing = getOppositeFacingDirection(*moveTable);
unkFlag = true;
@@ -517,7 +517,7 @@ void KyraEngine_HoF::runSceneScript7() {
void KyraEngine_HoF::initSceneAnims(int unk1) {
debugC(9, kDebugLevelMain, "KyraEngine_HoF::initSceneAnims(%d)", unk1);
- for (int i = 0; i < ARRAYSIZE(_animObjects); ++i)
+ for (int i = 0; i < 41; ++i)
_animObjects[i].enabled = 0;
bool animInit = false;
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index 53c0cb5380..ad4ce63b6c 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -654,7 +654,7 @@ int KyraEngine_MR::trySceneChange(int *moveTable, int unk1, int updateChar) {
const int *moveTableStart = moveTable;
_unk4 = 0;
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (*moveTable >= 0 && *moveTable <= 7) {
_mainCharacter.facing = getOppositeFacingDirection(*moveTable);
unkFlag = true;
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 0cde066cc0..4bcde9a679 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -188,19 +188,19 @@ void Screen::setResolution() {
if (_vm->gameFlags().useHiResOverlay) {
_system->beginGFXTransaction();
- _vm->initCommonGFX(true);
if (_debugEnabled)
_system->initSize(960, 400);
else
_system->initSize(640, 400);
+ _vm->initCommonGFX(true);
_system->endGFXTransaction();
} else {
_system->beginGFXTransaction();
- _vm->initCommonGFX(false);
if (_debugEnabled)
_system->initSize(640, 200);
else
_system->initSize(320, 200);
+ _vm->initCommonGFX(false);
_system->endGFXTransaction();
}
@@ -476,6 +476,25 @@ void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) {
setScreenPalette(_currentPalette);
}
+void Screen::getRealPalette(int num, uint8 *dst) {
+ debugC(9, kDebugLevelScreen, "Screen::getRealPalette(%d, %p)", num, (const void *)dst);
+ const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256);
+ const uint8 *palData = getPalette(num);
+
+ if (!palData) {
+ memset(dst, 0, colors * 3);
+ return;
+ }
+
+ for (int i = 0; i < colors; ++i) {
+ dst[0] = (palData[0] << 2) | (palData[0] & 3);
+ dst[1] = (palData[1] << 2) | (palData[1] & 3);
+ dst[2] = (palData[2] << 2) | (palData[2] & 3);
+ dst += 3;
+ palData += 3;
+ }
+}
+
void Screen::setScreenPalette(const uint8 *palData) {
debugC(9, kDebugLevelScreen, "Screen::setScreenPalette(%p)", (const void *)palData);
@@ -554,19 +573,16 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
copyOverlayRegion(x1, y1, x2, y2, w, h, srcPage, dstPage);
- if (flags & CR_X_FLIPPED) {
+ if (flags & CR_NO_P_CHECK) {
while (h--) {
- for (int i = 0; i < w; ++i) {
- if (src[i] || (flags & CR_NO_P_CHECK))
- dst[w-i] = src[i];
- }
+ memcpy(dst, src, w);
src += SCREEN_W;
dst += SCREEN_W;
}
} else {
while (h--) {
for (int i = 0; i < w; ++i) {
- if (src[i] || (flags & CR_NO_P_CHECK))
+ if (src[i])
dst[i] = src[i];
}
src += SCREEN_W;
@@ -2739,21 +2755,7 @@ bool Screen::loadPalette(const char *filename, uint8 *palData) {
if (palData && fileSize) {
debugC(9, kDebugLevelScreen,"Loading a palette of size %u from '%s'", fileSize, filename);
- if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
- assert(fileSize % 2 == 0);
- assert(fileSize / 2 <= 256);
- fileSize >>= 1;
- const uint16 *src = (const uint16 *)srcData;
- for (uint i = 0; i < fileSize; ++i) {
- uint16 col = READ_BE_UINT16(src); ++src;
- palData[2] = (col & 0xF) << 2; col >>= 4;
- palData[1] = (col & 0xF) << 2; col >>= 4;
- palData[0] = (col & 0xF) << 2; col >>= 4;
- palData += 3;
- }
- } else {
- memcpy(palData, srcData, fileSize);
- }
+ loadPalette(srcData, palData, fileSize);
}
delete[] srcData;
return true;
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 99ba2d7c5f..58744a9d2a 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -74,8 +74,7 @@ public:
};
enum CopyRegionFlags {
- CR_X_FLIPPED = 0x01,
- CR_NO_P_CHECK = 0x02
+ CR_NO_P_CHECK = 0x01
};
enum DrawShapeFlags {
@@ -153,6 +152,8 @@ public:
void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue);
void setScreenPalette(const uint8 *palData);
const uint8 *getScreenPalette() const { return _screenPalette; }
+
+ void getRealPalette(int num, uint8 *dst);
uint8 *getPalette(int num);
// gui specific (processing on _curPage)
diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp
index 011c90dde9..da88abc61f 100644
--- a/engines/kyra/screen_lok.cpp
+++ b/engines/kyra/screen_lok.cpp
@@ -147,8 +147,14 @@ void Screen_LoK::savePageToDisk(const char *file, int page) {
void Screen_LoK::loadPageFromDisk(const char *file, int page) {
debugC(9, kDebugLevelScreen, "Screen_LoK::loadPageFromDisk('%s', %d)", file, page);
+ if (!_saveLoadPage[page/2]) {
+ warning("trying to restore page %d, but no backup found", page);
+ return;
+ }
+
copyBlockToPage(page, 0, 0, SCREEN_W, SCREEN_H, _saveLoadPage[page/2]);
delete[] _saveLoadPage[page/2];
+ _saveLoadPage[page/2] = 0;
if (_saveLoadPageOvl[page/2]) {
uint8 *dstPage = getOverlayPtr(page);
@@ -160,7 +166,17 @@ void Screen_LoK::loadPageFromDisk(const char *file, int page) {
memcpy(dstPage, _saveLoadPageOvl[page/2], SCREEN_OVL_SJIS_SIZE);
delete[] _saveLoadPageOvl[page/2];
_saveLoadPageOvl[page/2] = 0;
- } _saveLoadPage[page/2] = 0;
+ }
+}
+
+void Screen_LoK::queryPageFromDisk(const char *file, int page, uint8 *buffer) {
+ debugC(9, kDebugLevelScreen, "Screen_LoK::queryPageFromDisk('%s', %d, %p)", file, page, (const void *)buffer);
+ if (!_saveLoadPage[page/2]) {
+ warning("trying to query page %d, but no backup found", page);
+ return;
+ }
+
+ memcpy(buffer, _saveLoadPage[page/2], SCREEN_W*SCREEN_H);
}
void Screen_LoK::deletePageFromDisk(int page) {
diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h
index 74df23a543..5b4b8a9266 100644
--- a/engines/kyra/screen_lok.h
+++ b/engines/kyra/screen_lok.h
@@ -50,6 +50,7 @@ public:
void savePageToDisk(const char *file, int page);
void loadPageFromDisk(const char *file, int page);
+ void queryPageFromDisk(const char *file, int page, uint8 *buffer);
void deletePageFromDisk(int page);
void copyBackgroundBlock(int x, int page, int flag);
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index b10a4b32bf..dba09f08ef 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -255,13 +255,13 @@ uint32 ScriptFileParser::getIFFBlockSize(const uint32 chunkName) {
_stream->seek(_startOffset + 0x0C);
- while (_stream->pos() < _endOffset) {
+ while ((uint)_stream->pos() < _endOffset) {
uint32 chunk = _stream->readUint32LE();
uint32 size_temp = _stream->readUint32BE();
if (chunk != chunkName) {
_stream->seek((size_temp + 1) & (~1), SEEK_CUR);
- assert(_stream->pos() <= _endOffset);
+ assert((uint)_stream->pos() <= _endOffset);
} else {
size = size_temp;
break;
@@ -274,13 +274,13 @@ uint32 ScriptFileParser::getIFFBlockSize(const uint32 chunkName) {
bool ScriptFileParser::loadIFFBlock(const uint32 chunkName, void *loadTo, uint32 ptrSize) {
_stream->seek(_startOffset + 0x0C);
- while (_stream->pos() < _endOffset) {
+ while ((uint)_stream->pos() < _endOffset) {
uint32 chunk = _stream->readUint32LE();
uint32 chunkSize = _stream->readUint32BE();
if (chunk != chunkName) {
_stream->seek((chunkSize + 1) & (~1), SEEK_CUR);
- assert(_stream->pos() <= _endOffset);
+ assert((uint)_stream->pos() <= _endOffset);
} else {
uint32 loadSize = 0;
@@ -435,59 +435,35 @@ void EMCInterpreter::cmd_eval(EMCState* script) {
switch (_parameter) {
case 0:
- if (!val2 || !val1)
- ret = 0;
- else
- ret = 1;
+ ret = (val2 && val1) ? 1 : 0;
break;
case 1:
- if (val2 || val1)
- ret = 1;
- else
- ret = 0;
+ ret = (val2 || val1) ? 1 : 0;
break;
case 2:
- if (val1 == val2)
- ret = 1;
- else
- ret = 0;
+ ret = (val1 == val2) ? 1 : 0;
break;
case 3:
- if (val1 != val2)
- ret = 1;
- else
- ret = 0;
+ ret = (val1 != val2) ? 1 : 0;
break;
case 4:
- if (val1 > val2)
- ret = 1;
- else
- ret = 0;
+ ret = (val1 > val2) ? 1 : 0;
break;
case 5:
- if (val1 >= val2)
- ret = 1;
- else
- ret = 0;
+ ret = (val1 >= val2) ? 1 : 0;
break;
case 6:
- if (val1 < val2)
- ret = 1;
- else
- ret = 0;
+ ret = (val1 < val2) ? 1 : 0;
break;
case 7:
- if (val1 <= val2)
- ret = 1;
- else
- ret = 0;
+ ret = (val1 <= val2) ? 1 : 0;
break;
case 8:
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 2b97a83289..6e08017974 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -47,7 +47,7 @@ struct EMCData {
};
struct EMCState {
- uint16 *ip;
+ const uint16 *ip;
const EMCData *dataPtr;
int16 retValue;
uint16 bp;
diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp
index efa0f8e48f..e965a075bd 100644
--- a/engines/kyra/script_lok.cpp
+++ b/engines/kyra/script_lok.cpp
@@ -1747,7 +1747,8 @@ int KyraEngine_LoK::o1_pauseMusicSeconds(EMCState *script) {
}
int KyraEngine_LoK::o1_resetMaskRegion(EMCState *script) {
- warning("STUB: o1_resetMaskRegion");
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_resetMaskRegion(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ _screen->fillRect(stackPos(1), stackPos(2), stackPos(1)+stackPos(3), stackPos(2)+stackPos(4), 0, 5);
return 0;
}
diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp
index 9a059ead2a..bc71e72ce4 100644
--- a/engines/kyra/script_mr.cpp
+++ b/engines/kyra/script_mr.cpp
@@ -293,7 +293,7 @@ int KyraEngine_MR::o3_updateScore(EMCState *script) {
int KyraEngine_MR::o3_makeSecondChanceSave(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_makeSecondChanceSave(%p) ()", (const void *)script);
- saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME");
+ saveGame(getSavegameFilename(999), "Autosave", 0);
return 0;
}
@@ -786,7 +786,7 @@ int KyraEngine_MR::o3_daggerWarning(EMCState *script) {
_screen->_curPage = curPageBackUp;
_screen->showMouse();
- while (!_quitFlag) {
+ while (!quit()) {
int keys = checkInput(0);
removeInputTop();
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 635db3629c..7915a33996 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -75,7 +75,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
_seqEndTime = 0;
_menuChoice = 0;
- for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) {
+ for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) {
_screen->clearPage(0);
_screen->clearPage(8);
memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300);
@@ -131,7 +131,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
seq_sequenceCommand(cseq.startupCommand);
- if (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ if (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
_screen->copyPage(2, 0);
_screen->updateScreen();
}
@@ -165,7 +165,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
_seqWsaCurrentFrame = cseq.startFrame;
bool loop = true;
- while (loop && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ while (loop && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
_seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength;
if (_seqWsa || !cb)
@@ -189,16 +189,16 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
seq_processWSAs();
seq_processText();
- if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
_screen->copyPage(2, 0);
_screen->updateScreen();
}
bool loop2 = true;
- while (loop2 && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ while (loop2 && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
if (_seqWsa) {
seq_processText();
- if (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ if (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
_screen->copyPage(2, 0);
_screen->updateScreen();
}
@@ -230,7 +230,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
} else {
_seqFrameDelay = cseq.frameDelay;
_seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength;
- while (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ while (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
_seqSubFrameStartTime = _system->getMillis();
seq_processWSAs();
if (cb)
@@ -262,7 +262,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) {
dl = ct;
_seqEndTime = _system->getMillis() + dl;
- while (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+ while (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) {
_seqSubFrameStartTime = _system->getMillis();
seq_processWSAs();
@@ -2267,7 +2267,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) {
void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) {
int xa = 0, ya = 0;
command--;
- if (!_activeWSA[wsaNum].movie || skipFlag() || _quitFlag || _abortIntroFlag)
+ if (!_activeWSA[wsaNum].movie || skipFlag() || quit() || _abortIntroFlag)
return;
switch (command) {
@@ -2467,7 +2467,7 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) {
void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) {
uint8 colormap[16];
- if (skipFlag() || _quitFlag || _abortIntroFlag || _menuChoice)
+ if (skipFlag() || quit() || _abortIntroFlag || _menuChoice)
return;
memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6);
@@ -2830,6 +2830,9 @@ void KyraEngine_HoF::seq_init() {
_res->unloadAllPakFiles();
_res->loadPakFile(StaticResource::staticDataFilename());
_res->loadFileList(_sequencePakList, _sequencePakListSize);
+
+ if (_flags.platform == Common::kPlatformPC98)
+ _sound->loadSoundFile("sound.dat");
int numShp = -1;
@@ -2954,7 +2957,7 @@ void KyraEngine_HoF::seq_makeBookAppear() {
++_invWsa.curFrame;
- if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag)
+ if (_invWsa.curFrame >= _invWsa.lastFrame && !quit())
break;
switch (_invWsa.curFrame) {
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 3a497a258f..77cfbed2d0 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -34,7 +34,6 @@
#include "kyra/text.h"
#include "kyra/timer.h"
-#include "common/events.h"
#include "common/system.h"
#include "common/savefile.h"
@@ -164,7 +163,7 @@ void KyraEngine_LoK::seq_introLogos() {
_screen->updateScreen();
_screen->fadeFromBlack();
- if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || _quitFlag) {
+ if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || quit()) {
_screen->fadeToBlack();
_screen->clearPage(0);
return;
@@ -176,14 +175,14 @@ void KyraEngine_LoK::seq_introLogos() {
_screen->setScreenPalette(_screen->_currentPalette);
}
- if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _quitFlag) {
+ if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || quit()) {
_screen->fadeToBlack();
_screen->clearPage(0);
return;
}
_screen->fillRect(0, 179, 319, 199, 0);
- if (_quitFlag)
+ if (quit())
return;
if (_flags.platform == Common::kPlatformAmiga) {
@@ -223,10 +222,10 @@ void KyraEngine_LoK::seq_introLogos() {
oldDistance = distance;
delay(10);
- } while (!doneFlag && !_quitFlag && !_abortIntroFlag);
+ } while (!doneFlag && !quit() && !_abortIntroFlag);
}
- if (_quitFlag)
+ if (quit())
return;
_seq->playSequence(_seq_Forest, true);
@@ -1030,7 +1029,7 @@ void KyraEngine_LoK::seq_brandonToStone() {
void KyraEngine_LoK::seq_playEnding() {
debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playEnding()");
- if (_quitFlag)
+ if (quit())
return;
_screen->hideMouse();
_screen->_curPage = 0;
@@ -1186,8 +1185,8 @@ void KyraEngine_LoK::seq_playCredits() {
case Common::EVENT_KEYDOWN:
finished = true;
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- quitGame();
finished = true;
break;
default:
@@ -1211,7 +1210,7 @@ void KyraEngine_LoK::seq_playCredits() {
bool KyraEngine_LoK::seq_skipSequence() const {
debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_skipSequence()");
- return _quitFlag || _abortIntroFlag;
+ return quit() || _abortIntroFlag;
}
int KyraEngine_LoK::handleMalcolmFlag() {
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index e5294eb15d..2f7ac27ac5 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -429,7 +429,7 @@ public:
MidiChannel *allocateChannel() { return 0; }
MidiChannel *getPercussionChannel() { return 0; }
- static float semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey,
+ static float calculatePhaseStep(int8 semiTone, int8 semiToneRootkey,
uint32 sampleRate, uint32 outputRate, int32 pitchWheel);
private:
@@ -492,7 +492,7 @@ public:
void process();
void loadSoundFile(uint file) {}
- void loadSoundFile(Common::String) {}
+ void loadSoundFile(Common::String file);
void playTrack(uint8 track);
void haltTrack();
@@ -507,6 +507,7 @@ protected:
bool _useFmSfx;
uint8 *_musicTrackData;
+ uint8 *_sfxTrackData;
TownsPC98_OpnDriver *_driver;
};
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index ec1962a58f..5bb09e5dc9 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/system.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
@@ -64,13 +63,13 @@ public:
MidiDriver *device() { return 0; }
byte getNumber() { return 0; }
void release() { }
- void send(uint32 b) { }
+ void send(uint32) { }
void noteOff(byte note);
void noteOn(byte note, byte onVelo);
- void programChange(byte program) {}
+ void programChange(byte) {}
void pitchBend(int16 value);
void controlChange(byte control, byte value);
- void pitchBendFactor(byte value) { }
+ void pitchBendFactor(byte) { }
void sysEx_customInstrument(uint32 unused, const byte *instr);
protected:
@@ -427,7 +426,7 @@ void Towns_EuphonyPcmChannel::nextTick(int32 *outbuf, int buflen) {
return;
}
- float phaseStep = SoundTowns::semitoneAndSampleRate_to_sampleStep(_note, _voice->_snd[_current]->keyNote -
+ float phaseStep = SoundTowns::calculatePhaseStep(_note, _voice->_snd[_current]->keyNote -
_voice->_env[_current]->rootKeyOffset, _voice->_snd[_current]->samplingRate, _rate, _frequencyOffs);
int32 looplength = _voice->_snd[_current]->loopLength;
@@ -819,7 +818,8 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
}
}
- while (true) {
+ bool loop = true;
+ while (loop) {
byte cmd = *pos;
byte evt = (cmd & 0xF0);
@@ -853,7 +853,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
info.basic.param2 = onVelo;
pos += 12;
- break;
+ loop = false;
} else {
pos += 6;
}
@@ -870,7 +870,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
info.basic.param1 = pos[4];
info.basic.param2 = pos[5];
pos += 6;
- break;
+ loop = false;
} else {
pos += 6;
}
@@ -889,7 +889,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
_tempo[2] = tempo & 0xff;
info.ext.data = (byte*) _tempo;
pos += 6;
- break;
+ loop = false;
} else if (cmd == 0xFD || cmd == 0xFE) {
// End of track.
if (_autoLoop) {
@@ -906,12 +906,12 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
info.event = 0xFF;
info.ext.type = 0x2F;
info.ext.data = pos;
- break;
+ loop = false;
} else {
error("Unknown Euphony music event 0x%02X", (int)cmd);
memset(&info, 0, sizeof(info));
pos = 0;
- break;
+ loop = false;
}
}
_position._play_pos = pos;
@@ -1085,7 +1085,7 @@ void Towns_EuphonyTrackQueue::initDriver() {
class TownsPC98_OpnOperator {
public:
- TownsPC98_OpnOperator(double rate, const uint8 *rateTable,
+ TownsPC98_OpnOperator(const uint32 timerbase, const uint8 *rateTable,
const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable,
const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable);
~TownsPC98_OpnOperator() {}
@@ -1095,7 +1095,7 @@ public:
void frequency(int freq);
void updatePhaseIncrement();
void recalculateRates();
- void generateOutput(int phasebuf, int *_feedbuf, int &out);
+ void generateOutput(int32 phasebuf, int32 *feedbuf, int32 &out);
void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; }
void detune(int value) { _detn = &_detnTbl[value << 5]; }
@@ -1111,6 +1111,7 @@ public:
protected:
EnvelopeState _state;
+ bool _playing;
uint32 _feedbackLevel;
uint32 _multiple;
uint32 _totalLevel;
@@ -1137,8 +1138,8 @@ protected:
const int32 *_tLvlTbl;
const int32 *_detnTbl;
- const double _tickLength;
- double _tick;
+ const uint32 _tickLength;
+ uint32 _timer;
int32 _currentLevel;
struct EvpState {
@@ -1147,23 +1148,31 @@ protected:
} fs_a, fs_d, fs_s, fs_r;
};
-TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, const uint8 *rateTable,
+TownsPC98_OpnOperator::TownsPC98_OpnOperator(const uint32 timerbase, const uint8 *rateTable,
const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable,
const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) :
_rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable),
- _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(rate * 65536.0),
+ _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2),
_specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
_phase(0), _state(s_ready) {
-
+
reset();
}
void TownsPC98_OpnOperator::keyOn() {
+ if (_playing)
+ return;
+
+ _playing = true;
_state = s_attacking;
_phase = 0;
}
void TownsPC98_OpnOperator::keyOff() {
+ if (!_playing)
+ return;
+
+ _playing = false;
if (_state != s_ready)
_state = s_releasing;
}
@@ -1172,6 +1181,7 @@ void TownsPC98_OpnOperator::frequency(int freq) {
uint8 block = (freq >> 11);
uint16 pos = (freq & 0x7ff);
uint8 c = pos >> 7;
+
_kcode = (block << 2) | ((c < 7) ? 0 : ((c > 8) ? 3 : c - 6 ));
_frequency = _fTbl[pos << 1] >> (7 - block);
}
@@ -1204,44 +1214,44 @@ void TownsPC98_OpnOperator::recalculateRates() {
fs_r.shift = _rshiftTbl[r + k];
}
-void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out) {
+void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &out) {
if (_state == s_ready)
return;
- _tick += _tickLength;
- while (_tick > 0x30000) {
- _tick -= 0x30000;
+ _timer += _tickLength;
+ while (_timer > 0x5B8D80) {
+ _timer -= 0x5B8D80;
++_tickCount;
int32 levelIncrement = 0;
uint32 targetTime = 0;
int32 targetLevel = 0;
- EnvelopeState next_state = s_ready;
+ EnvelopeState nextState = s_ready;
switch (_state) {
case s_ready:
return;
case s_attacking:
- next_state = s_decaying;
+ nextState = s_decaying;
targetTime = (1 << fs_a.shift) - 1;
targetLevel = 0;
levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
break;
case s_decaying:
targetTime = (1 << fs_d.shift) - 1;
- next_state = s_sustaining;
+ nextState = s_sustaining;
targetLevel = _sustainLevel;
levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)];
break;
case s_sustaining:
targetTime = (1 << fs_s.shift) - 1;
- next_state = s_ready;
+ nextState = s_sustaining;
targetLevel = 1023;
levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)];
break;
case s_releasing:
targetTime = (1 << fs_r.shift) - 1;
- next_state = s_ready;
+ nextState = s_ready;
targetLevel = 1023;
levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
break;
@@ -1249,31 +1259,29 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out
if (!(_tickCount & targetTime)) {
_currentLevel += levelIncrement;
- if ((!targetLevel && _currentLevel <= targetLevel) || (targetLevel && _currentLevel >= targetLevel)) {
+ if ((_state == s_attacking && _currentLevel <= targetLevel) || (_state != s_attacking && _currentLevel >= targetLevel)) {
if (_state != s_decaying)
_currentLevel = targetLevel;
- if (_state != s_sustaining)
- _state = next_state;
+ _state = nextState;
}
}
}
uint32 lvlout = _totalLevel + (uint32) _currentLevel;
- int outp = 0;
- int *i = &outp, *o = &outp;
+
+ int32 outp = 0;
+ int32 *i = &outp, *o = &outp;
int phaseShift = 0;
- if (_feedbuf) {
- o = &_feedbuf[0];
- i = &_feedbuf[1];
- phaseShift = _feedbackLevel ? ((_feedbuf[0] + _feedbuf[1]) << _feedbackLevel) : 0;
- if (phasebuf == -1)
- *i = 0;
+ if (feed) {
+ o = &feed[0];
+ i = &feed[1];
+ phaseShift = _feedbackLevel ? ((*o + *i) << _feedbackLevel) : 0;
*o = *i;
} else {
phaseShift = phasebuf << 15;
- }
+ }
if (lvlout < 832) {
uint32 index = (lvlout << 3) + _sinTbl[(((int32)((_phase & 0xffff0000)
@@ -1285,15 +1293,11 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out
_phase += _phaseIncrement;
out += *o;
- if (out > 32767)
- out = 32767;
- if (out < -32767)
- out = -32767;
}
void TownsPC98_OpnOperator::reset(){
keyOff();
- _tick = 0;
+ _timer = 0;
_keyScale2 = 0;
_currentLevel = 1023;
@@ -1306,7 +1310,7 @@ void TownsPC98_OpnOperator::reset(){
decayRate(0);
releaseRate(0);
sustainRate(0);
- feedbackLevel(0);
+ feedbackLevel(0);
totalLevel(127);
}
@@ -1332,40 +1336,34 @@ public:
virtual ~TownsPC98_OpnChannel();
virtual void init();
- typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para);
-
typedef enum channelState {
CHS_RECALCFREQ = 0x01,
CHS_KEYOFF = 0x02,
- CHS_SSG = 0x04,
- CHS_PITCHWHEELOFF = 0x08,
- CHS_ALL_BUT_EOT = 0x0f,
+ CHS_SSGOFF = 0x04,
+ CHS_VBROFF = 0x08,
+ CHS_ALLOFF = 0x0f,
+ CHS_PROTECT = 0x40,
CHS_EOT = 0x80
} ChannelState;
virtual void loadData(uint8 *data);
virtual void processEvents();
virtual void processFrequency();
- bool processControlEvent(uint8 cmd);
- void writeReg(uint8 regAdress, uint8 value);
+ virtual bool processControlEvent(uint8 cmd);
virtual void keyOn();
- virtual void keyOff();
-
+ void keyOff();
+
void setOutputLevel();
- void fadeStep();
+ virtual void fadeStep();
void reset();
- void updateEnv();
- void generateOutput(int16 &leftSample, int16 &rightSample, int *del, int *feed);
-
- bool _enableLeft;
- bool _enableRight;
- bool _updateEnvelopes;
- const uint8 _idFlag;
- int _feedbuf[3];
+ const uint8 _idFlag;
protected:
+ void setupVibrato();
+ bool processVibrato();
+
bool control_dummy(uint8 para);
bool control_f0_setPatch(uint8 para);
bool control_f1_presetOutputLevel(uint8 para);
@@ -1374,52 +1372,47 @@ protected:
bool control_f4_setOutputLevel(uint8 para);
bool control_f5_setTempo(uint8 para);
bool control_f6_repeatSection(uint8 para);
- bool control_f7_setupPitchWheel(uint8 para);
- bool control_f8_togglePitchWheel(uint8 para);
+ bool control_f7_setupVibrato(uint8 para);
+ bool control_f8_toggleVibrato(uint8 para);
bool control_fa_writeReg(uint8 para);
- bool control_fb_incOutLevel(uint8 para);
- bool control_fc_decOutLevel(uint8 para);
+ virtual bool control_fb_incOutLevel(uint8 para);
+ virtual bool control_fc_decOutLevel(uint8 para);
bool control_fd_jump(uint8 para);
- bool control_ff_endOfTrack(uint8 para);
-
- bool control_f0_setPatchSSG(uint8 para);
- bool control_f1_setTotalLevel(uint8 para);
- bool control_f4_setAlgorithm(uint8 para);
- bool control_f9_unkSSG(uint8 para);
- bool control_fb_incOutLevelSSG(uint8 para);
- bool control_fc_decOutLevelSSG(uint8 para);
- bool control_ff_endOfTrackSSG(uint8 para);
+ virtual bool control_ff_endOfTrack(uint8 para);
uint8 _ticksLeft;
uint8 _algorithm;
- uint8 _instrID;
+ uint8 _instr;
uint8 _totalLevel;
uint8 _frqBlockMSB;
int8 _frqLSB;
uint8 _keyOffTime;
- bool _protect;
+ bool _hold;
uint8 *_dataPtr;
- uint8 _ptchWhlInitDelayLo;
- uint8 _ptchWhlInitDelayHi;
- int16 _ptchWhlModInitVal;
- uint8 _ptchWhlDuration;
- uint8 _ptchWhlCurDelay;
- int16 _ptchWhlModCurVal;
- uint8 _ptchWhlDurLeft;
- uint16 frequency;
+ uint8 _vbrInitDelayHi;
+ uint8 _vbrInitDelayLo;
+ int16 _vbrModInitVal;
+ uint8 _vbrDuration;
+ uint8 _vbrCurDelay;
+ int16 _vbrModCurVal;
+ uint8 _vbrDurLeft;
+ uint16 _frequency;
+ uint8 _block;
uint8 _regOffset;
uint8 _flags;
- uint8 _ssg1;
- uint8 _ssg2;
+ uint8 _ssgTl;
+ uint8 _ssgStep;
+ uint8 _ssgTicksLeft;
+ uint8 _ssgTargetLvl;
+ uint8 _ssgStartLvl;
const uint8 _chanNum;
const uint8 _keyNum;
const uint8 _part;
TownsPC98_OpnDriver *_drv;
- TownsPC98_OpnOperator **_opr;
- uint16 _frqTemp;
+ typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para);
const ControlEventFunc *controlEvents;
};
@@ -1427,24 +1420,169 @@ class TownsPC98_OpnChannelSSG : public TownsPC98_OpnChannel {
public:
TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs,
uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
- ~TownsPC98_OpnChannelSSG() {}
+ virtual ~TownsPC98_OpnChannelSSG() {}
void init();
+ virtual void loadData(uint8 *data);
void processEvents();
void processFrequency();
+ bool processControlEvent(uint8 cmd);
void keyOn();
- void keyOff();
+ void nextShape();
+
+ void protect();
+ void restore();
+
+ void fadeStep();
+
+protected:
+ void setOutputLevel(uint8 lvl);
+
+ bool control_f0_setInstr(uint8 para);
+ bool control_f1_setTotalLevel(uint8 para);
+ bool control_f4_setAlgorithm(uint8 para);
+ bool control_f9_loadCustomPatch(uint8 para);
+ bool control_fb_incOutLevel(uint8 para);
+ bool control_fc_decOutLevel(uint8 para);
+ bool control_ff_endOfTrack(uint8 para);
+
+ typedef bool (TownsPC98_OpnChannelSSG::*ControlEventFunc)(uint8 para);
+ const ControlEventFunc *controlEvents;
+};
+
+class TownsPC98_OpnSfxChannel : public TownsPC98_OpnChannelSSG {
+public:
+ TownsPC98_OpnSfxChannel(TownsPC98_OpnDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
+ TownsPC98_OpnChannelSSG(driver, regOffs, flgs, num, key, prt, id) {}
+ ~TownsPC98_OpnSfxChannel() {}
+
+ void loadData(uint8 *data);
+};
+
+class TownsPC98_OpnChannelPCM : public TownsPC98_OpnChannel {
+public:
+ TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
+ ~TownsPC98_OpnChannelPCM() {}
+ void init();
+
void loadData(uint8 *data);
+ void processEvents();
+ bool processControlEvent(uint8 cmd);
private:
- void opn_SSG_UNK(uint8 a);
+ bool control_f1_prcStart(uint8 para);
+ bool control_ff_endOfTrack(uint8 para);
+
+ typedef bool (TownsPC98_OpnChannelPCM::*ControlEventFunc)(uint8 para);
+ const ControlEventFunc *controlEvents;
};
+class TownsPC98_OpnSquareSineSource {
+public:
+ TownsPC98_OpnSquareSineSource(const uint32 timerbase);
+ ~TownsPC98_OpnSquareSineSource();
-class TownsPC98_OpnDriver : public Audio::AudioStream {
-friend class TownsPC98_OpnChannel;
-friend class TownsPC98_OpnChannelSSG;
+ void init(const int *rsTable, const int *rseTable);
+ void reset();
+ void writeReg(uint8 address, uint8 value, bool force = false);
+
+ void nextTick(int32 *buffer, uint32 bufferSize);
+
+ uint8 chanEnable() { return _chanEnable; }
+private:
+ void updatesRegs();
+
+ uint8 _updateRequestBuf[32];
+ int _updateRequest;
+ int _rand;
+
+ int8 _evpTimer;
+ uint32 _pReslt;
+ uint8 _attack;
+
+ bool _evpUpdate, _cont;
+
+ int _evpUpdateCnt;
+ uint8 _outN;
+ int _nTick;
+
+ int32 *_tlTable;
+ int32 *_tleTable;
+
+ const uint32 _tickLength;
+ uint32 _timer;
+
+ struct Channel {
+ int tick;
+ uint8 smp;
+ uint8 out;
+
+ uint8 frqL;
+ uint8 frqH;
+ uint8 vol;
+ } _channels[3];
+
+ uint8 _noiseGenerator;
+ uint8 _chanEnable;
+
+ uint8 *const *_reg;
+
+ bool _ready;
+};
+
+class TownsPC98_OpnPercussionSource {
+public:
+ TownsPC98_OpnPercussionSource(const uint32 timerbase);
+ ~TownsPC98_OpnPercussionSource() {}
+
+ void init(const uint8 *instrData = 0);
+ void reset();
+ void writeReg(uint8 address, uint8 value);
+
+ void nextTick(int32 *buffer, uint32 bufferSize);
+
+private:
+ struct RhtChannel {
+ const uint8 *data;
+
+ const uint8 *start;
+ const uint8 *end;
+ const uint8 *pos;
+ uint32 size;
+ bool active;
+ uint8 level;
+
+ int8 decState;
+ uint8 decStep;
+
+ int16 samples[2];
+ int out;
+
+ uint8 startPosH;
+ uint8 startPosL;
+ uint8 endPosH;
+ uint8 endPosL;
+ };
+
+ void recalcOuput(RhtChannel *ins);
+ void advanceInput(RhtChannel *ins);
+
+ RhtChannel _rhChan[6];
+
+ uint8 _totalLevel;
+
+ const uint32 _tickLength;
+ uint32 _timer;
+
+ uint8 *const *_reg;
+
+ bool _ready;
+};
+
+class TownsPC98_OpnCore : public Audio::AudioStream {
public:
enum OpnType {
OD_TOWNS,
@@ -1452,21 +1590,13 @@ public:
OD_TYPE86
};
- TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type);
- ~TownsPC98_OpnDriver();
-
- bool init();
- void loadData(uint8 *data, bool loadPaused = false);
- void reset();
- void fadeOut();
-
- void pause() { _playing = false; }
- void cont() { _playing = true; }
+ TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type);
+ virtual ~TownsPC98_OpnCore();
- void callback();
- void nextTick(int16 *buffer, uint32 bufferSize);
+ virtual bool init();
+ virtual void reset();
- bool looping() { return _looping == _updateChannelsFlag ? true : false; }
+ void writeReg(uint8 part, uint8 regAddress, uint8 value);
// AudioStream interface
int inline readBuffer(int16 *buffer, const int numSamples);
@@ -1477,24 +1607,34 @@ public:
protected:
void generateTables();
- TownsPC98_OpnChannel **_channels;
- TownsPC98_OpnChannelSSG **_ssgChannels;
- //TownsPC98_OpnChannel *_adpcmChannel;
-
- void setTempo(uint8 tempo);
+ void toggleRegProtection(bool prot) { _regProtectionFlag = prot; }
+ uint8 readSSGStatus() { return _ssg->chanEnable(); }
- void lock() { _mutex.lock(); }
- void unlock() { _mutex.unlock(); }
+ virtual void timerCallbackA() = 0;
+ virtual void timerCallbackB() = 0;
- Audio::Mixer *_mixer;
- Common::Mutex _mutex;
- Audio::SoundHandle _soundHandle;
+ const int _numChan;
+ const int _numSSG;
+ const bool _hasPercussion;
- const uint8 *_opnCarrier;
- const uint8 *_opnFreqTable;
- const uint8 *_opnFxCmdLen;
- const uint8 *_opnLvlPresets;
+private:
+ void nextTick(int32 *buffer, uint32 bufferSize);
+ void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed);
+
+ struct ChanInternal {
+ uint16 frqTemp;
+ bool enableLeft;
+ bool enableRight;
+ bool updateEnvelopeParameters;
+ int32 feedbuf[3];
+ uint8 algorithm;
+ TownsPC98_OpnOperator **opr;
+ };
+ TownsPC98_OpnSquareSineSource *_ssg;
+ TownsPC98_OpnPercussionSource *_prc;
+ ChanInternal *_chanInternal;
+
uint8 *_oprRates;
uint8 *_oprRateshift;
uint8 *_oprAttackDecay;
@@ -1503,34 +1643,112 @@ protected:
int32 *_oprLevelOut;
int32 *_oprDetune;
- uint8 *_trackData;
+ bool _regProtectionFlag;
+
+ typedef void (TownsPC98_OpnCore::*OpnTimerProc)();
+
+ struct OpnTimer {
+ bool enabled;
+ uint16 value;
+
+ int32 smpTillCb;
+ uint32 smpTillCbRem;
+ int32 smpPerCb;
+ uint32 smpPerCbRem;
+
+ OpnTimerProc cb;
+ };
+
+ OpnTimer _timers[2];
+
+ const float _baserate;
+ uint32 _timerbase;
+
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _soundHandle;
+
+ static const uint8 _percussionData[];
+ static const uint32 _adtStat[];
+ static const uint8 _detSrc[];
+ static const int _ssgTables[];
+
+ bool _ready;
+};
+
+class TownsPC98_OpnDriver : public TownsPC98_OpnCore {
+friend class TownsPC98_OpnChannel;
+friend class TownsPC98_OpnChannelSSG;
+friend class TownsPC98_OpnSfxChannel;
+friend class TownsPC98_OpnChannelPCM;
+public:
+ TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type);
+ ~TownsPC98_OpnDriver();
+
+ void loadMusicData(uint8 *data, bool loadPaused = false);
+ void loadSoundEffectData(uint8 *data, uint8 trackNum);
+ bool init();
+ void reset();
+
+ void fadeStep();
+
+ void pause() { _musicPlaying = false; }
+ void cont() { _musicPlaying = true; }
+
+ void timerCallbackB();
+ void timerCallbackA();
+
+ bool looping() { return _looping == _updateChannelsFlag ? true : false; }
+ bool musicPlaying() { return _musicPlaying; }
+
+protected:
+ void startSoundEffect();
+
+ void setMusicTempo(uint8 tempo);
+ void setSfxTempo(uint16 tempo);
+
+ void lock() { _mutex.lock(); }
+ void unlock() { _mutex.unlock(); }
+
+ TownsPC98_OpnChannel **_channels;
+ TownsPC98_OpnChannelSSG **_ssgChannels;
+ TownsPC98_OpnSfxChannel **_sfxChannels;
+ TownsPC98_OpnChannelPCM *_rhythmChannel;
+
+ Common::Mutex _mutex;
+
+ const uint8 *_opnCarrier;
+ const uint8 *_opnFreqTable;
+ const uint8 *_opnFreqTableSSG;
+ const uint8 *_opnFxCmdLen;
+ const uint8 *_opnLvlPresets;
+
+ uint8 *_musicBuffer;
+ uint8 *_sfxBuffer;
+ uint8 *_trackPtr;
uint8 *_patches;
+ uint8 *_ssgPatches;
- uint8 _cbCounter;
uint8 _updateChannelsFlag;
+ uint8 _updateSSGFlag;
+ uint8 _updateRhythmFlag;
+ uint8 _updateSfxFlag;
uint8 _finishedChannelsFlag;
- uint16 _tempo;
- bool _playing;
- bool _fading;
- uint8 _looping;
- uint32 _tickCounter;
-
- bool _updateEnvelopes;
- int _ssgFlag;
+ uint8 _finishedSSGFlag;
+ uint8 _finishedRhythmFlag;
+ uint8 _finishedSfxFlag;
- int32 _samplesTillCallback;
- int32 _samplesTillCallbackRemainder;
- int32 _samplesPerCallback;
- int32 _samplesPerCallbackRemainder;
+ bool _musicPlaying;
+ bool _sfxPlaying;
+ uint8 _fading;
+ uint8 _looping;
+ uint32 _musicTickCounter;
- const int _numChan;
- const int _numSSG;
- const bool _hasADPCM;
- const bool _hasStereo;
+ int _sfxOffs;
+ uint8 *_sfxData;
+ uint16 _sfxOffsets[2];
- double _baserate;
static const uint8 _drvTables[];
- static const uint32 _adtStat[];
+
bool _ready;
};
@@ -1538,33 +1756,20 @@ TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 re
uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key),
_part(prt), _idFlag(id) {
- _ticksLeft = _algorithm = _instrID = _totalLevel = _frqBlockMSB = _keyOffTime = _ssg1 = _ssg2 = 0;
- _ptchWhlInitDelayLo = _ptchWhlInitDelayHi = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = 0;
+ _ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0;
+ _ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0;
+ _vbrInitDelayHi = _vbrInitDelayLo = _vbrDuration = _vbrCurDelay = _vbrDurLeft = 0;
_frqLSB = 0;
- _protect = _updateEnvelopes = false;
- _enableLeft = _enableRight = true;
- _dataPtr = 0;
- _ptchWhlModInitVal = _ptchWhlModCurVal = 0;
- frequency = _frqTemp = 0;
- memset(&_feedbuf, 0, sizeof(int) * 3);
- _opr = 0;
+ _hold = false;
+ _dataPtr = 0;
+ _vbrModInitVal = _vbrModCurVal = 0;
+ _frequency = 0;
}
TownsPC98_OpnChannel::~TownsPC98_OpnChannel() {
- if (_opr) {
- for (int i = 0; i < 4; i++)
- delete _opr[i];
- delete [] _opr;
- }
}
void TownsPC98_OpnChannel::init() {
-
- _opr = new TownsPC98_OpnOperator*[4];
- for (int i = 0; i < 4; i++)
- _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift,
- _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune);
-
#define Control(x) &TownsPC98_OpnChannel::control_##x
static const ControlEventFunc ctrlEvents[] = {
Control(f0_setPatch),
@@ -1574,8 +1779,8 @@ void TownsPC98_OpnChannel::init() {
Control(f4_setOutputLevel),
Control(f5_setTempo),
Control(f6_repeatSection),
- Control(f7_setupPitchWheel),
- Control(f8_togglePitchWheel),
+ Control(f7_setupVibrato),
+ Control(f8_toggleVibrato),
Control(dummy),
Control(fa_writeReg),
Control(fb_incOutLevel),
@@ -1592,20 +1797,24 @@ void TownsPC98_OpnChannel::init() {
void TownsPC98_OpnChannel::keyOff() {
// all operators off
uint8 value = _keyNum & 0x0f;
- uint8 regAdress = 0x28;
- writeReg(regAdress, value);
+ if (_part)
+ value |= 4;
+ uint8 regAddress = 0x28;
+ _drv->writeReg(0, regAddress, value);
_flags |= CHS_KEYOFF;
}
void TownsPC98_OpnChannel::keyOn() {
// all operators on
uint8 value = _keyNum | 0xf0;
- uint8 regAdress = 0x28;
- writeReg(regAdress, value);
+ if (_part)
+ value |= 4;
+ uint8 regAddress = 0x28;
+ _drv->writeReg(0, regAddress, value);
}
void TownsPC98_OpnChannel::loadData(uint8 *data) {
- _flags = (_flags & ~CHS_EOT) | CHS_ALL_BUT_EOT;
+ _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
_ticksLeft = 1;
_dataPtr = data;
_totalLevel = 0x7F;
@@ -1645,13 +1854,13 @@ void TownsPC98_OpnChannel::processEvents() {
if (_flags & CHS_EOT)
return;
- if (_protect == false && _ticksLeft == _keyOffTime)
+ if (!_hold && _ticksLeft == _keyOffTime)
keyOff();
if (--_ticksLeft)
return;
- if (_protect == false)
+ if (!_hold)
keyOff();
uint8 cmd = 0;
@@ -1669,14 +1878,14 @@ void TownsPC98_OpnChannel::processEvents() {
if (cmd == 0x80) {
keyOff();
- _protect = false;
+ _hold = false;
} else {
keyOn();
- if (_protect == false || cmd != _frqBlockMSB)
+ if (_hold == false || cmd != _frqBlockMSB)
_flags |= CHS_RECALCFREQ;
-
- _protect = (para & 0x80) ? true : false;
+
+ _hold = (para & 0x80) ? true : false;
_frqBlockMSB = cmd;
}
@@ -1685,37 +1894,47 @@ void TownsPC98_OpnChannel::processEvents() {
void TownsPC98_OpnChannel::processFrequency() {
if (_flags & CHS_RECALCFREQ) {
- uint8 block = (_frqBlockMSB & 0x70) >> 1;
- uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f];
- frequency = (bfreq + _frqLSB) | (block << 8);
-
- writeReg(_regOffset + 0xa4, (frequency >> 8));
- writeReg(_regOffset + 0xa0, (frequency & 0xff));
+
+ _frequency = (((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f] + _frqLSB) | (((_frqBlockMSB & 0x70) >> 1) << 8);
- _ptchWhlCurDelay = _ptchWhlInitDelayHi;
- if (_flags & CHS_KEYOFF) {
- _ptchWhlModCurVal = _ptchWhlModInitVal;
- _ptchWhlCurDelay += _ptchWhlInitDelayLo;
- }
+ _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
+ _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
- _ptchWhlDurLeft = (_ptchWhlDuration >> 1);
- _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ);
+ setupVibrato();
}
- if (!(_flags & CHS_PITCHWHEELOFF)) {
- if (--_ptchWhlCurDelay)
+ if (!(_flags & CHS_VBROFF)) {
+ if (!processVibrato())
return;
- _ptchWhlCurDelay = _ptchWhlInitDelayHi;
- frequency += _ptchWhlModCurVal;
- writeReg(_regOffset + 0xa4, (frequency >> 8));
- writeReg(_regOffset + 0xa0, (frequency & 0xff));
+ _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
+ _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
+ }
+}
- if(!--_ptchWhlDurLeft) {
- _ptchWhlDurLeft = _ptchWhlDuration;
- _ptchWhlModCurVal = -_ptchWhlModCurVal;
- }
+void TownsPC98_OpnChannel::setupVibrato() {
+ _vbrCurDelay = _vbrInitDelayHi;
+ if (_flags & CHS_KEYOFF) {
+ _vbrModCurVal = _vbrModInitVal;
+ _vbrCurDelay += _vbrInitDelayLo;
+ }
+ _vbrDurLeft = (_vbrDuration >> 1);
+ _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ);
+}
+
+bool TownsPC98_OpnChannel::processVibrato() {
+ if (--_vbrCurDelay)
+ return false;
+
+ _vbrCurDelay = _vbrInitDelayHi;
+ _frequency += _vbrModCurVal;
+
+ if(!--_vbrDurLeft) {
+ _vbrDurLeft = _vbrDuration;
+ _vbrModCurVal = -_vbrModCurVal;
}
+
+ return true;
}
bool TownsPC98_OpnChannel::processControlEvent(uint8 cmd) {
@@ -1729,7 +1948,7 @@ void TownsPC98_OpnChannel::setOutputLevel() {
for (int i = 0; i < 4; i++) {
if (outopr & 1)
- writeReg(reg, _totalLevel);
+ _drv->writeReg(_part, reg, _totalLevel);
outopr >>= 1;
reg += 4;
}
@@ -1743,254 +1962,59 @@ void TownsPC98_OpnChannel::fadeStep() {
}
void TownsPC98_OpnChannel::reset() {
- for (int i = 0; i < 4; i++)
- _opr[i]->reset();
-
- _updateEnvelopes = false;
- _enableLeft = _enableRight = true;
- memset(&_feedbuf, 0, sizeof(int) * 3);
-}
-
-void TownsPC98_OpnChannel::updateEnv() {
- for (int i = 0; i < 4 ; i++)
- _opr[i]->updatePhaseIncrement();
-}
+ _hold = false;
+ _keyOffTime = 0;
+ _ticksLeft = 1;
-void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, int *del, int *feed) {
- int phbuf1, phbuf2, output;
- phbuf1 = phbuf2 = output = 0;
+ _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
- switch (_algorithm) {
- case 0:
- _opr[0]->generateOutput(0, feed, phbuf1);
- _opr[2]->generateOutput(*del, 0, phbuf2);
- *del = 0;
- _opr[1]->generateOutput(phbuf1, 0, *del);
- _opr[3]->generateOutput(phbuf2, 0, output);
- break;
- case 1:
- _opr[0]->generateOutput(0, feed, phbuf1);
- _opr[2]->generateOutput(*del, 0, phbuf2);
- _opr[1]->generateOutput(0, 0, phbuf1);
- _opr[3]->generateOutput(phbuf2, 0, output);
- *del = phbuf1;
- break;
- case 2:
- _opr[0]->generateOutput(0, feed, phbuf2);
- _opr[2]->generateOutput(*del, 0, phbuf2);
- _opr[1]->generateOutput(0, 0, phbuf1);
- _opr[3]->generateOutput(phbuf2, 0, output);
- *del = phbuf1;
- break;
- case 3:
- _opr[0]->generateOutput(0, feed, phbuf2);
- _opr[2]->generateOutput(0, 0, *del);
- _opr[1]->generateOutput(phbuf2, 0, phbuf1);
- _opr[3]->generateOutput(*del, 0, output);
- *del = phbuf1;
- break;
- case 4:
- _opr[0]->generateOutput(0, feed, phbuf1);
- _opr[2]->generateOutput(0, 0, phbuf2);
- _opr[1]->generateOutput(phbuf1, 0, output);
- _opr[3]->generateOutput(phbuf2, 0, output);
- *del = 0;
- break;
- case 5:
- *del = feed[1];
- _opr[0]->generateOutput(-1, feed, phbuf1);
- _opr[2]->generateOutput(*del, 0, output);
- _opr[1]->generateOutput(*del, 0, output);
- _opr[3]->generateOutput(*del, 0, output);
- break;
- case 6:
- _opr[0]->generateOutput(0, feed, phbuf1);
- _opr[2]->generateOutput(0, 0, output);
- _opr[1]->generateOutput(phbuf1, 0, output);
- _opr[3]->generateOutput(0, 0, output);
- *del = 0;
- break;
- case 7:
- _opr[0]->generateOutput(0, feed, output);
- _opr[2]->generateOutput(0, 0, output);
- _opr[1]->generateOutput(0, 0, output);
- _opr[3]->generateOutput(0, 0, output);
- *del = 0;
- break;
- };
-
- if (_enableLeft) {
- int l = output + leftSample;
- if (l > 32767)
- l = 32767;
- if (l < -32767)
- l = -32767;
- leftSample = (int16) l;
- }
-
- if (_enableRight) {
- int r = output + rightSample;
- if (r > 32767)
- r = 32767;
- if (r < -32767)
- r = -32767;
- rightSample = (int16) r;
- }
-}
+ _totalLevel = 0;
+ _algorithm = 0;
+ _flags = CHS_EOT;
+ _algorithm = 0;
+
+ _block = 0;
+ _frequency = 0;
+ _frqBlockMSB = 0;
+ _frqLSB = 0;
-void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) {
- uint8 h = regAdress & 0xf0;
- uint8 l = (regAdress & 0x0f);
- static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
- uint8 o = oprOrdr[(l - _regOffset) >> 2];
+ _ssgTl = 0;
+ _ssgStartLvl = 0;
+ _ssgTargetLvl = 0;
+ _ssgStep = 0;
+ _ssgTicksLeft = 0;
- switch (h) {
- case 0x00:
- // ssg
- warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress);
- break;
- case 0x10:
- // adpcm
- warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress);
- break;
- case 0x20:
- if (l == 8) {
- // Key on/off
- for (int i = 0; i < 4; i++) {
- if ((value >> (4 + i)) & 1)
- _opr[i]->keyOn();
- else
- _opr[i]->keyOff();
- }
- } else if (l == 2) {
- // LFO
- warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)");
- } else if (l == 7) {
- // Timers; Ch 3/6 special mode
- warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE (NOT SUPPORTED)");
- } else if (l == 4 || l == 5) {
- // Timer A
- warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_A (NOT SUPPORTED)");
- } else if (l == 6) {
- // Timer B
- warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_B (NOT SUPPORTED)");
- } else if (l == 10 || l == 11) {
- // DAC
- warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)");
- }
- break;
-
- case 0x30:
- // detune, multiple
- _opr[o]->detune((value >> 4) & 7);
- _opr[o]->multiple(value & 0x0f);
- _updateEnvelopes = true;
- break;
-
- case 0x40:
- // total level
- _opr[o]->totalLevel(value & 0x7f);
- break;
-
- case 0x50:
- // rate scaling, attack rate
- _opr[o]->attackRate(value & 0x1f);
- if (_opr[o]->scaleRate(value >> 6))
- _updateEnvelopes = true;
- break;
-
- case 0x60:
- // first decay rate, amplitude modulation
- _opr[o]->decayRate(value & 0x1f);
- if (value & 0x80)
- warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)");
-
- break;
-
- case 0x70:
- // secondary decay rate
- _opr[o]->sustainRate(value & 0x1f);
- break;
-
- case 0x80:
- // secondary amplitude, release rate;
- _opr[o]->sustainLevel(value >> 4);
- _opr[o]->releaseRate(value & 0x0f);
- break;
-
- case 0x90:
- // ssg
- warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress);
- break;
-
- case 0xa0:
- // frequency
- l -= _regOffset;
- if (l == 0) {
- _frqTemp = (_frqTemp & 0xff00) | value;
- _updateEnvelopes = true;
- for (int i = 0; i < 4; i++)
- _opr[i]->frequency(_frqTemp);
- } else if (l == 4) {
- _frqTemp = (_frqTemp & 0xff) | (value << 8);
- } else if (l == 8) {
- // Ch 3/6 special mode frq
- warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
- } else if (l == 12) {
- // Ch 3/6 special mode frq
- warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
- }
- break;
-
- case 0xb0:
- l -= _regOffset;
- if (l == 0) {
- // feedback, _algorithm
- _opr[0]->feedbackLevel((value >> 3) & 7);
- _opr[1]->feedbackLevel(0);
- _opr[2]->feedbackLevel(0);
- _opr[3]->feedbackLevel(0);
- } else if (l == 4) {
- // stereo, LFO sensitivity
- _enableLeft = value & 0x80 ? true : false;
- _enableRight = value & 0x40 ? true : false;
- uint8 ams = (value & 0x3F) >> 3;
- if (ams)
- warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)");
- uint8 fms = value & 3;
- if (fms)
- warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)");
- }
- break;
-
- default:
- warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress);
- break;
- }
+ _vbrInitDelayHi = 0;
+ _vbrInitDelayLo = 0;
+ _vbrModInitVal = 0;
+ _vbrDuration = 0;
+ _vbrCurDelay = 0;
+ _vbrModCurVal = 0;
+ _vbrDurLeft = 0;
}
bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) {
- _instrID = para;
+ _instr = para;
uint8 reg = _regOffset + 0x80;
for (int i = 0; i < 4; i++) {
// set release rate for each operator
- writeReg(reg, 0x0f);
+ _drv->writeReg(_part, reg, 0x0f);
reg += 4;
}
- const uint8 *tptr = _drv->_patches + ((uint32)_instrID << 5);
+ const uint8 *tptr = _drv->_patches + ((uint32)_instr << 5);
reg = _regOffset + 0x30;
// write registers 0x30 to 0x8f
for (int i = 0; i < 6; i++) {
- writeReg(reg, tptr[0]);
+ _drv->writeReg(_part, reg, tptr[0]);
reg += 4;
- writeReg(reg, tptr[2]);
+ _drv->writeReg(_part, reg, tptr[2]);
reg += 4;
- writeReg(reg, tptr[1]);
+ _drv->writeReg(_part, reg, tptr[1]);
reg += 4;
- writeReg(reg, tptr[3]);
+ _drv->writeReg(_part, reg, tptr[3]);
reg += 4;
tptr += 4;
}
@@ -1998,7 +2022,7 @@ bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) {
reg = _regOffset + 0xB0;
_algorithm = tptr[0] & 7;
// set feedback and algorithm
- writeReg(reg, tptr[0]);
+ _drv->writeReg(_part, reg, tptr[0]);
setOutputLevel();
return true;
@@ -2033,7 +2057,7 @@ bool TownsPC98_OpnChannel::control_f4_setOutputLevel(uint8 para) {
}
bool TownsPC98_OpnChannel::control_f5_setTempo(uint8 para) {
- _drv->setTempo(para);
+ _drv->setMusicTempo(para);
return true;
}
@@ -2043,7 +2067,7 @@ bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) {
if (*_dataPtr) {
// repeat section until counter has reached zero
- _dataPtr = _drv->_trackData + READ_LE_UINT16(_dataPtr + 2);
+ _dataPtr = _drv->_trackPtr + READ_LE_UINT16(_dataPtr + 2);
} else {
// reset counter, advance to next section
_dataPtr[0] = _dataPtr[1];
@@ -2052,35 +2076,36 @@ bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) {
return true;
}
-bool TownsPC98_OpnChannel::control_f7_setupPitchWheel(uint8 para) {
- _ptchWhlInitDelayLo = _dataPtr[0];
- _ptchWhlInitDelayHi = para;
- _ptchWhlModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1);
- _ptchWhlDuration = _dataPtr[3];
+bool TownsPC98_OpnChannel::control_f7_setupVibrato(uint8 para) {
+ _vbrInitDelayHi = _dataPtr[0];
+ _vbrInitDelayLo = para;
+ _vbrModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1);
+ _vbrDuration = _dataPtr[3];
_dataPtr += 4;
- _flags = (_flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF | CHS_RECALCFREQ;
+ _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF | CHS_RECALCFREQ;
return true;
}
-bool TownsPC98_OpnChannel::control_f8_togglePitchWheel(uint8 para) {
+bool TownsPC98_OpnChannel::control_f8_toggleVibrato(uint8 para) {
if (para == 0x10) {
if (*_dataPtr++) {
- _flags = (_flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF;
+ _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF;
} else {
- _flags |= CHS_PITCHWHEELOFF;
+ _flags |= CHS_VBROFF;
}
} else {
- //uint8 skipChannels = para / 36;
- //uint8 entry = para % 36;
- //TownsPC98_OpnDriver::TownsPC98_OpnChannel *t = &chan[skipChannels];
- ////// NOT IMPLEMENTED
- //t->unnamedEntries[entry] = *_dataPtr++;
+ /* NOT IMPLEMENTED
+ uint8 skipChannels = para / 36;
+ uint8 entry = para % 36;
+ TownsPC98_OpnDriver::TownsPC98_OpnChannel *t = &chan[skipChannels];
+
+ t->unnamedEntries[entry] = *_dataPtr++;*/
}
return true;
}
bool TownsPC98_OpnChannel::control_fa_writeReg(uint8 para) {
- writeReg(para, *_dataPtr++);
+ _drv->writeReg(_part, para, *_dataPtr++);
return true;
}
@@ -2113,7 +2138,7 @@ bool TownsPC98_OpnChannel::control_fc_decOutLevel(uint8 para) {
}
bool TownsPC98_OpnChannel::control_fd_jump(uint8 para) {
- uint8 *tmp = _drv->_trackData + READ_LE_UINT16(_dataPtr - 1);
+ uint8 *tmp = _drv->_trackPtr + READ_LE_UINT16(_dataPtr - 1);
_dataPtr = (tmp[1] == 1) ? tmp : ++_dataPtr;
return true;
}
@@ -2127,7 +2152,7 @@ bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) {
uint16 val = READ_LE_UINT16(--_dataPtr);
if (val) {
// loop
- _dataPtr = _drv->_trackData + val;
+ _dataPtr = _drv->_trackPtr + val;
return true;
} else {
// quit parsing for active channel
@@ -2139,31 +2164,248 @@ bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) {
}
}
-bool TownsPC98_OpnChannel::control_f0_setPatchSSG(uint8 para) {
- _instrID = para << 4;
+TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs,
+ uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
+ TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) {
+}
+
+void TownsPC98_OpnChannelSSG::init() {
+ _algorithm = 0x80;
+
+ #define Control(x) &TownsPC98_OpnChannelSSG::control_##x
+ static const ControlEventFunc ctrlEventsSSG[] = {
+ Control(f0_setInstr),
+ Control(f1_setTotalLevel),
+ Control(f2_setKeyOffTime),
+ Control(f3_setFreqLSB),
+ Control(f4_setAlgorithm),
+ Control(f5_setTempo),
+ Control(f6_repeatSection),
+ Control(f7_setupVibrato),
+ Control(f8_toggleVibrato),
+ Control(f9_loadCustomPatch),
+ Control(fa_writeReg),
+ Control(fb_incOutLevel),
+ Control(fc_decOutLevel),
+ Control(fd_jump),
+ Control(dummy),
+ Control(ff_endOfTrack)
+ };
+ #undef Control
+
+ controlEvents = ctrlEventsSSG;
+}
+
+void TownsPC98_OpnChannelSSG::processEvents() {
+ if (_flags & CHS_EOT)
+ return;
+
+ _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
+
+ if (!_hold && _ticksLeft == _keyOffTime)
+ nextShape();
+
+ if (!--_ticksLeft) {
+
+ uint8 cmd = 0;
+ bool loop = true;
+
+ while (loop) {
+ cmd = *_dataPtr++;
+ if (cmd < 0xf0)
+ loop = false;
+ else if (!processControlEvent(cmd))
+ return;
+ }
+
+ uint8 para = *_dataPtr++;
+
+ if (cmd == 0x80) {
+ nextShape();
+ _hold = false;
+ } else {
+ if (!_hold) {
+ _instr &= 0xf0;
+ _ssgStep = _drv->_ssgPatches[_instr];
+ _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
+ _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
+ _ssgStartLvl = _drv->_ssgPatches[_instr + 3];
+ _flags = (_flags & ~CHS_SSGOFF) | CHS_KEYOFF;
+ }
+
+ keyOn();
+
+ if (_hold == false || cmd != _frqBlockMSB)
+ _flags |= CHS_RECALCFREQ;
+
+ _hold = (para & 0x80) ? true : false;
+ _frqBlockMSB = cmd;
+ }
+
+ _ticksLeft = para & 0x7f;
+ }
+
+ if (!(_flags & CHS_SSGOFF)) {
+ if (--_ssgTicksLeft) {
+ if (!_drv->_fading)
+ setOutputLevel(_ssgStartLvl);
+ return;
+ }
+
+ _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
+
+ if (_drv->_ssgPatches[_instr + 1] & 0x80) {
+ uint8 t = _ssgStartLvl - _ssgStep;
+
+ if (_ssgStep <= _ssgStartLvl && _ssgTargetLvl < t) {
+ if (!_drv->_fading)
+ setOutputLevel(t);
+ return;
+ }
+ } else {
+ int t = _ssgStartLvl + _ssgStep;
+ uint8 p = (uint8) (t & 0xff);
+
+ if (t < 256 && _ssgTargetLvl > p) {
+ if (!_drv->_fading)
+ setOutputLevel(p);
+ return;
+ }
+ }
+
+ setOutputLevel(_ssgTargetLvl);
+ if (_ssgStartLvl && !(_instr & 8)){
+ _instr += 4;
+ _ssgStep = _drv->_ssgPatches[_instr];
+ _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
+ _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
+ } else {
+ _flags |= CHS_SSGOFF;
+ setOutputLevel(0);
+ }
+ }
+}
+
+void TownsPC98_OpnChannelSSG::processFrequency() {
+ if (_algorithm & 0x40)
+ return;
+
+ if (_flags & CHS_RECALCFREQ) {
+ _block = _frqBlockMSB >> 4;
+ _frequency = ((const uint16*)_drv->_opnFreqTableSSG)[_frqBlockMSB & 0x0f] + _frqLSB;
+
+ uint16 f = _frequency >> _block;
+ _drv->writeReg(_part, _regOffset << 1, f & 0xff);
+ _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
+
+ setupVibrato();
+ }
+
+ if (!(_flags & (CHS_EOT | CHS_VBROFF | CHS_SSGOFF))) {
+ if (!processVibrato())
+ return;
+
+ uint16 f = _frequency >> _block;
+ _drv->writeReg(_part, _regOffset << 1, f & 0xff);
+ _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
+ }
+}
+
+bool TownsPC98_OpnChannelSSG::processControlEvent(uint8 cmd) {
+ uint8 para = *_dataPtr++;
+ return (this->*controlEvents[cmd & 0x0f])(para);
+}
+
+void TownsPC98_OpnChannelSSG::nextShape() {
+ _instr = (_instr & 0xf0) + 0x0c;
+ _ssgStep = _drv->_ssgPatches[_instr];
+ _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
+ _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
+}
+
+void TownsPC98_OpnChannelSSG::keyOn() {
+ uint8 c = 0x7b;
+ uint8 t = (_algorithm & 0xC0) << 1;
+ if (_algorithm & 0x80)
+ t |= 4;
+
+ c = (c << (_regOffset + 1)) | (c >> (7 - _regOffset));
+ t = (t << (_regOffset + 1)) | (t >> (7 - _regOffset));
+
+ if (!(_algorithm & 0x80))
+ _drv->writeReg(_part, 6, _algorithm & 0x7f);
+
+ uint8 e = (_drv->readSSGStatus() & c) | t;
+ _drv->writeReg(_part, 7, e);
+}
+
+void TownsPC98_OpnChannelSSG::protect() {
+ _flags |= CHS_PROTECT;
+}
+
+void TownsPC98_OpnChannelSSG::restore() {
+ _flags &= ~CHS_PROTECT;
+ keyOn();
+ _drv->writeReg(_part, 8 + _regOffset, _ssgTl);
+ uint16 f = _frequency >> _block;
+ _drv->writeReg(_part, _regOffset << 1, f & 0xff);
+ _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
+}
+
+void TownsPC98_OpnChannelSSG::loadData(uint8 *data) {
+ _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
+ TownsPC98_OpnChannel::loadData(data);
+ setOutputLevel(0);
+ _algorithm = 0x80;
+}
+
+void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) {
+ _ssgStartLvl = lvl;
+ uint16 newTl = (((uint16)_totalLevel + 1) * (uint16)lvl) >> 8;
+ if (newTl == _ssgTl)
+ return;
+ _ssgTl = newTl;
+ _drv->writeReg(_part, 8 + _regOffset, _ssgTl);
+}
+
+void TownsPC98_OpnChannelSSG::fadeStep() {
+ _totalLevel--;
+ if ((int8)_totalLevel < 0)
+ _totalLevel = 0;
+ setOutputLevel(_ssgStartLvl);
+}
+
+bool TownsPC98_OpnChannelSSG::control_f0_setInstr(uint8 para) {
+ _instr = para << 4;
para = (para >> 3) & 0x1e;
if (para)
return control_f4_setAlgorithm(para | 0x40);
return true;
}
-bool TownsPC98_OpnChannel::control_f1_setTotalLevel(uint8 para) {
+bool TownsPC98_OpnChannelSSG::control_f1_setTotalLevel(uint8 para) {
if (!_drv->_fading)
_totalLevel = para;
return true;
}
-bool TownsPC98_OpnChannel::control_f4_setAlgorithm(uint8 para) {
+bool TownsPC98_OpnChannelSSG::control_f4_setAlgorithm(uint8 para) {
_algorithm = para;
return true;
}
-bool TownsPC98_OpnChannel::control_f9_unkSSG(uint8 para) {
- _dataPtr += 5;
+bool TownsPC98_OpnChannelSSG::control_f9_loadCustomPatch(uint8 para) {
+ _instr = (_drv->_sfxOffs + 10 + _regOffset) << 4;
+ _drv->_ssgPatches[_instr] = *_dataPtr++;
+ _drv->_ssgPatches[_instr + 3] = para;
+ _drv->_ssgPatches[_instr + 4] = *_dataPtr++;
+ _drv->_ssgPatches[_instr + 6] = *_dataPtr++;
+ _drv->_ssgPatches[_instr + 8] = *_dataPtr++;
+ _drv->_ssgPatches[_instr + 12] = *_dataPtr++;
return true;
}
-bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) {
+bool TownsPC98_OpnChannelSSG::control_fb_incOutLevel(uint8 para) {
_dataPtr--;
if (_drv->_fading)
return true;
@@ -2175,7 +2417,7 @@ bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) {
return true;
}
-bool TownsPC98_OpnChannel::control_fc_decOutLevelSSG(uint8 para) {
+bool TownsPC98_OpnChannelSSG::control_fc_decOutLevel(uint8 para) {
_dataPtr--;
if (_drv->_fading)
return true;
@@ -2186,200 +2428,513 @@ bool TownsPC98_OpnChannel::control_fc_decOutLevelSSG(uint8 para) {
return true;
}
-bool TownsPC98_OpnChannel::control_ff_endOfTrackSSG(uint8 para) {
- uint16 val = READ_LE_UINT16(--_dataPtr);
- if (val) {
- // loop
- _dataPtr = _drv->_trackData + val;
- return true;
+bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) {
+ if (!_drv->_sfxOffs) {
+ uint16 val = READ_LE_UINT16(--_dataPtr);
+ if (val) {
+ // loop
+ _dataPtr = _drv->_trackPtr + val;
+ return true;
+ } else {
+ // stop parsing
+ if (!_drv->_fading)
+ setOutputLevel(0);
+ --_dataPtr;
+ _flags |= CHS_EOT;
+ _drv->_finishedSSGFlag |= _idFlag;
+ }
} else {
- // quit parsing for active channel
- --_dataPtr;
+ // end of sfx track - restore ssg music channel
_flags |= CHS_EOT;
- //_finishedChannelsFlag |= _idFlag;
- keyOff();
- return false;
+ _drv->_finishedSfxFlag |= _idFlag;
+ _drv->_ssgChannels[_chanNum]->restore();
}
+
+ return false;
+}
+
+void TownsPC98_OpnSfxChannel::loadData(uint8 *data) {
+ _flags = CHS_ALLOFF;
+ _ticksLeft = 1;
+ _dataPtr = data;
+ _ssgTl = 0xff;
+ _algorithm = 0x80;
}
-TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs,
+TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs,
uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) {
}
-void TownsPC98_OpnChannelSSG::init() {
+void TownsPC98_OpnChannelPCM::init() {
_algorithm = 0x80;
-
- _opr = new TownsPC98_OpnOperator*[4];
- for (int i = 0; i < 4; i++)
- _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift,
- _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune);
- #define Control(x) &TownsPC98_OpnChannelSSG::control_##x
- static const ControlEventFunc ctrlEventsSSG[] = {
- Control(f0_setPatchSSG),
- Control(f1_setTotalLevel),
- Control(f2_setKeyOffTime),
- Control(f3_setFreqLSB),
- Control(f4_setOutputLevel),
- Control(f5_setTempo),
+ #define Control(x) &TownsPC98_OpnChannelPCM::control_##x
+ static const ControlEventFunc ctrlEventsPCM[] = {
+ Control(dummy),
+ Control(f1_prcStart),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
Control(f6_repeatSection),
- Control(f7_setupPitchWheel),
- Control(f8_togglePitchWheel),
- Control(f9_unkSSG),
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
Control(fa_writeReg),
- Control(fb_incOutLevelSSG),
- Control(fc_decOutLevelSSG),
- Control(fd_jump),
Control(dummy),
- Control(ff_endOfTrackSSG)
+ Control(dummy),
+ Control(dummy),
+ Control(dummy),
+ Control(ff_endOfTrack)
};
#undef Control
- controlEvents = ctrlEventsSSG;
+ controlEvents = ctrlEventsPCM;
}
-void TownsPC98_OpnChannelSSG::processEvents() {
+void TownsPC98_OpnChannelPCM::loadData(uint8 *data) {
+ _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
+ _ticksLeft = 1;
+ _dataPtr = data;
+ _totalLevel = 0x7F;
+}
+
+void TownsPC98_OpnChannelPCM::processEvents() {
if (_flags & CHS_EOT)
return;
- _drv->_ssgFlag = (_flags & CHS_SSG) ? -1 : 0;
-
- if (_protect == false && _ticksLeft == _keyOffTime)
- keyOff();
-
if (--_ticksLeft)
return;
- if (_protect == false)
- keyOff();
-
uint8 cmd = 0;
bool loop = true;
while (loop) {
cmd = *_dataPtr++;
- if (cmd < 0xf0)
+ if (cmd == 0x80) {
loop = false;
- else if (!processControlEvent(cmd))
+ } else if (cmd < 0xf0) {
+ _drv->writeReg(_part, 0x10, cmd);
+ } else if (!processControlEvent(cmd)) {
return;
+ }
}
+ _ticksLeft = *_dataPtr++;
+}
+
+bool TownsPC98_OpnChannelPCM::processControlEvent(uint8 cmd) {
uint8 para = *_dataPtr++;
+ return (this->*controlEvents[cmd & 0x0f])(para);
+}
- if (cmd == 0x80) {
- keyOff();
- _protect = false;
+bool TownsPC98_OpnChannelPCM::control_f1_prcStart(uint8 para) {
+ _totalLevel = para;
+ _drv->writeReg(_part, 0x11, para);
+ return true;
+}
+
+bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) {
+ uint16 val = READ_LE_UINT16(--_dataPtr);
+ if (val) {
+ // loop
+ _dataPtr = _drv->_trackPtr + val;
+ return true;
} else {
- keyOn();
+ // quit parsing for active channel
+ --_dataPtr;
+ _flags |= CHS_EOT;
+ _drv->_finishedRhythmFlag |= _idFlag;
+ return false;
+ }
+}
- if (_protect == false || cmd != _frqBlockMSB)
- _flags |= CHS_RECALCFREQ;
+TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0),
+ _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0) {
+ memset(_channels, 0, sizeof(Channel) * 3);
- _protect = (para & 0x80) ? true : false;
- _frqBlockMSB = cmd;
+ static uint8 *const reg [] = {
+ &_channels[0].frqL,
+ &_channels[0].frqH,
+ &_channels[1].frqL,
+ &_channels[1].frqH,
+ &_channels[2].frqL,
+ &_channels[2].frqH,
+ &_noiseGenerator,
+ &_chanEnable,
+ &_channels[0].vol,
+ &_channels[1].vol,
+ &_channels[2].vol,
+ };
+
+ _reg = reg;
+
+ reset();
+}
+
+TownsPC98_OpnSquareSineSource::~TownsPC98_OpnSquareSineSource() {
+ delete [] _tlTable;
+ delete [] _tleTable;
+}
+
+void TownsPC98_OpnSquareSineSource::init(const int *rsTable, const int *rseTable) {
+ if (_ready) {
+ reset();
+ return;
}
- _ticksLeft = para & 0x7f;
+ delete [] _tlTable;
+ delete [] _tleTable;
+ _tlTable = new int32[16];
+ _tleTable = new int32[32];
+ float a, b, d;
+ d = 801.0f;
+
+ for (int i = 0; i < 16; i++) {
+ b = 1.0f / rsTable[i];
+ a = 1.0f / d + b + 1.0f / 1000.0f;
+ float v = (b / a) * 32767.0f;
+ _tlTable[i] = (int32) v;
+
+ b = 1.0f / rseTable[i];
+ a = 1.0f / d + b + 1.0f / 1000.0f;
+ v = (b / a) * 32767.0f;
+ _tleTable[i] = (int32) v;
+ }
- if (!(_flags & CHS_SSG)) {
+ for (int i = 16; i < 32; i++) {
+ b = 1.0f / rseTable[i];
+ a = 1.0f / d + b + 1.0f / 1000.0f;
+ float v = (b / a) * 32767.0f;
+ _tleTable[i] = (int32) v;
+ }
+ _ready = true;
+}
+
+void TownsPC98_OpnSquareSineSource::reset() {
+ _rand = 1;
+ _outN = 1;
+ _updateRequest = -1;
+ _nTick = _evpUpdateCnt = 0;
+ _evpTimer = 0x1f;
+ _pReslt = 0x1f;
+ _attack = 0;
+ _cont = false;
+ _evpUpdate = true;
+ _timer = 0;
+
+ for (int i = 0; i < 3; i++) {
+ _channels[i].tick = 0;
+ _channels[i].smp = _channels[i].out = 0;
}
+
+ for (int i = 0; i < 14; i++)
+ writeReg(i, 0, true);
+
+ writeReg(7, 0xbf, true);
}
-void TownsPC98_OpnChannelSSG::processFrequency() {
- if (_flags & CHS_RECALCFREQ) {
- uint8 block = (_frqBlockMSB & 0x70) >> 1;
- uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f];
- frequency = (bfreq + _frqLSB) | (block << 8);
+void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool force) {
+ if (address > 10 || *_reg[address] == value) {
+ if ((address == 11 || address == 12 || address == 13) && value)
+ warning("TownsPC98_OpnSquareSineSource: unsupported reg address: %d", address);
+ return;
+ }
+
+ if (!force) {
+ if (_updateRequest == 31) {
+ warning("TownsPC98_OpnSquareSineSource: event buffer overflow");
+ _updateRequest = -1;
+ }
+ _updateRequestBuf[++_updateRequest] = value;
+ _updateRequestBuf[++_updateRequest] = address;
+ return;
+ }
- writeReg(_regOffset + 0xa4, (frequency >> 8));
- writeReg(_regOffset + 0xa0, (frequency & 0xff));
+ *_reg[address] = value;
+}
+
+void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
+ return;
+
+ for (uint32 i = 0; i < bufferSize; i++) {
+ _timer += _tickLength;
+ while (_timer > 0x5B8D80) {
+ _timer -= 0x5B8D80;
+
+ if (++_nTick >= (_noiseGenerator & 0x1f)) {
+ if ((_rand + 1) & 2)
+ _outN ^= 1;
- _ptchWhlCurDelay = _ptchWhlInitDelayHi;
- if (_flags & CHS_KEYOFF) {
- _ptchWhlModCurVal = _ptchWhlModInitVal;
- _ptchWhlCurDelay += _ptchWhlInitDelayLo;
+ _rand = (((_rand & 1) ^ ((_rand >> 3) & 1)) << 16) | (_rand >> 1);
+ _nTick = 0;
+ }
+
+ for (int ii = 0; ii < 3; ii++) {
+ if (++_channels[ii].tick >= (((_channels[ii].frqH & 0x0f) << 8) | _channels[ii].frqL)) {
+ _channels[ii].tick = 0;
+ _channels[ii].smp ^= 1;
+ }
+ _channels[ii].out = (_channels[ii].smp | ((_chanEnable >> ii) & 1)) & (_outN | ((_chanEnable >> (ii + 3)) & 1));
+ }
+
+ if (_evpUpdate) {
+ if (++_evpUpdateCnt >= 0) {
+ _evpUpdateCnt = 0;
+
+ if (--_evpTimer < 0) {
+ if (_cont) {
+ _evpTimer &= 0x1f;
+ } else {
+ _evpUpdate = false;
+ _evpTimer = 0;
+ }
+ }
+ }
+ }
+ _pReslt = _evpTimer ^ _attack;
+ updatesRegs();
+ }
+
+ int32 finOut = 0;
+ for (int ii = 0; ii < 3; ii++) {
+ if ((_channels[ii].vol >> 4) & 1)
+ finOut += _tleTable[_channels[ii].out ? _pReslt : 0];
+ else
+ finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
}
- _ptchWhlDurLeft = (_ptchWhlDuration >> 1);
- _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ);
+ finOut /= 2;
+ buffer[i << 1] += finOut;
+ buffer[(i << 1) + 1] += finOut;
}
+}
- if (!(_flags & CHS_PITCHWHEELOFF)) {
- if (--_ptchWhlCurDelay)
- return;
- _ptchWhlCurDelay = _ptchWhlInitDelayHi;
- frequency += _ptchWhlModCurVal;
+void TownsPC98_OpnSquareSineSource::updatesRegs() {
+ for (int i = 0; i < _updateRequest;) {
+ uint8 b = _updateRequestBuf[i++];
+ uint8 a = _updateRequestBuf[i++];
+ writeReg(a, b, true);
+ }
+ _updateRequest = -1;
+}
+
+TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) :
+ _tickLength(timerbase * 2), _timer(0), _ready(false) {
+
+ memset(_rhChan, 0, sizeof(RhtChannel) * 6);
+ static uint8 *const reg [] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ &_rhChan[0].startPosL,
+ &_rhChan[1].startPosL,
+ &_rhChan[2].startPosL,
+ &_rhChan[3].startPosL,
+ &_rhChan[4].startPosL,
+ &_rhChan[5].startPosL,
+ &_rhChan[0].startPosH,
+ &_rhChan[1].startPosH,
+ &_rhChan[2].startPosH,
+ &_rhChan[3].startPosH,
+ &_rhChan[4].startPosH,
+ &_rhChan[5].startPosH,
+ &_rhChan[0].endPosL,
+ &_rhChan[1].endPosL,
+ &_rhChan[2].endPosL,
+ &_rhChan[3].endPosL,
+ &_rhChan[4].endPosL,
+ &_rhChan[5].endPosL,
+ &_rhChan[0].endPosH,
+ &_rhChan[1].endPosH,
+ &_rhChan[2].endPosH,
+ &_rhChan[3].endPosH,
+ &_rhChan[4].endPosH,
+ &_rhChan[5].endPosH,
+ };
+
+ _reg = reg;
+}
+
+void TownsPC98_OpnPercussionSource::init(const uint8 *instrData) {
+ if (_ready) {
+ reset();
+ return;
+ }
- writeReg(_regOffset + 0xa4, (frequency >> 8));
- writeReg(_regOffset + 0xa0, (frequency & 0xff));
+ const uint8 *start = instrData;
+ const uint8 *pos = start;
- if(!--_ptchWhlDurLeft) {
- _ptchWhlDurLeft = _ptchWhlDuration;
- _ptchWhlModCurVal = -_ptchWhlModCurVal;
+ if (instrData) {
+ for (int i = 0; i < 6; i++) {
+ _rhChan[i].data = start + READ_BE_UINT16(pos);
+ pos += 2;
+ _rhChan[i].size = READ_BE_UINT16(pos);
+ pos += 2;
}
+ reset();
+ _ready = true;
+ } else {
+ memset(_rhChan, 0, sizeof(RhtChannel) * 6);
+ _ready = false;
}
}
-void TownsPC98_OpnChannelSSG::keyOff() {
- // all operators off
- uint8 value = _keyNum & 0x0f;
- uint8 regAdress = 0x28;
- writeReg(regAdress, value);
- _flags |= CHS_KEYOFF;
-}
+void TownsPC98_OpnPercussionSource::reset() {
+ _timer = 0;
+ _totalLevel = 63;
-void TownsPC98_OpnChannelSSG::keyOn() {
- // all operators on
- uint8 value = _keyNum | 0xf0;
- uint8 regAdress = 0x28;
- writeReg(regAdress, value);
+ for (int i = 0; i < 6; i++) {
+ RhtChannel *s = &_rhChan[i];
+ s->pos = s->start = s->data;
+ s->end = s->data + s->size;
+ s->active = false;
+ s->level = 0;
+ s->out = 0;
+ s->decStep = 1;
+ s->decState = 0;
+ s->samples[0] = s->samples[1] = 0;
+ s->startPosH = s->startPosL = s->endPosH = s->endPosL = 0;
+ }
}
-void TownsPC98_OpnChannelSSG::loadData(uint8 *data) {
- _drv->_ssgFlag = (_flags & CHS_SSG) ? -1 : 0;
- opn_SSG_UNK(0);
- TownsPC98_OpnChannel::loadData(data);
- _algorithm = 0x80;
+void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) {
+ if (!_ready)
+ return;
+
+ uint8 h = address >> 4;
+ uint8 l = address & 15;
+
+ if (address > 15)
+ *_reg[address] = value;
+
+ if (address == 0) {
+ if (value & 0x80) {
+ //key off
+ for (int i = 0; i < 6; i++) {
+ if ((value >> i) & 1)
+ _rhChan[i].active = false;
+ }
+ } else {
+ //key on
+ for (int i = 0; i < 6; i++) {
+ if ((value >> i) & 1) {
+ RhtChannel *s = &_rhChan[i];
+ s->pos = s->start;
+ s->active = true;
+ s->out = 0;
+ s->samples[0] = s->samples[1] = 0;
+ s->decStep = 1;
+ s->decState = 0;
+ }
+ }
+ }
+ } else if (address == 1) {
+ // total level
+ _totalLevel = (value & 63) ^ 63;
+ for (int i = 0; i < 6; i++)
+ recalcOuput(&_rhChan[i]);
+ } else if (!h && l & 8) {
+ // instrument level
+ l &= 7;
+ _rhChan[l].level = (value & 0x1f) ^ 0x1f;
+ recalcOuput(&_rhChan[l]);
+ } else if (h & 3) {
+ l &= 7;
+ if (h == 1) {
+ // set start offset
+ _rhChan[l].start = _rhChan[l].data + ((_rhChan[l].startPosH << 8 | _rhChan[l].startPosL) << 8);
+ } else if (h == 2) {
+ // set end offset
+ _rhChan[l].end = _rhChan[l].data + ((_rhChan[l].endPosH << 8 | _rhChan[l].endPosL) << 8) + 255;
+ }
+ }
}
-void TownsPC98_OpnChannelSSG::opn_SSG_UNK(uint8 a) {
- _ssg1 = a;
- uint16 h = (_totalLevel + 1) * a;
- if ((h >> 8) == _ssg2)
+void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
return;
- _ssg2 = (h >> 8);
- writeReg(8 + _regOffset, _ssg2);
+
+ for (uint32 i = 0; i < bufferSize; i++) {
+ _timer += _tickLength;
+ while (_timer > 0x5B8D80) {
+ _timer -= 0x5B8D80;
+
+ for (int ii = 0; ii < 6; ii++) {
+ RhtChannel *s = &_rhChan[ii];
+ if (s->active) {
+ recalcOuput(s);
+ if (s->decStep) {
+ advanceInput(s);
+ if (s->pos == s->end)
+ s->active = false;
+ }
+ s->decStep ^= 1;
+ }
+ }
+ }
+
+ int32 finOut = 0;
+
+ for (int ii = 0; ii < 6; ii++) {
+ if (_rhChan[ii].active)
+ finOut += _rhChan[ii].out;
+ }
+
+ finOut *= 7;
+
+ buffer[i << 1] += finOut;
+ buffer[(i << 1) + 1] += finOut;
+ }
}
-TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) :
- _mixer(mixer), _trackData(0), _playing(false), _fading(false), _channels(0), _ssgChannels(0),
- _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84),
- _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) ,
- _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0),
- _oprDetune(0), _cbCounter(4), _tickCounter(0), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F),
- _finishedChannelsFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), _ready(false),
- _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false),
- _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) {
- setTempo(84);
- _baserate = (486202500.0 / (double)getRate()) / 10368.0;
+void TownsPC98_OpnPercussionSource::recalcOuput(RhtChannel *ins) {
+ uint32 s = _totalLevel + ins->level;
+ uint32 x = s > 62 ? 0 : (1 + (s >> 3));
+ int32 y = s > 62 ? 0 : (15 - (s & 7));
+ ins->out = ((ins->samples[ins->decStep] * y) >> x) & ~3;
}
-TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
- _mixer->stopHandle(_soundHandle);
+void TownsPC98_OpnPercussionSource::advanceInput(RhtChannel *ins) {
+ static const int8 adjustIndex[] = {-1, -1, -1, -1, 2, 5, 7, 9 };
- if (_channels) {
- for (int i = 0; i < _numChan; i++)
- delete _channels[i];
- delete [] _channels;
- }
+ static const int16 stepTable[] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55,
+ 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337,
+ 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
+ };
+
+ uint8 cur = (int8) *ins->pos++;
- if (_ssgChannels) {
- for (int i = 0; i < _numSSG; i++)
- delete _ssgChannels[i];
- delete [] _ssgChannels;
+ for (int i = 0; i < 2; i++) {
+ int b = (2 * (cur & 7) + 1) * stepTable[ins->decState] / 8;
+ ins->samples[i] = CLIP<int16>(ins->samples[i ^ 1] + (cur & 8 ? b : -b), -2048, 2047);
+ ins->decState = CLIP<int8>(ins->decState + adjustIndex[cur & 7], 0, 48);
+ cur >>= 4;
}
+}
+
+TownsPC98_OpnCore::TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type) :
+ _mixer(mixer),
+ _chanInternal(0), _ssg(0), _prc(0),
+ _numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPercussion(type == OD_TYPE86 ? true : false),
+ _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
+ _baserate(55125.0f / (float)mixer->getOutputRate()),
+ _regProtectionFlag(false), _ready(false) {
+
+ memset(&_timers[0], 0, sizeof(OpnTimer));
+ memset(&_timers[1], 0, sizeof(OpnTimer));
+ _timers[0].cb = &TownsPC98_OpnCore::timerCallbackA;
+ _timers[1].cb = &TownsPC98_OpnCore::timerCallbackB;
+ _timerbase = (uint32)(_baserate * 1000000.0f);
+}
+
+TownsPC98_OpnCore::~TownsPC98_OpnCore() {
+ _mixer->stopHandle(_soundHandle);
+ delete _ssg;
+ delete _prc;
+ delete [] _chanInternal;
delete [] _oprRates;
delete [] _oprRateshift;
@@ -2387,235 +2942,280 @@ TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
delete [] _oprAttackDecay;
delete [] _oprSinTbl;
delete [] _oprLevelOut;
- delete [] _oprDetune;
+ delete [] _oprDetune;
}
-bool TownsPC98_OpnDriver::init() {
+bool TownsPC98_OpnCore::init() {
if (_ready) {
reset();
return true;
}
generateTables();
+
+ TownsPC98_OpnOperator **opr = new TownsPC98_OpnOperator*[_numChan << 2];
+ for (int i = 0; i < (_numChan << 2); i++)
+ opr[i] = new TownsPC98_OpnOperator(_timerbase, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune);
- if (_channels) {
- for (int i = 0; i < _numChan; i++) {
- if (_channels[i])
- delete _channels[i];
- }
- delete [] _channels;
- }
- _channels = new TownsPC98_OpnChannel*[_numChan];
+ _chanInternal = new ChanInternal[_numChan];
for (int i = 0; i < _numChan; i++) {
- int ii = i * 6;
- _channels[i] = new TownsPC98_OpnChannel(this, _drvTables[ii], _drvTables[ii + 1],
- _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
- _channels[i]->init();
+ memset(&_chanInternal[i], 0, sizeof(ChanInternal));
+ _chanInternal[i].opr = &opr[i << 2];
}
- if (_ssgChannels) {
- for (int i = 0; i < _numSSG; i++) {
- if (_ssgChannels[i])
- delete _ssgChannels[i];
- }
- delete [] _ssgChannels;
- }
if (_numSSG) {
- _ssgChannels = new TownsPC98_OpnChannelSSG*[_numSSG];
- for (int i = 0; i < _numSSG; i++) {
- int ii = i * 6;
- _ssgChannels[i] = new TownsPC98_OpnChannelSSG(this, _drvTables[ii], _drvTables[ii + 1],
- _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
- _ssgChannels[i]->init();
- }
+ _ssg = new TownsPC98_OpnSquareSineSource(_timerbase);
+ _ssg->init(&_ssgTables[0], &_ssgTables[16]);
+ }
+
+ if (_hasPercussion) {
+ _prc = new TownsPC98_OpnPercussionSource(_timerbase);
+ _prc->init(_percussionData);
}
_mixer->playInputStream(Audio::Mixer::kMusicSoundType,
&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
_ready = true;
+
return true;
}
-int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) {
- memset(buffer, 0, sizeof(int16) * numSamples);
- int32 samplesLeft = numSamples >> 1;
- while (samplesLeft) {
- if (!_samplesTillCallback) {
- callback();
- _samplesTillCallback = _samplesPerCallback;
- _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
- if (_samplesTillCallbackRemainder >= _tempo) {
- _samplesTillCallback++;
- _samplesTillCallbackRemainder -= _tempo;
- }
- }
+void TownsPC98_OpnCore::reset() {
+ for (int i = 0; i < _numChan; i++) {
+ for (int ii = 0; ii < 4; ii++)
+ _chanInternal[i].opr[ii]->reset();
+ memset(&_chanInternal[i].feedbuf, 0, 3);
+ _chanInternal[i].algorithm = 0;
+ _chanInternal[i].frqTemp = 0;
+ _chanInternal[i].enableLeft = _chanInternal[i].enableRight = true;
+ _chanInternal[i].updateEnvelopeParameters = false;
+ }
- int32 render = MIN(samplesLeft, _samplesTillCallback);
- samplesLeft -= render;
- _samplesTillCallback -= render;
+ writeReg(0, 27, 0x33);
- nextTick(buffer, render);
+ if (_ssg)
+ _ssg->reset();
- for (int i = 0; i < render; ++i) {
- buffer[i << 1] <<= 2;
- buffer[(i << 1) + 1] <<= 2;
- }
-
- buffer += (render << 1);
- }
-
- return numSamples;
+ if (_prc)
+ _prc->reset();
}
-void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) {
- if (!_ready) {
- warning("TownsPC98_OpnDriver: Driver must be initialized before loading data");
+void TownsPC98_OpnCore::writeReg(uint8 part, uint8 regAddress, uint8 value) {
+ if (_regProtectionFlag || !_ready)
return;
- }
- if (!data) {
- warning("TownsPC98_OpnDriver: Invalid music file data");
- return;
- }
-
- lock();
- _trackData = data;
-
- reset();
+ static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
- uint8 *src_a = data;
-
- for (uint8 i = 0; i < 3; i++) {
- _channels[i]->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
-
- for (int i = 0; i < _numSSG; i++) {
- _ssgChannels[i]->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
-
- for (uint8 i = 3; i < _numChan; i++) {
- _channels[i]->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
+ uint8 h = regAddress & 0xf0;
+ uint8 l = (regAddress & 0x0f);
+
+ ChanInternal *c = &_chanInternal[(h < 0x30) ? ((value & 3) + ((value & 4) ? 3 : 0)) : ((l & 3) + 3 * part)];
+ TownsPC98_OpnOperator **co = c->opr;
+ TownsPC98_OpnOperator *o = (h < 0x30) ? 0 : c->opr[oprOrdr[(l - (l & 3)) >> 2]];
- if (_hasADPCM) {
- //_adpcmChannel->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
+ switch (h) {
+ case 0x00:
+ // ssg
+ if (_ssg)
+ _ssg->writeReg(regAddress, value);
+ break;
+ case 0x10:
+ // pcm rhythm channel
+ if (_prc)
+ _prc->writeReg(regAddress - 0x10, value);
+ break;
+ case 0x20:
+ if (l == 8) {
+ // Key on/off
+ for (int i = 0; i < 4; i++) {
+ if ((value >> (4 + i)) & 1)
+ co[i]->keyOn();
+ else
+ co[i]->keyOff();
+ }
+ } else if (l == 4) {
+ // Timer A
+ _timers[0].value = (_timers[0].value & 0xff00) | value;
+ } else if (l == 5) {
+ // Timer A
+ _timers[0].value = (_timers[0].value & 0xff) | (value << 8);
+ } else if (l == 6) {
+ // Timer B
+ _timers[1].value = value & 0xff;
+ } else if (l == 7) {
+ _timers[0].enabled = (value & 1) ? 1 : 0;
+ _timers[1].enabled = (value & 2) ? 1 : 0;
+
+ float spc = (float)(0x400 - _timers[0].value) / _baserate;
+ _timers[0].smpPerCb = (int32) spc;
+ _timers[0].smpPerCbRem = (uint32) ((spc - (float)_timers[0].smpPerCb) * 1000000.0f);
+
+ spc = (float)(0x100 - _timers[1].value) * 16.0f / _baserate;
+ _timers[1].smpPerCb = (int32) spc;
+ _timers[1].smpPerCbRem = (uint32) ((spc - (float)_timers[1].smpPerCb) * 1000000.0f);
+
+ if (value & 10) {
+ _timers[0].smpTillCb = _timers[0].smpPerCb;
+ _timers[0].smpTillCbRem = _timers[0].smpTillCbRem;
+ }
+
+ if (value & 20) {
+ _timers[1].smpTillCb = _timers[1].smpPerCb;
+ _timers[1].smpTillCbRem = _timers[1].smpTillCbRem;
+ }
+ } else if (l == 2) {
+ // LFO
+ warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)");
+ } else if (l == 10 || l == 11) {
+ // DAC
+ warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)");
+ }
+ break;
- _ssgFlag = 0;
+ case 0x30:
+ // detune, multiple
+ o->detune((value >> 4) & 7);
+ o->multiple(value & 0x0f);
+ c->updateEnvelopeParameters = true;
+ break;
- _patches = src_a + 4;
- _cbCounter = 4;
- _finishedChannelsFlag = 0;
+ case 0x40:
+ // total level
+ o->totalLevel(value & 0x7f);
+ break;
- // AH 0x17
- unlock();
- _playing = (loadPaused ? false : true);
-}
+ case 0x50:
+ // rate scaling, attack rate
+ o->attackRate(value & 0x1f);
+ if (o->scaleRate(value >> 6))
+ c->updateEnvelopeParameters = true;
+ break;
-void TownsPC98_OpnDriver::reset() {
- for (int i = 0; i < (_numChan); i++)
- _channels[i]->reset();
- for (int i = 0; i < (_numSSG); i++)
- _ssgChannels[i]->reset();
+ case 0x60:
+ // first decay rate, amplitude modulation
+ o->decayRate(value & 0x1f);
+ if (value & 0x80)
+ warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)");
+ break;
- _playing = _fading = false;
- _looping = 0;
- _tickCounter = 0;
-}
+ case 0x70:
+ // secondary decay rate
+ o->sustainRate(value & 0x1f);
+ break;
-void TownsPC98_OpnDriver::fadeOut() {
- if (!_playing)
- return;
+ case 0x80:
+ // secondary amplitude, release rate;
+ o->sustainLevel(value >> 4);
+ o->releaseRate(value & 0x0f);
+ break;
- _fading = true;
+ case 0x90:
+ warning("TownsPC98_OpnDriver: TRYING TO SSG ENVELOPE SHAPES (NOT SUPPORTED)");
+ break;
- for (int i = 0; i < 20; i++) {
- lock();
- uint32 dTime = _tickCounter + 2;
- for (int j = 0; j < _numChan; j++) {
- if (_updateChannelsFlag & _channels[j]->_idFlag)
- _channels[j]->fadeStep();
- }
- for (int j = 0; j < _numSSG; j++)
- _ssgChannels[j]->fadeStep();
+ case 0xa0:
+ // frequency
+ l &= ~3;
+ if (l == 0) {
+ c->frqTemp = (c->frqTemp & 0xff00) | value;
+ c->updateEnvelopeParameters = true;
+ for (int i = 0; i < 4; i++)
+ co[i]->frequency(c->frqTemp);
+ } else if (l == 4) {
+ c->frqTemp = (c->frqTemp & 0xff) | (value << 8);
+ } else if (l == 8) {
+ // Ch 3/6 special mode frq
+ warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
+ } else if (l == 12) {
+ // Ch 3/6 special mode frq
+ warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
+ }
+ break;
- unlock();
+ case 0xb0:
+ l &= ~3;
+ if (l == 0) {
+ // feedback, _algorithm
+ co[0]->feedbackLevel((value >> 3) & 7);
+ c->algorithm = value & 7;
+ } else if (l == 4) {
+ // stereo, LFO sensitivity
+ c->enableLeft = value & 0x80 ? true : false;
+ c->enableRight = value & 0x40 ? true : false;
+ uint8 ams = (value & 0x3F) >> 3;
+ if (ams)
+ warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)");
+ uint8 fms = value & 3;
+ if (fms)
+ warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)");
+ }
+ break;
- while (_playing) {
- if (_tickCounter >= dTime)
- break;
- }
+ default:
+ warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress);
+ break;
}
-
- _fading = false;
-
- reset();
}
-void TownsPC98_OpnDriver::callback() {
- if (!_playing || --_cbCounter)
- return;
+int inline TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) {
+ memset(buffer, 0, sizeof(int16) * numSamples);
+ int32 *tmp = new int32[numSamples];
+ int32 *tmpStart = tmp;
+ memset(tmp, 0, sizeof(int32) * numSamples);
+ int32 samplesLeft = numSamples >> 1;
- _cbCounter = 4;
- _tickCounter++;
+ while (samplesLeft) {
- lock();
+ int32 render = samplesLeft;
- for (int i = 0; i < _numChan; i++) {
- if (_updateChannelsFlag & _channels[i]->_idFlag) {
- _channels[i]->processEvents();
- _channels[i]->processFrequency();
- }
- }
+ for (int i = 0; i < 2; i++) {
+ if (_timers[i].enabled && _timers[i].cb) {
+ if (!_timers[i].smpTillCb) {
+ (this->*_timers[i].cb)();
+ _timers[i].smpTillCb = _timers[i].smpPerCb;
- if (_numSSG) {
- for (int i = 0; i < _numSSG; i++) {
- _ssgChannels[i]->processEvents();
- _ssgChannels[i]->processFrequency();
+ _timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
+ if (_timers[i].smpTillCbRem >= _timerbase) {
+ _timers[i].smpTillCb++;
+ _timers[i].smpTillCbRem -= _timerbase;
+ }
+ }
+ render = MIN(render, _timers[i].smpTillCb);
+ }
}
- }
-
- _ssgFlag = 0;
- unlock();
+ samplesLeft -= render;
- if (_finishedChannelsFlag == _updateChannelsFlag)
- reset();
-}
+ for (int i = 0; i < 2; i++) {
+ if (_timers[i].enabled && _timers[i].cb) {
+ _timers[i].smpTillCb -= render;
+ }
+ }
-void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) {
- if (!_playing)
- return;
+ nextTick(tmp, render);
- for (int i = 0; i < _numChan ; i++) {
- if (_channels[i]->_updateEnvelopes) {
- _channels[i]->_updateEnvelopes = false;
- _channels[i]->updateEnv();
- }
-
- for (uint32 ii = 0; ii < bufferSize ; ii++)
- _channels[i]->generateOutput(buffer[ii * 2],
- buffer[ii * 2 + 1], &_channels[i]->_feedbuf[2], _channels[i]->_feedbuf);
- }
+ if (_ssg)
+ _ssg->nextTick(tmp, render);
+ if (_prc)
+ _prc->nextTick(tmp, render);
- for (int i = 0; i < _numSSG ; i++) {
- if (_ssgChannels[i]->_updateEnvelopes) {
- _ssgChannels[i]->_updateEnvelopes = false;
- _ssgChannels[i]->updateEnv();
+ for (int i = 0; i < render; ++i) {
+ int32 l = CLIP<int32>(tmp[i << 1], -32767, 32767);
+ buffer[i << 1] = (int16) l;
+ int32 r = CLIP<int32>(tmp[(i << 1) + 1], -32767, 32767);
+ buffer[(i << 1) + 1] = (int16) r;
}
-
- for (uint32 ii = 0; ii < bufferSize ; ii++)
- _ssgChannels[i]->generateOutput(buffer[ii * 2],
- buffer[ii * 2 + 1], &_ssgChannels[i]->_feedbuf[2], _ssgChannels[i]->_feedbuf);
+
+ buffer += (render << 1);
+ tmp += (render << 1);
}
+
+ delete [] tmpStart;
+ return numSamples;
}
-void TownsPC98_OpnDriver::generateTables() {
+void TownsPC98_OpnCore::generateTables() {
delete [] _oprRates;
_oprRates = new uint8[128];
memset(_oprRates, 0x90, 32);
@@ -2641,7 +3241,7 @@ void TownsPC98_OpnDriver::generateTables() {
delete [] _oprFrq;
_oprFrq = new uint32[0x1000];
for (uint32 i = 0; i < 0x1000; i++)
- _oprFrq[i] = (uint32)(_baserate * (double)(i << 11));
+ _oprFrq[i] = (uint32)(_baserate * (float)(i << 11));
delete [] _oprAttackDecay;
_oprAttackDecay = new uint8[152];
@@ -2675,22 +3275,416 @@ void TownsPC98_OpnDriver::generateTables() {
uint8 *dtt = new uint8[128];
memset(dtt, 0, 36);
memset(dtt + 36, 1, 8);
- memcpy(dtt + 44, _drvTables + 144, 84);
+ memcpy(dtt + 44, _detSrc, 84);
delete [] _oprDetune;
_oprDetune = new int32[256];
for (int i = 0; i < 128; i++) {
- _oprDetune[i] = (int32) ((double)dtt[i] * _baserate * 64.0);
+ _oprDetune[i] = (int32) ((float)dtt[i] * _baserate * 64.0);
_oprDetune[i + 128] = -_oprDetune[i];
}
delete [] dtt;
}
-void TownsPC98_OpnDriver::setTempo(uint8 tempo) {
- _tempo = tempo;
- _samplesPerCallback = getRate() / _tempo;
- _samplesPerCallbackRemainder = getRate() % _tempo;
+void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) {
+ if (!_ready)
+ return;
+
+ for (int i = 0; i < _numChan; i++) {
+ TownsPC98_OpnOperator **o = _chanInternal[i].opr;
+
+ if (_chanInternal[i].updateEnvelopeParameters) {
+ _chanInternal[i].updateEnvelopeParameters = false;
+ for (int ii = 0; ii < 4 ; ii++)
+ o[ii]->updatePhaseIncrement();
+ }
+
+ for (uint32 ii = 0; ii < bufferSize ; ii++) {
+ int32 phbuf1, phbuf2, output;
+ phbuf1 = phbuf2 = output = 0;
+
+ int32 *leftSample = &buffer[ii * 2];
+ int32 *rightSample = &buffer[ii * 2 + 1];
+ int32 *del = &_chanInternal[i].feedbuf[2];
+ int32 *feed = _chanInternal[i].feedbuf;
+
+ switch (_chanInternal[i].algorithm) {
+ case 0:
+ o[0]->generateOutput(0, feed, phbuf1);
+ o[2]->generateOutput(*del, 0, phbuf2);
+ *del = 0;
+ o[1]->generateOutput(phbuf1, 0, *del);
+ o[3]->generateOutput(phbuf2, 0, output);
+ break;
+ case 1:
+ o[0]->generateOutput(0, feed, phbuf1);
+ o[2]->generateOutput(*del, 0, phbuf2);
+ o[1]->generateOutput(0, 0, phbuf1);
+ o[3]->generateOutput(phbuf2, 0, output);
+ *del = phbuf1;
+ break;
+ case 2:
+ o[0]->generateOutput(0, feed, phbuf2);
+ o[2]->generateOutput(*del, 0, phbuf2);
+ o[1]->generateOutput(0, 0, phbuf1);
+ o[3]->generateOutput(phbuf2, 0, output);
+ *del = phbuf1;
+ break;
+ case 3:
+ o[0]->generateOutput(0, feed, phbuf2);
+ o[2]->generateOutput(0, 0, *del);
+ o[1]->generateOutput(phbuf2, 0, phbuf1);
+ o[3]->generateOutput(*del, 0, output);
+ *del = phbuf1;
+ break;
+ case 4:
+ o[0]->generateOutput(0, feed, phbuf1);
+ o[2]->generateOutput(0, 0, phbuf2);
+ o[1]->generateOutput(phbuf1, 0, output);
+ o[3]->generateOutput(phbuf2, 0, output);
+ *del = 0;
+ break;
+ case 5:
+ o[0]->generateOutput(0, feed, phbuf1);
+ o[2]->generateOutput(*del, 0, output);
+ o[1]->generateOutput(phbuf1, 0, output);
+ o[3]->generateOutput(phbuf1, 0, output);
+ *del = phbuf1;
+ break;
+ case 6:
+ o[0]->generateOutput(0, feed, phbuf1);
+ o[2]->generateOutput(0, 0, output);
+ o[1]->generateOutput(phbuf1, 0, output);
+ o[3]->generateOutput(0, 0, output);
+ *del = 0;
+ break;
+ case 7:
+ o[0]->generateOutput(0, feed, output);
+ o[2]->generateOutput(0, 0, output);
+ o[1]->generateOutput(0, 0, output);
+ o[3]->generateOutput(0, 0, output);
+ *del = 0;
+ break;
+ };
+
+ int32 finOut = ((output * 7) / 2);
+
+ if (_chanInternal[i].enableLeft)
+ *leftSample += finOut;
+
+ if (_chanInternal[i].enableRight)
+ *rightSample += finOut;
+ }
+ }
+}
+
+TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : TownsPC98_OpnCore(mixer, type),
+ _channels(0), _ssgChannels(0), _sfxChannels(0), _rhythmChannel(0),
+ _trackPtr(0), _sfxData(0), _sfxOffs(0), _ssgPatches(0),
+
+ _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 108), _opnFreqTableSSG(_drvTables + 132),
+ _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 84)),
+
+ _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0),
+ _updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0),
+ _updateRhythmFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedRhythmFlag(0),
+ _updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0),
+
+ _musicTickCounter(0),
+
+ _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) {
+}
+
+TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
+ if (_channels) {
+ for (int i = 0; i < _numChan; i++)
+ delete _channels[i];
+ delete [] _channels;
+ }
+
+ if (_ssgChannels) {
+ for (int i = 0; i < _numSSG; i++)
+ delete _ssgChannels[i];
+ delete [] _ssgChannels;
+ }
+
+ if (_sfxChannels) {
+ for (int i = 0; i < 2; i++)
+ delete _sfxChannels[i];
+ delete [] _sfxChannels;
+ }
+
+ if (_rhythmChannel)
+ delete _rhythmChannel;
+
+ delete [] _ssgPatches;
+}
+
+bool TownsPC98_OpnDriver::init() {
+ if (_ready) {
+ reset();
+ return true;
+ }
+
+ TownsPC98_OpnCore::init();
+
+ _channels = new TownsPC98_OpnChannel*[_numChan];
+ for (int i = 0; i < _numChan; i++) {
+ int ii = i * 6;
+ _channels[i] = new TownsPC98_OpnChannel(this, _drvTables[ii], _drvTables[ii + 1],
+ _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
+ _channels[i]->init();
+ }
+
+ if (_numSSG) {
+ _ssgPatches = new uint8[256];
+ memcpy(_ssgPatches, _drvTables + 156, 256);
+
+ _ssgChannels = new TownsPC98_OpnChannelSSG*[_numSSG];
+ for (int i = 0; i < _numSSG; i++) {
+ int ii = i * 6;
+ _ssgChannels[i] = new TownsPC98_OpnChannelSSG(this, _drvTables[ii], _drvTables[ii + 1],
+ _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
+ _ssgChannels[i]->init();
+ }
+
+ _sfxChannels = new TownsPC98_OpnSfxChannel*[2];
+ for (int i = 0; i < 2; i++) {
+ int ii = (i + 1) * 6;
+ _sfxChannels[i] = new TownsPC98_OpnSfxChannel(this, _drvTables[ii], _drvTables[ii + 1],
+ _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
+ _sfxChannels[i]->init();
+ }
+ }
+
+ if (_hasPercussion) {
+ _rhythmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1);
+ _rhythmChannel->init();
+ }
+
+ setMusicTempo(84);
+ setSfxTempo(654);
+
+ _ready = true;
+
+ return true;
+}
+
+void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) {
+ if (!_ready) {
+ warning("TownsPC98_OpnDriver: Driver must be initialized before loading data");
+ return;
+ }
+
+ if (!data) {
+ warning("TownsPC98_OpnDriver: Invalid music file data");
+ return;
+ }
+
+ reset();
+
+ lock();
+
+ uint8 *src_a = _trackPtr = _musicBuffer = data;
+
+ for (uint8 i = 0; i < 3; i++) {
+ _channels[i]->loadData(data + READ_LE_UINT16(src_a));
+ src_a += 2;
+ }
+
+ for (int i = 0; i < _numSSG; i++) {
+ _ssgChannels[i]->loadData(data + READ_LE_UINT16(src_a));
+ src_a += 2;
+ }
+
+ for (uint8 i = 3; i < _numChan; i++) {
+ _channels[i]->loadData(data + READ_LE_UINT16(src_a));
+ src_a += 2;
+ }
+
+ if (_hasPercussion) {
+ _rhythmChannel->loadData(data + READ_LE_UINT16(src_a));
+ src_a += 2;
+ }
+
+ toggleRegProtection(false);
+
+ _patches = src_a + 4;
+ _finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0;
+
+ _musicPlaying = (loadPaused ? false : true);
+
+ unlock();
+}
+
+void TownsPC98_OpnDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
+ if (!_ready) {
+ warning("TownsPC98_OpnDriver: Driver must be initialized before loading data");
+ return;
+ }
+
+ if (!_sfxChannels) {
+ warning("TownsPC98_OpnDriver: Sound effects not supported by this configuration");
+ return;
+ }
+
+ if (!data) {
+ warning("TownsPC98_OpnDriver: Invalid sound effects file data");
+ return;
+ }
+
+ lock();
+ _sfxData = _sfxBuffer = data;
+ _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);
+ _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);
+ _sfxPlaying = true;
+ _finishedSfxFlag = 0;
+ unlock();
+}
+
+void TownsPC98_OpnDriver::reset() {
+ lock();
+
+ TownsPC98_OpnCore::reset();
+
+ for (int i = 0; i < _numChan; i++)
+ _channels[i]->reset();
+ for (int i = 0; i < _numSSG; i++)
+ _ssgChannels[i]->reset();
+
+ if (_numSSG) {
+ for (int i = 0; i < 2; i++)
+ _sfxChannels[i]->reset();
+
+ memcpy(_ssgPatches, _drvTables + 156, 256);
+ }
+
+ if (_rhythmChannel)
+ _rhythmChannel->reset();
+
+ _musicPlaying = false;
+ _sfxPlaying = false;
+ _fading = false;
+ _looping = 0;
+ _musicTickCounter = 0;
+ _sfxData = 0;
+
+ unlock();
+}
+
+void TownsPC98_OpnDriver::fadeStep() {
+ if (!_musicPlaying)
+ return;
+
+ lock();
+
+ for (int j = 0; j < _numChan; j++) {
+ if (_updateChannelsFlag & _channels[j]->_idFlag)
+ _channels[j]->fadeStep();
+ }
+
+ for (int j = 0; j < _numSSG; j++) {
+ if (_updateSSGFlag & _ssgChannels[j]->_idFlag)
+ _ssgChannels[j]->fadeStep();
+ }
+
+ if (!_fading) {
+ _fading = 19;
+ if (_hasPercussion) {
+ if (_updateRhythmFlag & _rhythmChannel->_idFlag)
+ _rhythmChannel->reset();
+ }
+ } else {
+ if (!--_fading)
+ reset();
+ }
+
+ unlock();
+}
+
+void TownsPC98_OpnDriver::timerCallbackB() {
+ lock();
+
+ _sfxOffs = 0;
+
+ if (_musicPlaying) {
+ _musicTickCounter++;
+
+ for (int i = 0; i < _numChan; i++) {
+ if (_updateChannelsFlag & _channels[i]->_idFlag) {
+ _channels[i]->processEvents();
+ _channels[i]->processFrequency();
+ }
+ }
+
+ for (int i = 0; i < _numSSG; i++) {
+ if (_updateSSGFlag & _ssgChannels[i]->_idFlag) {
+ _ssgChannels[i]->processEvents();
+ _ssgChannels[i]->processFrequency();
+ }
+ }
+
+ if (_hasPercussion)
+ if (_updateRhythmFlag & _rhythmChannel->_idFlag)
+ _rhythmChannel->processEvents();
+ }
+
+ toggleRegProtection(false);
+
+ if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag)
+ _musicPlaying = false;
+
+ unlock();
+}
+
+void TownsPC98_OpnDriver::timerCallbackA() {
+ lock();
+
+ if (_sfxChannels && _sfxPlaying) {
+ if (_sfxData)
+ startSoundEffect();
+
+ _sfxOffs = 3;
+ _trackPtr = _sfxBuffer;
+
+ for (int i = 0; i < 2; i++) {
+ if (_updateSfxFlag & _sfxChannels[i]->_idFlag) {
+ _sfxChannels[i]->processEvents();
+ _sfxChannels[i]->processFrequency();
+ }
+ }
+
+ _trackPtr = _musicBuffer;
+ }
+
+ if (_finishedSfxFlag == _updateSfxFlag)
+ _sfxPlaying = false;
+
+ unlock();
+}
+
+void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) {
+ writeReg(0, 0x26, tempo);
+ writeReg(0, 0x27, 0x33);
+}
+
+void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) {
+ writeReg(0, 0x24, tempo & 0xff);
+ writeReg(0, 0x25, tempo >> 8);
+ writeReg(0, 0x27, 0x33);
+}
+
+void TownsPC98_OpnDriver::startSoundEffect() {
+ for (int i = 0; i < 2; i++) {
+ if (_sfxOffsets[i]) {
+ _ssgChannels[i + 1]->protect();
+ _sfxChannels[i]->reset();
+ _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]);
+ }
+ }
+
+ _sfxData = 0;
}
const uint8 TownsPC98_OpnDriver::_drvTables[] = {
@@ -2706,55 +3700,63 @@ const uint8 TownsPC98_OpnDriver::_drvTables[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05,
0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02,
- // fmt level presets
+ // fmt level presets
0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38,
0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18,
0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90,
-
+
// carriers
0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F,
- // frequencies
- 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02,
- 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03,
- 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04,
- 0x00, 0x00, 0x00, 0x00,
-
- // unused
- 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-
- // detune
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
- 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
- 0x10, 0x10, 0x10, 0x10, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05,
- 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a,
- 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14,
- 0x16, 0x16, 0x16, 0x16,
-
- // pc98 level presets
+ // pc98 level presets
0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25,
0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10,
- 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90
-};
+ 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90,
-const uint32 TownsPC98_OpnDriver::_adtStat[] = {
- 0x00010001, 0x00010001, 0x00010001, 0x01010001,
- 0x00010101, 0x00010101, 0x00010101, 0x01010101,
- 0x01010101, 0x01010101, 0x01010102, 0x01010102,
- 0x01020102, 0x01020102, 0x01020202, 0x01020202,
- 0x02020202, 0x02020202, 0x02020204, 0x02020204,
- 0x02040204, 0x02040204, 0x02040404, 0x02040404,
- 0x04040404, 0x04040404, 0x04040408, 0x04040408,
- 0x04080408, 0x04080408, 0x04080808, 0x04080808,
- 0x08080808, 0x08080808, 0x10101010, 0x10101010
+ // frequencies
+ 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02,
+ 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03,
+ 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04,
+
+ // ssg frequencies
+ 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C,
+ 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09,
+ 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07,
+
+ // ssg patch data
+ 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00,
+ 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
+ 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
+ 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
+ 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00,
+ 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
+ 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00,
+ 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00,
+ 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+
+ 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00,
+ 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00,
+ 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00
};
SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer)
@@ -2916,7 +3918,8 @@ void SoundTowns::playSoundEffect(uint8 track) {
}
playbackBufferSize -= 0x20;
- uint32 outputRate = uint32(11025 * semitoneAndSampleRate_to_sampleStep(note, sfxRootNoteOffs, sfxRate, 11025, 0x2000));
+
+ uint32 outputRate = uint32(11025 * calculatePhaseStep(note, sfxRootNoteOffs, sfxRate, 11025, 0x2000));
_currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize,
outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
@@ -2995,7 +3998,7 @@ void SoundTowns::onTimer(void *data) {
music->_parser->onTimer();
}
-float SoundTowns::semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey,
+float SoundTowns::calculatePhaseStep(int8 semiTone, int8 semiToneRootkey,
uint32 sampleRate, uint32 outputRate, int32 pitchWheel) {
if (semiTone < 0)
semiTone = 0;
@@ -3050,18 +4053,18 @@ bool SoundPC98::init() {
void SoundPC98::playTrack(uint8 track) {
if (--track >= 56)
track -= 55;
-
+
if (track == _lastTrack && _musicEnabled)
return;
- haltTrack();
+ beginFadeOut();
char musicfile[13];
sprintf(musicfile, fileListEntry(0), track);
delete[] _musicTrackData;
_musicTrackData = _vm->resource()->fileData(musicfile, 0);
if (_musicEnabled)
- _driver->loadData(_musicTrackData);
+ _driver->loadMusicData(_musicTrackData);
_lastTrack = track;
}
@@ -3074,29 +4077,42 @@ void SoundPC98::haltTrack() {
}
void SoundPC98::beginFadeOut() {
- _driver->fadeOut();
+ if (!_driver->musicPlaying())
+ return;
+
+ for (int i = 0; i < 20; i++) {
+ _driver->fadeStep();
+ _vm->delay(32);
+ }
haltTrack();
}
-void SoundPC98::playSoundEffect(uint8) {
- /// TODO ///
+void SoundPC98::playSoundEffect(uint8 track) {
+ if (!_sfxTrackData)
+ return;
+
+ // This has been disabled for now since I don't know
+ // how to make up the correct track number. It probably
+ // needs a map.
+ //_driver->loadSoundEffectData(_sfxTrackData, track);
}
// KYRA 2
SoundTownsPC98_v2::SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) :
- Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false) {
+ Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false) {
}
SoundTownsPC98_v2::~SoundTownsPC98_v2() {
delete[] _musicTrackData;
+ delete[] _sfxTrackData;
delete _driver;
}
bool SoundTownsPC98_v2::init() {
- _driver = new TownsPC98_OpnDriver(_mixer, /*_vm->gameFlags().platform == Common::kPlatformPC98 ?
- TownsPC98_OpnDriver::OD_TYPE86 :*/ TownsPC98_OpnDriver::OD_TOWNS);
+ _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
+ TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
_useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
_vm->checkCD();
// FIXME: While checking for 'track1.XXX(X)' looks like
@@ -3106,13 +4122,19 @@ bool SoundTownsPC98_v2::init() {
// this misses the possibility that we play the tracks
// right off CD. So we should find another way to
// check if we have access to CD audio.
+ Resource *res = _vm->resource();
if (_musicEnabled &&
- (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") ||
- Common::File::exists("track1.flac") || Common::File::exists("track1.fla")))
+ (res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla")))
_musicEnabled = 2;
+
return _driver->init();
}
+void SoundTownsPC98_v2::loadSoundFile(Common::String file) {
+ delete [] _sfxTrackData;
+ _sfxTrackData = _vm->resource()->fileData(file.c_str(), 0);
+}
+
void SoundTownsPC98_v2::process() {
AudioCD.updateCD();
}
@@ -3138,9 +4160,9 @@ void SoundTownsPC98_v2::playTrack(uint8 track) {
char musicfile[13];
sprintf(musicfile, fileListEntry(0), track);
delete[] _musicTrackData;
-
+
_musicTrackData = _vm->resource()->fileData(musicfile, 0);
- _driver->loadData(_musicTrackData, true);
+ _driver->loadMusicData(_musicTrackData, true);
if (_musicEnabled == 2 && trackNum != -1) {
AudioCD.play(trackNum+1, _driver->looping() ? -1 : 1, 0, 0);
@@ -3160,7 +4182,14 @@ void SoundTownsPC98_v2::haltTrack() {
}
void SoundTownsPC98_v2::beginFadeOut() {
- _driver->fadeOut();
+ if (!_driver->musicPlaying())
+ return;
+
+ for (int i = 0; i < 20; i++) {
+ _driver->fadeStep();
+ _vm->delay(32);
+ }
+
haltTrack();
}
@@ -3221,7 +4250,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) {
sfx[i] = cmd;
}
- uint32 outputRate = uint32(11025 * SoundTowns::semitoneAndSampleRate_to_sampleStep(0x3c, 0x3c, sfxRate, 11025, 0x2000));
+ uint32 outputRate = uint32(11025 * SoundTowns::calculatePhaseStep(0x3c, 0x3c, sfxRate, 11025, 0x2000));
_currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate,
Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
@@ -3233,16 +4262,163 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) {
}
void SoundTownsPC98_v2::playSoundEffect(uint8 track) {
- if (!_useFmSfx)
+ if (!_useFmSfx || !_sfxTrackData)
return;
- uint8 *sd = _vm->resource()->fileData("sound.dat", 0);
+ _driver->loadSoundEffectData(_sfxTrackData, track);
+}
+
+// static resources
+
+const uint32 TownsPC98_OpnCore::_adtStat[] = {
+ 0x00010001, 0x00010001, 0x00010001, 0x01010001,
+ 0x00010101, 0x00010101, 0x00010101, 0x01010101,
+ 0x01010101, 0x01010101, 0x01010102, 0x01010102,
+ 0x01020102, 0x01020102, 0x01020202, 0x01020202,
+ 0x02020202, 0x02020202, 0x02020204, 0x02020204,
+ 0x02040204, 0x02040204, 0x02040404, 0x02040404,
+ 0x04040404, 0x04040404, 0x04040408, 0x04040408,
+ 0x04080408, 0x04080408, 0x04080808, 0x04080808,
+ 0x08080808, 0x08080808, 0x10101010, 0x10101010
+};
+const uint8 TownsPC98_OpnCore::_detSrc[] = {
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
+ 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x10, 0x10, 0x10, 0x10, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05,
+ 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14,
+ 0x16, 0x16, 0x16, 0x16
+};
- //TODO
+const int TownsPC98_OpnCore::_ssgTables[] = {
+ 0x01202A, 0x0092D2, 0x006B42, 0x0053CB, 0x003DF8, 0x003053, 0x0022DA, 0x001A8C,
+ 0x00129B, 0x000DC1, 0x000963, 0x0006C9, 0x000463, 0x0002FA, 0x0001B6, 0x0000FB,
+ 0x0193B6, 0x01202A, 0x00CDB1, 0x0092D2, 0x007D7D, 0x006B42, 0x005ECD, 0x0053CB,
+ 0x00480F, 0x003DF8, 0x0036B9, 0x003053, 0x00290A, 0x0022DA, 0x001E6B, 0x001A8C,
+ 0x001639, 0x00129B, 0x000FFF, 0x000DC1, 0x000B5D, 0x000963, 0x0007FB, 0x0006C9,
+ 0x000575, 0x000463, 0x00039D, 0x0002FA, 0x000242, 0x0001B6, 0x00014C, 0x0000FB
+};
- delete [] sd;
-}
+const uint8 TownsPC98_OpnCore::_percussionData[] = {
+ 0,24,1,192,1,216,2,128,4,88,23,64,27,152,1,128,29,24,2,128,31,152,0,128,136,128,128,128,0,136,97,103,153,139,34,163,72,195,27,69,1,154,137,35,8,51,169,122,164,75,133,203,81,146,168,121,185,68,202,8,33,237,49,177,12,133,140,17,160,42,161,10,0,137,176, 57,
+ 233,41,160,136,235,65,177,137,128,26,164,28,3,157,51,137,1,152,113,161,40,146,115,192,56,5,169,66,161,56,1,50,145,59,39,168,97,1,160,57,7,153,50,153,32,2,25,129,32,20,186,66,129,24,153,164,142,130,169,153,26,242,138,217,9,128,204,58,209,172,40, 176, 141,
+ 128,155,144,203,139,0,235,9,177,172,0,185,168,138,25,240,59,211,139,19,176,90,160,17,26,132,41,1,5,25,3,50,144,115,147,42,39,152,41,3,56,193,105,130,155,66,200,26,19,218,154,49,201,171,138,176,251,139,185,172,136,189,139,145,207,41,160,171,152, 186, 139,
+ 186,141,128,218,171,51,217,170,56,163,12,4,155,81,147,42,37,152,32,54,136,49,50,48,37,32,69,0,17,50,50,83,2,16,68,20,8,66,4,154,84,145,24,33,24,32,17,18,145,32,22,168,49,163,1,33,50,184,115,129,25,66,1,24,67,2,80,35,40,53,2,65,51,19,67,37,0,52,35,49, 37,
+ 34,49,37,17,52,17,35,35,35,34,32,49,33,152,34,145,24,24,128,138,128,184,9,177,171,168,185,155,152,172,155,186,172,185,172,155,186,173,153,202,187,185,202,170,171,202,186,169,170,170,171,139,154,171,153,154,169,10,168,154,128,168,154,0,153, 152, 136, 137,
+ 128,153,0,152,8,128,137,0,136,136,8,9,8,9,8,24,153,128,136,153,144,0,161,138,1,169,136,128,160,168,152,153,138,137,154,153,153,154,153,170,168,170,185,168,169,154,169,171,153,169,170,153,152,154,153,137,169,137,136,144,152,144,128,128,144,129,129, 0, 33,
+ 0,17,17,17,33,33,18,18,34,34,34,34,34,34,35,19,35,19,35,35,18,19,18,35,18,33,0,8,8,8,8,8,8,8,160,205,65,176,171,203,16,240,95,242,120,145,156,66,177,26,19,153,9,35,35,239,56,132,138,154,50,145,203,25,32,20,237,24,130,138,160,27,39,173,50,203,64,145, 139,
+ 18,168,48,146,171,65,18,176,12,52,128,25,5,57,240,104,161,25,129,18,188,114,160,26,36,200,154,18,1,128,186,73,162,173,32,184,25,144,137,234,8,154,32,160,158,18,187,81,2,235,41,36,144,154,17,67,128,33,160,114,146,26,37,33,232,41,130,41,178,29,50, 251, 24,
+ 1,153,138,160,76,179,155,11,0,38,252,41,146,41,178,27,193,43,39,170,136,17,129,8,49,233,48,129,11,6,26,130,136,128,64,1,248,105,145,9,16,144,140,5,25,168,16,186,48,5,171,217,57,134,171,8,34,188,20,203,41,6,155,161,89,164,140,2,136,51,202,41,131, 56, 144,
+ 8,97,144,146,13,69,200,42,130,25,152,57,6,220,88,177,26,148,9,168,8,67,192,156,65,145,137,10,4,154,18,157,67,160,154,1,50,188,82,170,82,185,49,220,97,144,10,8,16,145,9,136,18,202,51,184,141,114,179,139,24,19,8,250,121,160,40,160,10,18,152,168,42,35, 216,
+ 187,120,145,18,156,203,84,144,9,144,26,66,161,13,1,128,17,154,18,142,6,154,65,192,29,35,186,64,192,24,9,146,56,185,16,248,121,176,40,129,136,171,96,147,140,50,203,64,144,41,128,161,187,71,200,24,129,24,217,56,20,220,24,4,169,9,1,33,201,26,134,141,51,201,
+ 25,16,33,235,32,144,33,153,169,99,160,11,3,136,58,210,33,203,48,163,17,219,128,140,38,8,184,141,50,131,159,33,128,153,25,18,153,88,242,43,3,9,136,157,53,202,40,145,25,2,204,105,146,156,66,152,8,153,33,128,129,136,153,50,186,55,188,51,249,64,178, 27, 128,
+ 48,177,156,18,35,175,51,189,32,51,234,155,69,184,26,2,152,9,17,136,144,137,50,235,115,216,24,2,170,67,187,49,129,155,4,27,129,56,232,43,39,203,40,3,154,169,66,184,114,224,25,2,9,128,11,35,155,18,11,202,84,169,26,5,154,8,160,98,185,17,187,50, 23, 188, 33,
+ 1,139,4,154,90,147,12,3,43,2,170,171,103,193,28,132,137,8,129,24,170,50,201,42,35,202,169,52,201,33,218,40,39,203,0,40,147,29,163,139,83,185,1,4,159,34,160,12,21,155,40,129,137,58,151,13,2,136,144,16,153,40,17,131,207,51,144,140,4,154,17,146,170,73, 163,
+ 44,164,12,152,37,203,17,128,144,139,23,154,128,138,38,216,41,1,0,233,73,131,171,49,136,9,164,46,3,171,32,0,145,157,38,187,64,176,58,134,155,18,136,217,64,1,200,140,38,153,170,66,161,8,169,65,185,98,200,41,3,155,144,58,23,187,1,145,40,147,189,32, 68, 249,
+ 1,112,255,199,195,19,108,76,187,247,247,183,40,168,212,245,199,227,68,45,59,10,145,177,198,24,130,76,26,193,180,129,0,162,42,160,199,162,0,16,152,137,132,168,195,130,162,181,227,163,161,179,211,180,179,164,128,162,161,194,164,179,40,153,195,213,146, 178,
+ 147,176,50,186,161,196,151,58,16,28,162,160,131,122,155,33,241,146,128,40,26,128,154,36,170,89,59,9,24,144,77,161,8,177,112,139,33,232,148,24,41,61,9,26,162,32,30,58,153,32,59,73,59,11,79,137,57,9,49,30,24,153,131,25,106,61,153,73,28,56,27, 41, 137, 148,
+ 76,43,74,58,13,161,3,171,149,32,77,10,74,42,168,16,0,123,138,129,162,178,225,50,140,161,0,147,10,129,41,244,210,165,1,152,24,162,184,166,32,144,59,216,132,177,8,145,67,143,146,160,183,162,130,24,192,32,225,146,144,33,44,73,30,129,137,32,76, 152, 25, 161,
+ 2,154,32,177,132,232,2,136,210,128,149,177,32,58,27,168,225,133,8,44,107,136,25,136,17,26,58,46,16,11,145,17,144,79,136,144,136,145,152,33,31,162,130,200,82,153,74,137,147,26,0,13,133,170,149,16,192,0,178,0,128,152,182,150,9,16,9,137,33,59,63,10,152, 32,
+ 179,192,5,154,228,182,145,130,144,42,128,242,2,136,41,168,17,76,57,31,129,136,17,47,8,41,138,32,138,123,59,58,10,136,161,4,46,25,145,136,129,25,56,28,91,41,154,108,9,16,44,24,137,48,15,0,194,162,41,194,56,241,163,146,0,139,7,186,150,129,152,1,208,33,176,
+ 136,164,163,185,7,138,130,242,162,163,177,88,136,184,166,146,0,25,25,177,199,146,16,136,9,145,178,178,0,147,138,229,18,152,25,144,163,246,162,129,129,184,5,152,178,145,148,136,146,95,152,128,144,33,170,81,11,40,202,131,0,243,24,1,11,148,42, 24, 163, 140,
+ 120,9,76,58,153,145,56,30,72,46,42,9,8,57,91,76,59,26,160,129,41,76,10,57,192,163,129,16,225,2,27,40,200,48,91,226,40,145,43,177,177,182,196,145,33,184,165,17,192,163,194,129,211,128,162,197,129,0,136,211,146,8,162,144,0,167,160,1,176,150,137,1, 24, 243,
+ 0,129,145,25,123,169,130,168,132,41,63,42,136,137,120,26,136,8,24,89,29,58,177,193,147,1,26,162,176,167,180,8,49,28,29,178,162,88,43,42,57,43,61,8,29,129,128,128,123,137,24,243,16,136,16,46,0,169,149,128,1,60,153,72,154,90,25,25,25,8,91,73,12,16,137,144,
+ 72,11,8,167,128,129,9,138,166,193,147,162,123,137,145,1,162,26,1,219,147,129,210,147,243,1,243,16,144,145,160,131,200,4,59,75,57,218,2,178,77,24,60,11,147,10,50,141,64,27,185,122,161,41,128,90,136,24,46,16,139,16,24,28,124,9,41,8,26,121,10,42,40,139,129,
+ 0,201,135,137,56,176,176,35,215,145,1,26,145,144,160,135,138,1,177,146,146,161,65,242,136,164,177,1,1,186,151,208,148,129,10,32,241,145,163,178,17,168,136,151,168,2,148,185,133,176,130,129,154,163,215,0,146,136,40,211,161,131,171,81,144,170, 21, 184, 56,
+ 195,168,133,177,91,16,187,5,145,153,66,172,18,177,42,120,138,27,134,26,106,42,138,146,184,66,75,46,41,168,0,145,57,91,75,27,24,27,48,169,40,122,9,109,10,8,177,146,16,74,30,129,160,162,146,41,124,138,24,145,152,3,1,14,3,139,1,192,161,151,177,122,8, 10, 0,
+ 176,130,129,27,88,225,0,2,154,129,129,193,49,203,81,153,226,33,0,30,0,176,179,18,9,96,156,162,148,160,129,2,29,195,128,0,56,156,20,232,129,128,32,10,144,74,183,9,145,162,1,162,138,23,171,1,164,224,34,43,43,177,200,135,161,91,57,154,177,148, 145, 146, 58,
+ 108,136,170,35,208,177,34,128,44,129,155,151,243,16,1,154,72,193,144,18,11,122,160,153,5,192,24,130,184,132,226,0,128,153,131,181,136,65,154,128,17,170,39,28,59,144,168,80,25,47,24,26,144,32,47,41,153,161,148,8,92,9,9,129,144,33,26,47,24,137,108, 25, 10,
+ 17,10,73,75,47,24,184,48,8,45,57,138,136,150,10,48,139,136,35,203,121,8,27,179,161,106,0,29,16,176,179,3,185,19,227,41,145,168,61,197,177,20,10,57,42,250,147,196,16,41,138,24,195,208,135,137,0,145,160,2,210,146,195,177,132,136,153,167,210,146,162, 40, 8,
+ 138,148,227,145,17,137,40,169,179,130,242,2,196,9,146,145,169,167,146,130,137,136,51,220,17,163,28,74,10,76,40,140,5,137,43,18,12,107,137,40,8,201,50,0,143,3,138,161,134,138,104,169,16,162,160,121,25,28,129,152,32,56,14,16,184,146,3,46,25, 176, 129, 179,
+ 193,17,130,202,135,8,57,25,154,148,184,120,9,153,211,165,24,128,26,17,242,161,18,185,81,42,11,17,12,25,181,137,66,42,47,41,184,166,129,24,91,27,136,196,0,0,74,28,178,161,149,160,32,8,225,32,128,59,8,169,50,139,47,72,186,16,132,9,122,9,160,146,144,89,153,
+ 10,149,178,0,121,11,146,152,162,48,13,123,177,24,0,106,27,9,144,132,12,17,0,168,0,181,56,169,129,242,195,129,17,154,64,161,244,16,137,24,144,144,164,129,75,42,176,149,9,179,148,203,4,166,136,163,128,227,163,8,57,11,30,165,0,74,59,62,9,208,131,144,40, 76,
+ 26,27,196,129,1,25,43,49,174,67,153,136,106,152,41,25,28,2,43,44,104,45,59,8,43,128,144,120,25,12,17,152,9,130,155,151,145,74,40,13,48,192,58,90,43,43,177,146,49,31,75,24,217,131,0,76,26,152,149,161,24,74,154,193,166,145,32,27,161,164,176,135,152,24,193,
+ 162,146,164,58,227,193,148,161,128,18,234,130,180,145,2,200,1,163,186,98,184,129,149,153,49,42,186,151,242,129,1,43,8,177,212,165,8,40,137,24,8,144,90,9,25,48,44,46,24,138,40,144,108,58,27,128,181,128,80,29,42,152,162,130,25,106,136,11,148,8,144,128,136,
+ 112,139,80,153,24,136,129,46,0,60,129,208,1,3,13,57,168,144,1,242,17,9,26,2,185,27,55,140,73,137,179,16,192,3,145,143,33,9,171,135,160,17,137,10,151,168,3,178,44,17,208,144,167,0,40,155,16,167,152,18,144,26,160,199,1,136,91,136,160,178,150,161,1,10, 181,
+ 145,161,1,145,161,198,2,9,90,137,177,160,150,40,29,129,144,145,162,57,77,169,16,148,42,42,40,141,34,170,121,154,210,131,162,107,8,9,160,195,40,73,139,18,224,162,34,139,0,244,178,163,24,26,146,194,166,49,29,42,137,130,192,16,93,128,154,19,59, 11, 122, 11,
+ 146,177,120,42,26,43,164,152,17,60,63,137,128,48,10,58,92,9,59,91,75,139,32,25,25,61,74,28,177,40,130,74,29,73,168,130,128,48,14,8,77,9,25,26,179,211,32,78,26,41,152,161,180,89,59,9,153,166,160,3,26,57,106,154,88,184,40,1,27,58,73,143,131,169,3,161, 184,
+ 122,152,16,181,145,129,17,15,129,193,147,145,192,33,193,162,183,163,136,178,129,178,197,2,41,216,131,168,163,181,226,163,178,1,33,187,166,212,129,1,27,24,162,184,151,8,16,160,144,181,210,72,168,128,32,42,25,40,142,5,185,88,58,11,58,177,32,129,63,42, 136,
+ 186,53,29,75,58,144,144,129,77,128,11,144,133,29,40,152,24,161,129,80,155,60,3,12,89,8,60,152,152,49,136,47,57,224,129,16,41,90,139,162,147,170,51,169,27,17,95,26,26,160,5,139,48,76,10,228,146,1,136,44,161,147,209,130,137,73,224,1,162,195,32,210,177,180,
+ 179,148,145,154,132,242,146,1,152,32,192,1,144,155,7,177,168,5,138,178,148,152,150,136,89,152,9,41,196,145,40,28,16,8,10,178,167,24,1,44,123,137,136,145,194,48,27,74,26,192,179,135,136,88,27,10,177,163,164,128,73,24,31,8,0,192,149,144,129,9,106, 41, 200,
+ 161,151,41,138,0,24,226,162,49,42,11,90,136,136,152,17,145,10,63,40,11,56,245,162,16,26,73,11,144,135,137,58,106,10,25,8,57,137,28,33,129,156,113,10,10,161,18,8,153,77,3,217,0,1,242,128,193,18,128,75,60,178,154,37,45,58,29,144,1,184,66,41,29, 8, 145, 10,
+ 194,33,148,170,107,89,139,128,163,178,16,63,59,176,144,151,129,42,74,10,129,192,2,128,154,97,192,0,177,128,178,183,16,16,155,149,145,184,84,138,8,192,161,20,225,0,130,138,165,0,28,148,153,18,209,128,88,153,89,152,9,17,9,29,130,43,122,153,24, 32, 202, 49,
+ 24,43,106,154,130,193,27,51,29,28,133,138,65,11,123,25,10,40,152,44,130,26,43,148,45,73,140,33,8,153,88,128,61,144,42,59,225,128,18,155,50,75,186,20,202,120,144,42,92,176,162,165,25,2,169,152,135,185,19,152,8,146,160,123,195,137,132,209,0,16, 11, 2, 242,
+ 146,164,152,73,193,136,130,178,1,136,169,23,169,128,164,242,129,178,129,32,138,180,167,153,132,8,138,2,209,4,138,1,128,138,92,136,44,129,136,162,33,63,40,141,2,160,144,106,137,64,155,17,129,60,30,146,26,17,28,48,46,169,51,154,91,137,41,26,32,143,18, 138,
+ 1,32,28,123,177,9,181,195,56,57,14,145,161,17,17,31,41,152,145,194,194,20,153,41,9,243,129,180,0,128,45,16,43,170,135,144,16,25,42,137,242,163,194,16,0,57,14,130,194,178,16,33,30,8,59,211,163,160,5,137,44,10,17,170,3,120,9,44,146,136,131,140, 91, 9, 171,
+ 7,161,32,73,13,8,161,40,106,11,25,129,59,0,49,31,42,28,40,11,0,81,176,61,32,138,25,178,241,148,136,106,8,136,128,177,90,8,155,96,176,9,18,217,132,129,10,81,156,40,178,161,36,169,76,147,203,150,0,10,146,200,147,149,128,144,148,154,182,24,0,137,11,134,211,
+ 24,136,129,145,209,33,8,43,163,243,88,41,13,0,160,145,33,31,32,185,145,4,155,17,32,47,161,128,73,160,44,56,176,75,74,12,35,141,104,137,9,89,152,58,56,44,41,30,41,40,157,48,128,154,88,41,42,8,14,3,184,59,120,152,9,56,10,128,41,57,227,186,52,152,62, 8, 56,
+ 242,0,58,8,156,34,243,128,24,176,51,169,58,183,192,146,164,177,18,170,7,177,208,132,161,24,136,27,147,243,128,133,10,24,161,161,178,214,17,160,25,16,161,137,165,192,48,27,72,58,218,133,162,26,72,27,10,197,178,49,138,89,56,142,1,24,11,0,44,105, 10, 25, 0,
+ 194,9,3,47,8,138,147,18,28,48,202,147,199,146,25,161,0,145,194,163,57,11,146,248,130,32,57,63,154,16,48,14,128,144,209,133,26,56,154,182,162,195,18,152,44,194,180,168,5,24,137,138,35,192,232,66,176,161,24,41,26,244,129,163,160,75,129,226,147,40, 145, 61,
+ 13,130,177,17,137,112,170,130,0,136,75,152,177,241,34,0,59,156,51,186,178,91,132,137,137,122,1,45,28,50,172,57,108,8,26,136,32,152,46,144,131,171,4,152,18,141,148,1,216,32,9,60,169,66,152,128,72,90,201,1,17,201,136,3,195,26,73,133,200,176, 150, 146, 169,
+ 24,33,178,184,151,73,11,28,72,44,153,82,153,17,42,57,78,153,8,160,0,1,123,11,19,171,195,18,59,31,129,10,162,2,58,96,142,130,26,75,128,176,17,180,123,9,90,137,211,145,32,26,76,43,145,130,12,90,41,27,58,160,160,128,178,7,76,59,0,203,180,147,33,62,10,0,243,
+ 129,146,73,29,145,144,0,26,56,153,185,83,8,76,27,166,161,193,146,131,224,145,165,161,40,168,149,162,226,2,136,138,163,131,211,0,59,146,218,148,1,192,16,16,58,248,88,144,177,136,1,58,45,9,195,197,147,48,29,10,0,162,176,64,122,9,10,17,9,153,56, 75, 27, 31,
+ 72,136,9,129,129,61,45,59,10,161,18,122,43,59,41,169,34,155,130,131,219,120,162,27,49,208,160,131,156,66,12,145,50,240,16,136,12,162,40,129,130,15,129,162,146,180,83,139,58,217,129,177,4,0,169,197,163,144,242,131,168,179,179,17,197,145,178,164, 128, 160,
+ 211,2,244,163,145,162,129,212,177,163,17,208,163,195,180,57,24,170,182,164,129,0,60,60,169,149,162,177,122,26,24,136,136,133,43,27,178,56,77,24,128,240,0,2,44,46,8,128,193,146,64,27,42,16,193,25,0,192,148,11,52,47,153,147,243,0,24,73,28,144, 161, 150, 9,
+ 8,73,170,2,162,25,27,147,167,131,29,1,168,200,165,16,91,137,8,162,176,35,41,31,24,169,50,168,58,123,144,48,128,13,73,169,144,16,57,123,44,200,163,56,153,80,10,176,146,57,94,8,152,131,9,168,125,26,145,177,132,137,41,60,26,144,243,32,192,34,60, 43, 26, 16,
+ 249,164,16,58,61,11,130,243,146,2,42,44,27,128,165,137,49,45,28,16,43,8,211,48,28,152,105,9,9,163,161,169,35,107,42,232,164,130,168,72,42,168,210,148,144,136,129,3,217,194,50,27,192,41,210,147,40,76,226,1,161,1,155,132,145,147,171,67,173,210,132,161,106,
+ 137,56,169,209,131,64,13,129,9,194,17,57,61,169,17,128,40,31,16,10,162,57,61,75,139,40,242,17,58,59,138,179,144,50,105,140,179,243,57,40,26,9,243,130,24,29,57,128,210,129,25,59,91,137,162,178,72,27,181,168,19,129,8,184,231,147,178,32,28,184,198,148, 144,
+ 1,26,128,16,192,2,26,144,244,129,0,16,10,197,177,181,1,41,9,178,165,211,129,25,145,137,210,147,152,210,163,132,194,17,91,169,145,181,130,9,89,137,152,178,4,128,9,63,160,128,106,8,25,43,10,32,47,26,123,152,24,40,25,27,18,186,35,158,64,42,216,33,25,58, 58,
+ 45,184,147,29,72,46,9,0,178,146,58,77,26,25,209,165,128,145,17,153,128,129,148,240,129,1,40,31,0,152,242,163,16,59,44,24,243,146,128,1,26,26,179,213,145,130,176,131,40,25,145,219,179,167,8,33,59,14,176,166,16,136,74,128,176,128,149,8,8,209,148,152,0, 72,
+ 153,161,178,35,62,75,154,163,153,19,62,170,133,179,136,89,12,129,164,144,3,47,58,193,177,148,0,61,43,10,129,17,41,61,43,25,8,126,26,25,137,145,34,44,45,129,216,179,1,90,25,137,32,227,8,16,9,170,49,31,32,29,128,145,148,75,25,75,153,162,192,35,12, 80, 136,
+ 176,8,194,24,1,176,21,154,145,80,251,130,2,30,9,8,130,145,128,98,27,26,129,136,162,15,33,168,59,65,177,77,141,1,128,168,113,10,137,178,163,146,132,74,153,224,164,33,184,19,184,228,161,17,91,152,25,146,152,44,121,9,160,145,17,25,28,93,128,152,2,25,27,161,
+ 210,129,146,45,179,227,163,162,9,40,193,148,179,57,107,140,196,32,25,57,47,136,210,130,24,40,28,152,210,182,145,40,8,129,184,147,147,140,163,166,160,34,45,144,194,161,134,41,46,152,162,162,3,44,58,75,209,162,144,57,129,47,152,130,59,16,248,129,17,26, 57,
+ 9,29,167,2,60,42,138,136,209,130,90,42,42,176,146,178,120,28,8,160,145,16,33,31,1,8,160,129,128,242,164,32,152,177,146,213,196,128,40,26,160,163,180,146,108,60,144,144,136,147,137,40,90,161,3,17,219,243,33,184,130,60,136,243,178,179,132,26,8,168,212,147,
+ 16,57,42,31,145,145,160,32,43,184,66,45,180,33,140,226,1,91,152,16,144,193,162,48,77,25,137,153,17,178,78,0,0,16,14,90,152,153,19,129,13,123,137,129,160,1,73,44,9,129,0,153,120,10,9,162,195,32,139,28,151,161,2,128,26,45,193,146,48,29,146,153, 194, 5, 59,
+ 29,128,144,195,1,64,43,208,178,149,8,9,16,240,163,129,16,42,185,181,211,24,48,45,137,149,9,24,41,75,184,177,4,43,91,128,180,16,144,29,25,184,167,1,59,60,153,148,161,146,91,42,186,4,24,145,123,11,2,178,77,136,26,25,195,40,115,61,27,168,177,3,59,79,26, 25,
+ 144,1,48,13,56,154,248,1,16,9,129,8,2,178,31,130,153,162,20,15,33,170,56,40,29,28,128,152,149,144,56,120,11,162,212,129,144,145,59,180,243,147,145,144,16,152,48,241,0,161,176,1,134,10,129,200,166,144,128,121,26,24,177,178,196,48,75,138,41,180,195,26, 24,
+ 89,138,24,33,187,41,84,155,57,79,136,160,210,130,0,58,58,168,243,132,27,41,75,138,3,8,61,8,29,145,179,76,24,28,146,208,2,49,140,75,196,144,0,40,44,179,208,3,176,33,15,177,2,160,106,8,160,164,164,8,73,27,226,179,161,1,57,1,196,211,128,40,156,145,166, 178,
+ 131,29,128,145,162,165,40,27,216,146,135,144,40,160,194,177,145,20,139,200,151,178,17,136,40,25,205,130,17,11,17,129,156,38,26,25,137,179,163,11,79,16,12,146,147,143,89,25,136,136,25,48,26,46,129,40,29,42,29,8,145,2,56,27,62,8,25,212,161,48,43, 144, 129,
+ 29,145,144,41,106,10,107,43,184,131,1,36,61,13,138,2,194,1,16,27,75,186,181,151,8,1,161,138,211,129,2,59,248,129,16,0,144,63,152,150,136,24,25,128,30,161,128,17,24,225,146,10,16,0,9,227,183,129,40,60,26,162,194,181,24,90,9,24,0,176,161,193,194,35,12, 63,
+ 8,210,162,1,32,78,28,152,164,144,16,48,45,137,162,147,168,152,98,27,43,33,12,160,165,129,137,63,41,153,153,151,16,91,26,8,8,9,56,10,46,24,146,57,168,160,166,241,129,32,140,16,145,179,164,137,113,138,208,131,26,25,1,42,178,196,106,24,171,18,196,8, 18, 29,
+ 41,194,128,3,249,57,162,152,48,184,120,160,208,33,137,74,57,187,149,129,26,35,158,72,128,168,32,26,25,180,75,2,136,15,163,161,136,120,27,41,160,128,182,56,60,25,12,178,151,128,168,72,10,152,4,177,26,147,137,113,44,42,33,220,2,152,41,82,11, 210, 163, 184,
+ 133,162,10,196,128,3,234,40,149,152,161,1,44,129,194,4,225,16,58,168,24,194,146,146,154,49,21,218,33,152,248,129,194,147,0,28,1,195,162,20,140,42,25,160,198,1,33,136,142,3,25,24,141,16,177,208,112,0,138,41,160,130,45,60,32,170,73,24,75,59,161,176,49,159,
+ 97,26,168,149,145,32,28,25,184,211,129,179,74,73,8,153,136,193,151,160,32,48,143,9,147,181,145,32,60,9,187,133,166,144,32,152,25,136,161,150,168,145,81,10,42,0,169,182,148,136,58,41,187,182,211,131,16,137,25,243,144,129,2,9,8,202,7,25,185,21,144,136,153,
+ 65,184,137,56,151,10,153,49,16,145,14,56,176,11,192,19,89,91,44,168,147,2,8,147,63,27,1,136,229,129,73,26,136,26,137,81,170,147,77,72,12,42,42,192,24,104,91,26,27,65,177,27,32,41,60,14,136,17,170,150,129,24,58,11,16,251,162,19,57,31,0,152,129,145,17, 61,
+ 14,1,129,27,129,66,169,178,74,12,11,19,198,145,75,33,138,174,133,1,184,57,40,136,169,20,1,60,174,20,154,201,67,26,162,151,42,16,138,59,130,204,20,169,59,180,59,114,184,56,178,242,128,130,43,8,194,3,229,144,33,185,144,34,181,145,168,17,149,153,74,35, 220,
+ 129,128,1,88,59,75,225,136,130,168,17,144,12,151,8,25,179,8,1,240,16,8,25,145,211,41,130,138,115,169,160,163,168,84,154,74,0,170,144,211,149,2,30,128,137,9,149,1,144,58,60,57,153,178,150,17,29,27,74,25,195,152,56,15,1,25,26,152,149,80,153,57,73,140, 128,
+ 160,144,113,27,56,28,25,4,42,44,137,60,171,130,50,240,8,5,139,145,1,105,137,200,80,137,145,146,178,179,160,46,16,240,195,131,128,144,24,164,198,128,0,136,137,131,194,165,177,2,161,147,11,144,188,181,148,144,23,0,28,224,128,131,192,32,1,224,1,168,132,145,
+ 9,41,208,58,137,179,151,145,16,1,30,8,145,178,1,47,32,186,72,169,146,75,8,41,48,136,89,13,48,9,10,124,26,11,42,32,129,91,77,16,12,128,42,57,138,10,60,2,63,9,0,93,128,152,90,8,10,24,40,44,144,29,49,188,48,72,25,30,177,33,128,186,120,129,186,133, 152, 130,
+ 24,156,51,154,8,226,2,56,155,2,179,233,167,128,24,129,176,136,151,8,184,0,33,224,152,21,177,24,10,163,16,250,17,130,171,83,137,136,37,12,56,242,154,17,160,145,82,13,3,201,128,18,137,24,162,63,162,8,107,178,128,57,158,32,24,200,18,0,106,154,73,16, 248, 8,
+ 73,137,57,75,0,128,12,65,137,59,75,28,144,129,122,0,58,140,160,195,145,105,56,28,153,145,164,88,8,28,25,153,9,162,113,89,153,136,33,234,147,128,41,72,11,138,151,144,145,16,43,58,248,130,178,42,4,40,10,196,154,147,216,24,7,136,10,161,148,210,161, 98, 138,
+ 137,128,146,176,33,105,27,43,163,49,185,6,10,136,43,67,174,161,162,151,137,1,64,200,193,24,64,200,56,145,242,24,57,137,1,128,3,162,175,80,128,162,152,25,58,175,17,17,0,200,64,168,162,91,1,154,44,211,177,35,64,160,161,144,4,241,41,209,162,25,1,3,242, 176,
+ 134,153,42,41,136,135,154,2,130,46,41,161,153,180,145,34,26,46,18,242,137,146,129,25,128,11,151,161,40,179,27,122,168,59,137,181,50,172,36,56,15,9,129,137,128,75,2,58,12,52,141,8,24,58,153,157,122,145,9,1,80,27,184,32,74,219,50,57,168,153,180,48,28, 143,
+ 131,144,178,65,13,48,168,162,147,155,121,9,170,5,16,153,21,29,144,161,91,0,184,57,128,137,17,159,88,178,128,105,152,9,162,33,164,141,88,178,224,1,0,16,27,185,150,161,9,4,139,16,128,160,194,144,65,180,46,40,136,27,135,160,16,44,57,145,236,2,195,40,75,177,
+ 2,200,179,146,186,104,50,141,24,169,165,148,11,97,10,11,130,177,49,57,78,42,154,128,165,59,33,28,30,1,136,16,192,41,128,152,123,136,24,1,169,113,10,11,49,153,14,147,19,45,43,8,176,210,148,8,16,11,96,144,192,163,150,10,128,43,26,150,178,165,24,41,171, 18,
+ 27,215,1,8,128,136,40,35,208,11,161,193,18,73,154,133,155,165,164,10,49,154,8,199,0,2,168,64,192,0,40,162,43,202,180,150,10,106,24,185,145,131,184,113,43,24,162,187,73,146,42,81,171,121,58,155,151,16,43,32,31,9,160,146,17,136,94,10,24,145,25, 9, 130, 59,
+ 65,13,91,25,169,146,176,112,42,59,16,217,130,20,13,25,9,40,161,138,68,169,154,18,62,154,180,145,135,152,56,58,155,165,211,8,40,42,10,198,1,2,184,57,184,224,51,154,27,134,168,19,202,73,75,184,35,176,75,24,25,209,51,157,19,30,184,179,3,33,148,45, 232, 146,
+ 129,168,41,32,170,149,193,35,136,16,50,191,56,146,173,149,16,24,41,30,129,168,209,3,57,31,0,16,176,147,41,152,10,17,181,14,40,144,49,170,75,97,141,25,162,146,72,177,92,137,137,19,137,153,113,154,2,41,60,129,217,2,211,152,73,42,193,197,146,147, 10, 59, 0,
+ 192,196,132,41,160,25,88,169,16,40,241,1,153,81,28,10,147,161,209,88,75,9,161,162,180,16,43,57,235,33,56,156,129,144,2,135,31,128,145,136,163,56,59,154,57,167,160,105,137,0,138,163,3,41,47,185,211,131,41,41,60,139,182,146,16,16,43,242,144,145,129,16,179,
+ 183,1,26,9,147,240,131,160,91,74,152,184,166,178,33,140,9,4,162,233,34,136,129,144,163,60,142,144,149,128,33,73,13,161,194,131,0,26,56,142,128,163,128,1,233,56,209,41,145,194,147,179,149,64,30,8,128,216,18,24,43,43,32,153,25,74,109,137,153,48,8,137, 122,
+ 25,144,26,43,59,30,33,41,27,24,96,153,160,50,76,27,47,152,145,163,73,40,14,152,131,176,74,90,8,8,200,67,155,154,50,49,155,28,124,177,152,1,2,17,62,138,180,176,4,25,9,177,245,162,129,40,25,176,164,130,172,4,8,181,194,49,11,168,154,165,133,152,40,136, 226,
+ 179,19,26,185,16,167,194,16,25,57,243,136,147,1,31,25,184,132,160,33,62,138,129,130,41,121,137,153,145,26,17,107,136,179,1,61,60,26,162,168,148,64,31,25,32,168,152,64,31,137,8,129,33,62,24,137,8,16,59,47,153,33,162,91,59,41,170,145,5,43,60,41,13,178,134,
+ 57,153,12,194,227,8,2,128,57,208,162,19,216,32,178,25,128,160,48,194,195,37,155,10,33,251,163,146,16,136,12,166,195,160,148,129,176,147,178,150,160,72,162,162,193,162,60,200,145,5,144,25,122,216,129,161,130,0,10,73,1,241,2,9,168,33,13,161,165,24,64, 203,
+ 50,1,14,9,9,129,161,106,33,27,13,164,128,40,41,107,169,160,33,136,60,92,168,152,2,91,57,176,129,0,144,47,136,162,164,128,80,43,154,179,213,130,74,27,0,145,145,167,58,59,160,9,26,76,8,171,5,49,28,44,169,162,183,130,72,28,144,179,228,2,25,26,129, 186, 151,
+ 1,75,128,169,17,178,15,57,170,16,166,16,57,8,139,162,181,1,8,152,164,181,41,81,43,10,242,145,57,139,89,8,193,18,154,32,176,10,165,129,137,147,177,134,0,25,25,201,147,227,129,72,59,185,167,128,129,160,91,25,176,130,147,145,9,160,5,202,17,16, 186, 136, 37,
+ 177,56,76,42,169,186,48,9,145,57,24,128,41,169,134,137,145,147,28,41,168,131,228,32,27,9,60,129,178,64,60,45,25,9,24,152,49,31,136,57,42,0,25,12,181,18,153,57,96,169,177,132,153,123,9,152,129,177,17,74,43,24,169,128,121,137,25,1,139,96,42,10,146,178, 18,
+ 44,29,1,161,164,146,31,137,146,177,19,1,10,26,209,165,146,43,40,138,240,130,18,144,25,40,212,1,58,11,152,196,147,10,74,26,152,225,130,146,58,60,210,145,16,148,16,185,192,18,44,42,57,199,162,1,9,87,47,186,215,231,197,179,180,195,212,164,32,59,92, 126, 62,
+ 41,59,76,59,60,168,179,213,197,163,72,44,25,74,126,127,127,79,26,177,148,90,27,225,247,165,0,152,147,123,138,211,164,72,126,127,46,210,196,163,228,215,64,11,210,180,1,8,58,153,1,224,149,57,76,27,24,76,42,43,136,128,243,179,130,106,60,42,42,92,28,243,231,
+ 147,24,57,44,58,94,45,8,57,139,214,148,40,77,26,9,16,10,144,64,62,43,25,123,59,138,162,48,63,26,41,92,60,43,176,3,59,232,214,164,16,75,75,76,60,153,179,33,62,26,136,40,75,169,197,163,129,57,60,59,75,138,145,64,63,138,179,1,42,136,90,43,176,214,180,1, 25,
+ 152,195,129,129,106,76,60,137,145,178,2,25,10,228,130,57,59,44,41,154,165,105,76,44,144,16,76,26,41,76,26,152,1,58,26,9,193,165,16,92,26,41,77,59,76,76,60,26,136,161,130,152,195,163,211,146,0,57,11,211,130,8,25,40,62,153,162,17,109,60,153,146,40, 76, 60,
+ 26,160,179,211,163,32,60,42,153,179,194,199,130,24,58,43,58,27,128,161,195,129,226,196,147,90,59,75,44,136,128,145,160,148,123,59,42,26,41,26,57,27,192,215,147,57,59,27,161,145,213,130,106,76,43,9,144,162,129,177,181,130,136,194,146,40,10,129,25,210,146,
+ 178,197,196,179,196,130,8,41,9,144,178,130,209,182,17,92,43,176,147,144,212,130,136,0,177,130,73,62,10,161,130,91,75,59,43,57,46,25,41,77,10,177,164,16,26,136,210,197,179,130,128,57,77,43,25,75,10,227,179,180,179,146,128,57,185,183,163,145,0,8,8,10, 119,
+ 114,120,16,210,244,60,28,41,25,152,149,56,161,35,44,89,27,24,136,24,164,211,17,233,176,136,192,129,179,17,17,25,0,10,46,160,132,49,66,24,132,177,147,193,56,72,26,29,232,168,176,12,137,41,139,147,9,1,41,15,91,136,35,148,21,18,48,40,1,168,167,144,0,42,172,
+ 177,204,193,155,232,152,152,26,152,41,146,17,6,4,65,34,35,135,4,16,32,9,24,186,176,0,250,153,204,186,173,154,153,177,3,65,41,34,145,134,35,65,98,49,50,50,2,33,169,138,155,175,170,172,204,192,138,234,136,155,136,10,32,18,5,52,48,24,162,17,67,54,66,51, 34,
+ 131,184,174,234,153,10,9,40,0,152,251,168,142,154,9,16,33,49,33,128,154,170,156,34,54,54,33,68,0,1,136,201,137,26,88,48,35,99,8,152,189,189,187,155,171,16,24,130,145,188,175,203,144,49,115,67,67,50,19,2,1,0,0,130,131,1,136,206,216,188,203, 204, 187, 187,
+ 156,153,0,0,51,17,34,24,112,20,69,67,67,34,19,0,136,169,185,137,186,232,185,219,201,203,187,173,170,154,153,129,131,6,2,19,49,49,21,65,19,53,51,83,34,16,168,201,154,172,156,138,0,1,24,201,233,186,204,186,171,137,3,37,48,24,128,201,202,202,129,17, 48, 21,
+ 22,20,19,19,32,16,2,66,52,68,4,3,1,203,235,188,189,186,171,153,137,153,170,219,170,140,9,17,53,115,50,52,67,51,51,51,17,130,0,145,154,169,188,236,187,190,203,187,172,171,138,136,17,33,18,2,34,98,98,50,50,52,66,34,35,2,19,24,169,203,203,188,219, 169, 154,
+ 9,137,171,204,188,203,184,136,34,83,50,33,153,184,170,170,152,40,57,19,36,50,50,18,35,17,2,49,49,66,66,66,34,17,168,233,202,202,170,171,170,186,219,203,188,188,154,138,25,33,68,52,68,67,67,36,51,36,18,17,17,136,8,170,176,202,188,206,202,171,172,186, 169,
+ 153,8,25,144,128,1,34,68,52,68,51,52,34,49,18,34,2,144,136,155,140,187,186,186,154,154,185,185,153,9,9,0,24,0,128,144,168,169,170,154,154,153,9,8,16,8,0,144,19,35,68,51,52,67,51,66,34,50,33,1,144,185,186,172,204,187,188,173,172,186,172,186, 154, 138, 41,
+ 33,52,53,83,50,51,52,52,37,34,34,18,16,144,152,154,187,219,203,188,173,186,186,186,170,154,153,138,144,16,17,67,82,50,51,21,34,19,33,2,18,33,1,8,153,169,153,153,136,128,0,136,154,153,153,8,8,1,16,0,169,170,187,171,171,154,153,153,152,153,153,0,16,51, 83,
+ 66,50,67,50,51,67,51,52,35,18,136,186,219,187,189,186,171,187,173,187,188,187,203,138,9,16,33,50,52,53,67,67,147,8,128,128,128,128,128,128,128,128,0,240,255,55,232,23,220,0,148,1,9,18,148,10,189,32,163,62,160,5,137,12,149,42,153,144,34,42,8, 1, 138, 181,
+ 45,136,18,144,105,138,1,160,14,128,132,145,186,37,138,41,192,48,145,46,160,33,44,24,225,16,13,132,136,137,16,148,25,170,194,82,152,136,91,24,42,169,33,233,131,179,24,185,149,16,57,172,164,18,10,211,160,147,211,33,138,243,129,16,41,193,0,43, 132, 155, 73,
+ 58,145,244,145,43,35,9,171,16,110,25,8,28,74,162,128,26,27,82,45,136,153,18,8,136,8
+};
} // end of namespace Kyra
diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp
index 34c2986f25..05074d20b1 100644
--- a/engines/kyra/sprites.cpp
+++ b/engines/kyra/sprites.cpp
@@ -28,7 +28,6 @@
#include "common/stream.h"
#include "common/util.h"
#include "common/system.h"
-#include "common/events.h"
#include "kyra/screen.h"
#include "kyra/kyra_lok.h"
#include "kyra/sprites.h"
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index bb63c24c36..bfffefb70a 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -43,22 +43,22 @@
namespace Kyra {
-#define RESFILE_VERSION 31
+#define RESFILE_VERSION 32
-bool StaticResource::checkKyraDat() {
- Common::File kyraDat;
- if (!kyraDat.open(StaticResource::staticDataFilename()))
+bool StaticResource::checkKyraDat(Resource *res) {
+ Common::SharedPtr<Common::SeekableReadStream> kyraDat(res->getFileStream(StaticResource::staticDataFilename()));
+ if (!kyraDat)
return false;
- uint32 size = kyraDat.size() - 16;
+ uint32 size = kyraDat->size() - 16;
uint8 digest[16];
- kyraDat.seek(size, SEEK_SET);
- if (kyraDat.read(digest, 16) != 16)
+ kyraDat->seek(size, SEEK_SET);
+ if (kyraDat->read(digest, 16) != 16)
return false;
- kyraDat.close();
uint8 digestCalc[16];
- if (!Common::md5_file(StaticResource::staticDataFilename().c_str(), digestCalc, size))
+ kyraDat->seek(0, SEEK_SET);
+ if (!Common::md5_file(*kyraDat, digestCalc, size))
return false;
for (int i = 0; i < 16; ++i)
@@ -308,28 +308,27 @@ bool StaticResource::init() {
}
char errorBuffer[100];
- int tempSize = 0;
- uint8 *temp = getFile("INDEX", tempSize);
- if (!temp) {
+ Common::SeekableReadStream *index = getFile("INDEX");
+ if (!index) {
snprintf(errorBuffer, sizeof(errorBuffer), "is missing an '%s' entry", getFilename("INDEX"));
outputError(errorBuffer);
return false;
}
- if (tempSize != 3*4) {
- delete[] temp;
+ if (index->size() != 3*4) {
+ delete index;
snprintf(errorBuffer, sizeof(errorBuffer), "has incorrect header size for entry '%s'", getFilename("INDEX"));
outputError(errorBuffer);
return false;
}
- uint32 version = READ_BE_UINT32(temp);
- uint32 gameID = READ_BE_UINT32((temp+4));
- uint32 featuresValue = READ_BE_UINT32((temp+8));
+ uint32 version = index->readUint32BE();
+ uint32 gameID = index->readUint32BE();
+ uint32 featuresValue = index->readUint32BE();
- delete[] temp;
- temp = 0;
+ delete index;
+ index = 0;
if (version != RESFILE_VERSION) {
snprintf(errorBuffer, sizeof(errorBuffer), "has invalid version %d required, you got %d", RESFILE_VERSION, version);
@@ -553,82 +552,86 @@ bool StaticResource::loadLanguageTable(const char *filename, void *&ptr, int &si
}
bool StaticResource::loadStringTable(const char *filename, void *&ptr, int &size) {
- uint8 *filePtr = getFile(filename, size);
- if (!filePtr)
+ Common::SeekableReadStream *file = getFile(filename);
+ if (!file)
return false;
- uint8 *src = filePtr;
- uint32 count = READ_BE_UINT32(src); src += 4;
+ uint32 count = file->readUint32BE();
size = count;
char **output = new char*[count];
assert(output);
- const char *curPos = (const char*)src;
for (uint32 i = 0; i < count; ++i) {
- int strLen = strlen(curPos);
- output[i] = new char[strLen+1];
- assert(output[i]);
- memcpy(output[i], curPos, strLen+1);
- curPos += strLen+1;
+ Common::String string;
+ char c = 0;
+ while ((c = (char)file->readByte()) != 0)
+ string += c;
+
+ output[i] = new char[string.size()+1];
+ strcpy(output[i], string.c_str());
}
- delete[] filePtr;
+ delete file;
ptr = output;
return true;
}
bool StaticResource::loadRawData(const char *filename, void *&ptr, int &size) {
- ptr = getFile(filename, size);
- if (!ptr)
+ Common::SeekableReadStream *file = getFile(filename);
+ if (!file)
return false;
+
+ ptr = new uint8[file->size()];
+ file->read(ptr, file->size());
+ size = file->size();
+ delete file;
+
return true;
}
bool StaticResource::loadShapeTable(const char *filename, void *&ptr, int &size) {
- uint8 *filePtr = getFile(filename, size);
- if (!filePtr)
+ Common::SeekableReadStream *file = getFile(filename);
+ if (!file)
return false;
- uint8 *src = filePtr;
- uint32 count = READ_BE_UINT32(src); src += 4;
+ uint32 count = file->readUint32BE();
size = count;
Shape *loadTo = new Shape[count];
assert(loadTo);
for (uint32 i = 0; i < count; ++i) {
- loadTo[i].imageIndex = *src++;
- loadTo[i].x = *src++;
- loadTo[i].y = *src++;
- loadTo[i].w = *src++;
- loadTo[i].h = *src++;
- loadTo[i].xOffset = *src++;
- loadTo[i].yOffset = *src++;
+ loadTo[i].imageIndex = file->readByte();
+ loadTo[i].x = file->readByte();
+ loadTo[i].y = file->readByte();
+ loadTo[i].w = file->readByte();
+ loadTo[i].h = file->readByte();
+ loadTo[i].xOffset = file->readSByte();
+ loadTo[i].yOffset = file->readSByte();
}
- delete[] filePtr;
+ delete file;
ptr = loadTo;
return true;
}
bool StaticResource::loadRoomTable(const char *filename, void *&ptr, int &size) {
- uint8 *filePtr = getFile(filename, size);
- if (!filePtr)
+ Common::SeekableReadStream *file = getFile(filename);
+ if (!file)
return false;
- uint8 *src = filePtr;
- uint32 count = READ_BE_UINT32(src); src += 4;
+ uint32 count = file->readUint32BE();
size = count;
Room *loadTo = new Room[count];
assert(loadTo);
for (uint32 i = 0; i < count; ++i) {
- loadTo[i].nameIndex = *src++;
- loadTo[i].northExit = READ_BE_UINT16(src); src += 2;
- loadTo[i].eastExit = READ_BE_UINT16(src); src += 2;
- loadTo[i].southExit = READ_BE_UINT16(src); src += 2;
- loadTo[i].westExit = READ_BE_UINT16(src); src += 2;
+ loadTo[i].nameIndex = file->readByte();
+ loadTo[i].northExit = file->readUint16BE();
+ loadTo[i].eastExit = file->readUint16BE();
+ loadTo[i].southExit = file->readUint16BE();
+ loadTo[i].westExit = file->readUint16BE();
memset(&loadTo[i].itemsTable[0], 0xFF, sizeof(byte)*6);
memset(&loadTo[i].itemsTable[6], 0, sizeof(byte)*6);
memset(loadTo[i].itemsXPos, 0, sizeof(uint16)*12);
@@ -636,7 +639,7 @@ bool StaticResource::loadRoomTable(const char *filename, void *&ptr, int &size)
memset(loadTo[i].needInit, 0, sizeof(loadTo[i].needInit));
}
- delete[] filePtr;
+ delete file;
ptr = loadTo;
return true;
@@ -651,10 +654,10 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz
++temp;
int end = atoi(temp);
- char **table = new char*[end-start+1];
+ uint8 **table = new uint8*[end-start+1];
assert(table);
- char file[64];
+ char baseFilename[64];
temp = filename;
temp = strstr(temp, " ");
++temp;
@@ -662,16 +665,24 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz
if (temp == NULL)
return false;
++temp;
- strncpy(file, temp, 64);
+ strncpy(baseFilename, temp, 64);
char name[64];
for (int i = start; i <= end; ++i) {
- snprintf(name, 64, "%s%d.PAL", file, i);
- table[(start != 0) ? (i-start) : i] = (char*)getFile(name, size);
- if (!table[(start != 0) ? (i-start) : i]) {
+ snprintf(name, 64, "%s%d.PAL", baseFilename, i);
+
+ Common::SeekableReadStream *file = getFile(name);
+ if (!file) {
+ for (int j = start; j < i; ++i)
+ delete[] table[j-start];
delete[] table;
+
return false;
}
+
+ table[i-start] = new uint8[file->size()];
+ file->read(table[i-start], file->size());
+ delete file;
}
ptr = table;
@@ -680,86 +691,67 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz
}
bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int &size) {
- int filesize;
- uint8 *filePtr = getFile(filename, filesize);
+ Common::SeekableReadStream *file = getFile(filename);
- if (!filePtr)
+ if (!file)
return false;
- uint16 *hdr = (uint16 *) filePtr;
- int numSeq = READ_BE_UINT16(hdr++);
+ int numSeq = file->readUint16BE();
+ uint32 offset = 2;
Sequence *tmp_s = new Sequence[numSeq];
- char *tmp_c = 0;
size = sizeof(HofSeqData) + numSeq * (sizeof(Sequence) + 28);
for (int i = 0; i < numSeq; i++) {
- const uint8 *offset = (const uint8 *)(filePtr + READ_BE_UINT16(hdr++));
- tmp_s[i].flags = READ_BE_UINT16(offset);
- offset += 2;
- tmp_c = new char[14];
- memcpy(tmp_c, offset, 14);
- tmp_s[i].wsaFile = tmp_c;
- offset += 14;
- tmp_c = new char[14];
- memcpy(tmp_c, offset, 14);
- tmp_s[i].cpsFile = tmp_c;
- offset += 14;
- tmp_s[i].startupCommand = *offset++;
- tmp_s[i].finalCommand = *offset++;
- tmp_s[i].stringIndex1 = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].stringIndex2 = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].startFrame = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].numFrames = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].frameDelay = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].xPos = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].yPos = READ_BE_UINT16(offset);
- offset += 2;
- tmp_s[i].duration = READ_BE_UINT16(offset);
+ file->seek(offset, SEEK_SET); offset += 2;
+ file->seek(file->readUint16BE(), SEEK_SET);
+
+ tmp_s[i].flags = file->readUint16BE();
+ tmp_s[i].wsaFile = new char[14];
+ file->read(const_cast<char*>(tmp_s[i].wsaFile), 14);
+ tmp_s[i].cpsFile = new char[14];
+ file->read(const_cast<char*>(tmp_s[i].cpsFile), 14);
+ tmp_s[i].startupCommand = file->readByte();
+ tmp_s[i].finalCommand = file->readByte();
+ tmp_s[i].stringIndex1 = file->readUint16BE();
+ tmp_s[i].stringIndex2 = file->readUint16BE();
+ tmp_s[i].startFrame = file->readUint16BE();
+ tmp_s[i].numFrames = file->readUint16BE();
+ tmp_s[i].frameDelay = file->readUint16BE();
+ tmp_s[i].xPos = file->readUint16BE();
+ tmp_s[i].yPos = file->readUint16BE();
+ tmp_s[i].duration = file->readUint16BE();
}
- int numSeqN = READ_BE_UINT16(hdr++);
+ file->seek(offset, SEEK_SET); offset += 2;
+ int numSeqN = file->readUint16BE();
NestedSequence *tmp_n = new NestedSequence[numSeqN];
size += (numSeqN * (sizeof(NestedSequence) + 14));
for (int i = 0; i < numSeqN; i++) {
- const uint8 *offset = (const uint8 *)(filePtr + READ_BE_UINT16(hdr++));
- tmp_n[i].flags = READ_BE_UINT16(offset);
- offset += 2;
- tmp_c = new char[14];
- memcpy(tmp_c, offset, 14);
- tmp_n[i].wsaFile = tmp_c;
- offset += 14;
- tmp_n[i].startframe = READ_BE_UINT16(offset);
- offset += 2;
- tmp_n[i].endFrame = READ_BE_UINT16(offset);
- offset += 2;
- tmp_n[i].frameDelay = READ_BE_UINT16(offset);
- offset += 2;
- tmp_n[i].x = READ_BE_UINT16(offset);
- offset += 2;
- tmp_n[i].y = READ_BE_UINT16(offset);
- offset += 2;
- uint16 ctrlOffs = READ_BE_UINT16(offset);
- offset += 2;
- tmp_n[i].startupCommand = READ_BE_UINT16(offset);
- offset += 2;
- tmp_n[i].finalCommand = READ_BE_UINT16(offset);
+ file->seek(offset, SEEK_SET); offset += 2;
+ file->seek(file->readUint16BE(), SEEK_SET);
+
+ tmp_n[i].flags = file->readUint16BE();
+ tmp_n[i].wsaFile = new char[14];
+ file->read(const_cast<char*>(tmp_n[i].wsaFile), 14);
+ tmp_n[i].startframe = file->readUint16BE();
+ tmp_n[i].endFrame = file->readUint16BE();
+ tmp_n[i].frameDelay = file->readUint16BE();
+ tmp_n[i].x = file->readUint16BE();
+ tmp_n[i].y = file->readUint16BE();
+ uint16 ctrlOffs = file->readUint16BE();
+ tmp_n[i].startupCommand = file->readUint16BE();
+ tmp_n[i].finalCommand = file->readUint16BE();
if (ctrlOffs) {
- int num_c = *(filePtr + ctrlOffs);
- const uint16 *in_c = (uint16*) (filePtr + ctrlOffs + 1);
+ file->seek(ctrlOffs, SEEK_SET);
+ int num_c = file->readByte();
FrameControl *tmp_f = new FrameControl[num_c];
for (int ii = 0; ii < num_c; ii++) {
- tmp_f[ii].index = READ_BE_UINT16(in_c++);
- tmp_f[ii].delay = READ_BE_UINT16(in_c++);
+ tmp_f[ii].index = file->readUint16BE();
+ tmp_f[ii].delay = file->readUint16BE();
}
tmp_n[i].wsaControl = (const FrameControl*) tmp_f;
@@ -770,7 +762,7 @@ bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int &
}
}
- delete[] filePtr;
+ delete file;
HofSeqData *loadTo = new HofSeqData;
assert(loadTo);
@@ -786,65 +778,53 @@ bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int &
}
bool StaticResource::loadShapeAnimData_v1(const char *filename, void *&ptr, int &size) {
- int filesize;
- uint8 *filePtr = getFile(filename, filesize);
- uint8 *src = filePtr;
+ Common::SeekableReadStream *file = getFile(filename);
- if (!filePtr)
+ if (!file)
return false;
- size = *src++;
+ size = file->readByte();
ItemAnimData_v1 *loadTo = new ItemAnimData_v1[size];
assert(loadTo);
for (int i = 0; i < size; i++) {
- loadTo[i].itemIndex = (int16) READ_BE_UINT16(src);
- src += 2;
- loadTo[i].y = READ_BE_UINT16(src);
- src += 2;
+ loadTo[i].itemIndex = file->readSint16BE();
+ loadTo[i].y = file->readUint16BE();
uint16 *tmp_f = new uint16[20];
- for (int ii = 0; ii < 20; ii++) {
- tmp_f[ii] = READ_BE_UINT16(src);
- src += 2;
- }
+ for (int ii = 0; ii < 20; ii++)
+ tmp_f[ii] = file->readUint16BE();
loadTo[i].frames = tmp_f;
}
- delete[] filePtr;
+ delete file;
ptr = loadTo;
return true;
}
bool StaticResource::loadShapeAnimData_v2(const char *filename, void *&ptr, int &size) {
- int filesize;
- uint8 *filePtr = getFile(filename, filesize);
- uint8 *src = filePtr;
+ Common::SeekableReadStream *file = getFile(filename);
- if (!filePtr)
+ if (!file)
return false;
- size = *src++;
+ size = file->readByte();
ItemAnimData_v2 *loadTo = new ItemAnimData_v2[size];
assert(loadTo);
for (int i = 0; i < size; i++) {
- loadTo[i].itemIndex = (int16) READ_BE_UINT16(src);
- src += 2;
- loadTo[i].numFrames = *src++;
+ loadTo[i].itemIndex = file->readSint16BE();
+ loadTo[i].numFrames = file->readByte();
FrameControl *tmp_f = new FrameControl[loadTo[i].numFrames];
for (int ii = 0; ii < loadTo[i].numFrames; ii++) {
- tmp_f[ii].index = READ_BE_UINT16(src);
- src += 2;
- tmp_f[ii].delay = READ_BE_UINT16(src);
- src += 2;
+ tmp_f[ii].index = file->readUint16BE();
+ tmp_f[ii].delay = file->readUint16BE();
}
loadTo[i].frames = tmp_f;
}
- delete[] filePtr;
+ delete file;
ptr = loadTo;
-
return true;
}
@@ -920,6 +900,7 @@ void StaticResource::freePaletteTable(void *&ptr, int &size) {
uint8 **data = (uint8**)ptr;
while (size--)
delete[] data[size];
+ delete[] data;
ptr = 0;
size = 0;
}
@@ -948,11 +929,8 @@ const char *StaticResource::getFilename(const char *name) {
return filename.c_str();
}
-uint8 *StaticResource::getFile(const char *name, int &size) {
- uint32 tempSize = 0;
- uint8 *data = _vm->resource()->fileData(getFilename(name), &tempSize);
- size = tempSize;
- return data;
+Common::SeekableReadStream *StaticResource::getFile(const char *name) {
+ return _vm->resource()->getFileStream(getFilename(name));
}
#pragma mark -
diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp
index f8eb10a85e..eecb617942 100644
--- a/engines/kyra/text.cpp
+++ b/engines/kyra/text.cpp
@@ -29,7 +29,6 @@
#include "kyra/screen.h"
#include "kyra/text.h"
-#include "common/events.h"
#include "common/system.h"
#include "common/endian.h"
diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp
index dd587c5112..b94b8a6258 100644
--- a/engines/kyra/text_hof.cpp
+++ b/engines/kyra/text_hof.cpp
@@ -335,7 +335,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() {
const uint32 endTime = _chatEndTime;
resetSkipFlag();
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (!_emc->isValid(&_chatScriptState))
_emc->start(&_chatScriptState, 1);
@@ -353,7 +353,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() {
uint32 nextFrame = _system->getMillis() + delayTime * _tickLength;
- while (_system->getMillis() < nextFrame && !_quitFlag) {
+ while (_system->getMillis() < nextFrame && !quit()) {
updateWithText();
const uint32 curTime = _system->getMillis();
@@ -593,7 +593,7 @@ void KyraEngine_HoF::initTalkObject(int index) {
if (_currentTalkSections.STATim) {
_tim->resetFinishedFlag();
- while (!_quitFlag && !_tim->finished()) {
+ while (!quit() && !_tim->finished()) {
_tim->exec(_currentTalkSections.STATim, false);
if (_chatText)
updateWithText();
@@ -609,7 +609,7 @@ void KyraEngine_HoF::deinitTalkObject(int index) {
if (_currentTalkSections.ENDTim) {
_tim->resetFinishedFlag();
- while (!_quitFlag && !_tim->finished()) {
+ while (!quit() && !_tim->finished()) {
_tim->exec(_currentTalkSections.ENDTim, false);
if (_chatText)
updateWithText();
@@ -647,10 +647,10 @@ void KyraEngine_HoF::npcChatSequence(const char *str, int objectId, int vocHigh,
_chatVocHigh = _chatVocLow = -1;
}
- while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || skipFlag())) {
+ while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(quit() || skipFlag())) {
if ((!speechEnabled() && chatAnimEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) {
_tim->resetFinishedFlag();
- while (!_tim->finished() && !skipFlag() && !_quitFlag) {
+ while (!_tim->finished() && !skipFlag() && !quit()) {
if (_currentTalkSections.TLKTim)
_tim->exec(_currentTalkSections.TLKTim, false);
else
diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp
index f6b0407a75..150ec59a23 100644
--- a/engines/kyra/text_lok.cpp
+++ b/engines/kyra/text_lok.cpp
@@ -120,8 +120,8 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const
if (event.kbd.keycode == '.')
_skipFlag = true;
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- quitGame();
runLoop = false;
break;
case Common::EVENT_LBUTTONDOWN:
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index 16c56da099..be306ceec1 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -349,7 +349,7 @@ void KyraEngine_MR::objectChatWaitToFinish() {
const uint32 endTime = _chatEndTime;
resetSkipFlag();
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (!_emc->isValid(&_chatScriptState))
_emc->start(&_chatScriptState, 1);
@@ -367,7 +367,7 @@ void KyraEngine_MR::objectChatWaitToFinish() {
uint32 nextFrame = _system->getMillis() + delayTime * _tickLength;
- while (_system->getMillis() < nextFrame && !_quitFlag) {
+ while (_system->getMillis() < nextFrame && !quit()) {
updateWithText();
const uint32 curTime = _system->getMillis();
@@ -419,7 +419,7 @@ void KyraEngine_MR::badConscienceChatWaitToFinish() {
uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength;
int frame = _badConscienceFrameTable[_badConscienceAnim+24];
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (nextFrame < _system->getMillis()) {
++frame;
if (_badConscienceFrameTable[_badConscienceAnim+32] < frame)
@@ -477,7 +477,7 @@ void KyraEngine_MR::goodConscienceChatWaitToFinish() {
uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(3, 6) * _tickLength;
int frame = _goodConscienceFrameTable[_goodConscienceAnim+15];
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (nextFrame < _system->getMillis()) {
++frame;
if (_goodConscienceFrameTable[_goodConscienceAnim+20] < frame)
@@ -597,7 +597,7 @@ void KyraEngine_MR::albumChatWaitToFinish() {
uint32 nextFrame = 0;
int frame = 12;
- while (running && !_quitFlag) {
+ while (running && !quit()) {
if (nextFrame < _system->getMillis()) {
++frame;
if (frame > 22)
diff --git a/engines/kyra/timer_mr.cpp b/engines/kyra/timer_mr.cpp
index 37a910ccf2..dd749723ce 100644
--- a/engines/kyra/timer_mr.cpp
+++ b/engines/kyra/timer_mr.cpp
@@ -65,7 +65,7 @@ void KyraEngine_MR::timerRunSceneScript7(int arg) {
void KyraEngine_MR::timerFleaDeath(int arg) {
debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_MR::timerFleaDeath(%d)", arg);
_timer->setCountdown(4, 5400);
- saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME");
+ saveGame(getSavegameFilename(999), "Autosave", 0);
_screen->hideMouse();
_timer->disable(4);
runAnimationScript("FLEADTH1.EMC", 0, 0, 1, 1);
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index 3d18f27c7e..0f6440fd47 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -32,13 +32,13 @@
// The jung2.vqa movie does work, but only thanks to a grotesque hack.
-#include "common/events.h"
#include "common/system.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "kyra/sound.h"
#include "kyra/screen.h"
#include "kyra/vqa.h"
+#include "kyra/resource.h"
namespace Kyra {
@@ -91,10 +91,10 @@ uint32 VQAMovie::readTag() {
// Some tags have to be on an even offset, so they are padded with a
// zero byte. Skip that.
- uint32 tag = _file.readUint32BE();
+ uint32 tag = _file->readUint32BE();
if (!(tag & 0xFF000000)) {
- tag = (tag << 8) | _file.readByte();
+ tag = (tag << 8) | _file->readByte();
}
return tag;
@@ -185,18 +185,19 @@ bool VQAMovie::open(const char *filename) {
debugC(9, kDebugLevelMovie, "VQAMovie::open('%s')", filename);
close();
- if (!_file.open(filename))
+ _file = _vm->resource()->getFileStream(filename);
+ if (!_file)
return false;
- if (_file.readUint32BE() != MKID_BE('FORM')) {
+ if (_file->readUint32BE() != MKID_BE('FORM')) {
warning("VQAMovie::open: Cannot find `FORM' tag");
return false;
}
// For now, we ignore the size of the FORM chunk.
- _file.readUint32BE();
+ _file->readUint32BE();
- if (_file.readUint32BE() != MKID_BE('WVQA')) {
+ if (_file->readUint32BE() != MKID_BE('WVQA')) {
warning("WQAMovie::open: Cannot find `WVQA' tag");
return false;
}
@@ -209,30 +210,30 @@ bool VQAMovie::open(const char *filename) {
while (!foundHeader || !foundFrameInfo) {
uint32 tag = readTag();
- uint32 size = _file.readUint32BE();
+ uint32 size = _file->readUint32BE();
switch (tag) {
case MKID_BE('VQHD'): // VQA header
- _header.version = _file.readUint16LE();
- _header.flags = _file.readUint16LE();
- _header.numFrames = _file.readUint16LE();
- _header.width = _file.readUint16LE();
- _header.height = _file.readUint16LE();
- _header.blockW = _file.readByte();
- _header.blockH = _file.readByte();
- _header.frameRate = _file.readByte();
- _header.cbParts = _file.readByte();
- _header.colors = _file.readUint16LE();
- _header.maxBlocks = _file.readUint16LE();
- _header.unk1 = _file.readUint32LE();
- _header.unk2 = _file.readUint16LE();
- _header.freq = _file.readUint16LE();
- _header.channels = _file.readByte();
- _header.bits = _file.readByte();
- _header.unk3 = _file.readUint32LE();
- _header.unk4 = _file.readUint16LE();
- _header.maxCBFZSize = _file.readUint32LE();
- _header.unk5 = _file.readUint32LE();
+ _header.version = _file->readUint16LE();
+ _header.flags = _file->readUint16LE();
+ _header.numFrames = _file->readUint16LE();
+ _header.width = _file->readUint16LE();
+ _header.height = _file->readUint16LE();
+ _header.blockW = _file->readByte();
+ _header.blockH = _file->readByte();
+ _header.frameRate = _file->readByte();
+ _header.cbParts = _file->readByte();
+ _header.colors = _file->readUint16LE();
+ _header.maxBlocks = _file->readUint16LE();
+ _header.unk1 = _file->readUint32LE();
+ _header.unk2 = _file->readUint16LE();
+ _header.freq = _file->readUint16LE();
+ _header.channels = _file->readByte();
+ _header.bits = _file->readByte();
+ _header.unk3 = _file->readUint32LE();
+ _header.unk4 = _file->readUint16LE();
+ _header.maxCBFZSize = _file->readUint32LE();
+ _header.unk5 = _file->readUint32LE();
// Kyrandia 3 uses version 1 VQA files, and is the only
// known game to do so. This version of the format has
@@ -302,7 +303,7 @@ bool VQAMovie::open(const char *filename) {
foundFrameInfo = true;
for (int i = 0; i < _header.numFrames; i++) {
- _frameInfo[i] = 2 * _file.readUint32LE();
+ _frameInfo[i] = 2 * _file->readUint32LE();
}
// HACK: This flag is set in jung2.vqa, and its
@@ -318,31 +319,31 @@ bool VQAMovie::open(const char *filename) {
// to the first VQFR chunk.
if (_frameInfo[0] & 0x01000000) {
- uint32 oldPos = _file.pos();
+ uint32 oldPos = _file->pos();
while (1) {
uint32 scanTag = readTag();
- uint32 scanSize = _file.readUint32BE();
+ uint32 scanSize = _file->readUint32BE();
- if (_file.eof())
+ if (_file->eos())
break;
if (scanTag == MKID_BE('VQFR')) {
- _frameInfo[0] = (_file.pos() - 8) | 0x80000000;
+ _frameInfo[0] = (_file->pos() - 8) | 0x80000000;
break;
}
- _file.seek(scanSize, SEEK_CUR);
+ _file->seek(scanSize, SEEK_CUR);
}
- _file.seek(oldPos);
+ _file->seek(oldPos);
}
break;
default:
warning("VQAMovie::open: Unknown tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF));
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
}
}
@@ -373,8 +374,8 @@ void VQAMovie::close() {
_vectorPointers = NULL;
_stream = NULL;
- if (_file.isOpen())
- _file.close();
+ delete _file;
+ _file = 0;
freeBuffers();
@@ -391,13 +392,13 @@ void VQAMovie::displayFrame(uint frameNum) {
bool foundFrame = false;
uint i;
- _file.seek(_frameInfo[frameNum] & 0x7FFFFFFF);
+ _file->seek(_frameInfo[frameNum] & 0x7FFFFFFF);
while (!foundSound || !foundFrame) {
uint32 tag = readTag();
- uint32 size = _file.readUint32BE();
+ uint32 size = _file->readUint32BE();
- if (_file.eof()) {
+ if (_file->eos()) {
// This happens at the last frame. Apparently it has
// no sound?
break;
@@ -405,24 +406,24 @@ void VQAMovie::displayFrame(uint frameNum) {
byte *inbuf, *outbuf;
uint32 insize, outsize;
- uint32 end;
+ int32 end;
switch (tag) {
case MKID_BE('SND0'): // Uncompressed sound
foundSound = true;
inbuf = new byte[size];
- _file.read(inbuf, size);
+ _file->read(inbuf, size);
assert(_stream);
_stream->queueBuffer(inbuf, size);
break;
case MKID_BE('SND1'): // Compressed sound, almost like AUD
foundSound = true;
- outsize = _file.readUint16LE();
- insize = _file.readUint16LE();
+ outsize = _file->readUint16LE();
+ insize = _file->readUint16LE();
inbuf = new byte[insize];
- _file.read(inbuf, insize);
+ _file->read(inbuf, insize);
if (insize == outsize) {
assert(_stream);
@@ -439,50 +440,50 @@ void VQAMovie::displayFrame(uint frameNum) {
case MKID_BE('SND2'): // Compressed sound
foundSound = true;
warning("VQAMovie::displayFrame: `SND2' is not implemented");
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
case MKID_BE('VQFR'):
foundFrame = true;
- end = _file.pos() + size - 8;
+ end = _file->pos() + size - 8;
- while (_file.pos() < end) {
+ while (_file->pos() < end) {
tag = readTag();
- size = _file.readUint32BE();
+ size = _file->readUint32BE();
switch (tag) {
case MKID_BE('CBF0'): // Full codebook
- _file.read(_codeBook, size);
+ _file->read(_codeBook, size);
break;
case MKID_BE('CBFZ'): // Full codebook
inbuf = (byte *)allocBuffer(0, size);
- _file.read(inbuf, size);
+ _file->read(inbuf, size);
Screen::decodeFrame4(inbuf, _codeBook, _codeBookSize);
break;
case MKID_BE('CBP0'): // Partial codebook
_compressedCodeBook = false;
- _file.read(_partialCodeBook + _partialCodeBookSize, size);
+ _file->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
case MKID_BE('CBPZ'): // Partial codebook
_compressedCodeBook = true;
- _file.read(_partialCodeBook + _partialCodeBookSize, size);
+ _file->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
case MKID_BE('CPL0'): // Palette
assert(size <= 3 * 256);
- _file.read(_vm->screen()->_currentPalette, size);
+ _file->read(_vm->screen()->_currentPalette, size);
break;
case MKID_BE('CPLZ'): // Palette
inbuf = (byte *)allocBuffer(0, size);
- _file.read(inbuf, size);
+ _file->read(inbuf, size);
Screen::decodeFrame4(inbuf, _vm->screen()->_currentPalette, 768);
break;
@@ -490,14 +491,14 @@ void VQAMovie::displayFrame(uint frameNum) {
assert(size / 2 <= _numVectorPointers);
for (i = 0; i < size / 2; i++)
- _vectorPointers[i] = _file.readUint16LE();
+ _vectorPointers[i] = _file->readUint16LE();
break;
case MKID_BE('VPTZ'): // Frame data
inbuf = (byte *)allocBuffer(0, size);
outbuf = (byte *)allocBuffer(1, 2 * _numVectorPointers);
- _file.read(inbuf, size);
+ _file->read(inbuf, size);
size = Screen::decodeFrame4(inbuf, outbuf, 2 * _numVectorPointers);
assert(size / 2 <= _numVectorPointers);
@@ -508,7 +509,7 @@ void VQAMovie::displayFrame(uint frameNum) {
default:
warning("VQAMovie::displayFrame: Unknown `VQFR' sub-tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF));
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
}
@@ -518,7 +519,7 @@ void VQAMovie::displayFrame(uint frameNum) {
default:
warning("VQAMovie::displayFrame: Unknown tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF));
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
}
}
@@ -593,11 +594,11 @@ void VQAMovie::play() {
uint32 insize, outsize;
if (_stream) {
- while (_file.pos() < (_frameInfo[0] & 0x7FFFFFFF)) {
+ while ((uint)_file->pos() < (_frameInfo[0] & 0x7FFFFFFF)) {
uint32 tag = readTag();
- uint32 size = _file.readUint32BE();
+ uint32 size = _file->readUint32BE();
- if (_file.eof()) {
+ if (_file->eos()) {
warning("VQAMovie::play: Unexpected EOF");
break;
}
@@ -605,16 +606,16 @@ void VQAMovie::play() {
switch (tag) {
case MKID_BE('SND0'): // Uncompressed sound
inbuf = new byte[size];
- _file.read(inbuf, size);
+ _file->read(inbuf, size);
_stream->queueBuffer(inbuf, size);
break;
case MKID_BE('SND1'): // Compressed sound
- outsize = _file.readUint16LE();
- insize = _file.readUint16LE();
+ outsize = _file->readUint16LE();
+ insize = _file->readUint16LE();
inbuf = new byte[insize];
- _file.read(inbuf, insize);
+ _file->read(inbuf, insize);
if (insize == outsize) {
_stream->queueBuffer(inbuf, insize);
@@ -628,17 +629,17 @@ void VQAMovie::play() {
case MKID_BE('SND2'): // Compressed sound
warning("VQAMovie::play: `SND2' is not implemented");
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
case MKID_BE('CMDS'): // Unused tag, always empty in kyra3
debugC(9, kDebugLevelMovie, "VQAMovie::play: skipping CMDS tag");
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
default:
warning("VQAMovie::play: Unknown tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF));
- _file.seek(size, SEEK_CUR);
+ _file->seek(size, SEEK_CUR);
break;
}
}
@@ -671,8 +672,8 @@ void VQAMovie::play() {
if (event.kbd.ascii == 27)
return;
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->quitGame();
return;
default:
break;
diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h
index f600f008b7..46d3bd48fb 100644
--- a/engines/kyra/vqa.h
+++ b/engines/kyra/vqa.h
@@ -26,6 +26,8 @@
#ifndef KYRA_VQA_H
#define KYRA_VQA_H
+#include "common/stream.h"
+
class OSystem;
namespace Kyra {
@@ -98,7 +100,7 @@ protected:
void displayFrame(uint frameNum);
- Common::File _file;
+ Common::SeekableReadStream *_file;
VQAHeader _header;
uint32 *_frameInfo;
diff --git a/engines/lure/animseq.cpp b/engines/lure/animseq.cpp
index 2af02b0374..f9f53b2806 100644
--- a/engines/lure/animseq.cpp
+++ b/engines/lure/animseq.cpp
@@ -44,12 +44,18 @@ AnimAbortType AnimationSequence::delay(uint32 milliseconds) {
while (g_system->getMillis() < delayCtr) {
while (events.pollEvent()) {
if ((events.type() == Common::EVENT_KEYDOWN) && (events.event().kbd.ascii != 0)) {
- if (events.event().kbd.keycode == Common::KEYCODE_ESCAPE) return ABORT_END_INTRO;
- else return ABORT_NEXT_SCENE;
- } else if (events.type() == Common::EVENT_LBUTTONDOWN)
+ if (events.event().kbd.keycode == Common::KEYCODE_ESCAPE)
+ return ABORT_END_INTRO;
+ else
+ return ABORT_NEXT_SCENE;
+ } else if (events.type() == Common::EVENT_LBUTTONDOWN) {
return ABORT_NEXT_SCENE;
- else if (events.type() == Common::EVENT_QUIT)
+ } else if ((events.type() == Common::EVENT_QUIT) || (events.type() == Common::EVENT_RTL)) {
return ABORT_END_INTRO;
+ } else if (events.type() == Common::EVENT_MAINMENU) {
+ return ABORT_NONE;
+ }
+
}
uint32 delayAmount = delayCtr - g_system->getMillis();
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index 7dd1c77348..163d095243 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -26,6 +26,7 @@
#include "base/plugins.h"
#include "common/advancedDetector.h"
+#include "common/savefile.h"
#include "lure/lure.h"
@@ -184,9 +185,20 @@ public:
return "Lure of the Temptress (C) Revolution";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
};
+bool LureMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
bool LureMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Lure::LureGameDescription *gd = (const Lure::LureGameDescription *)desc;
if (gd) {
@@ -195,6 +207,44 @@ bool LureMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
+SaveStateList LureMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ Common::String saveDesc;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ saveDesc = Lure::getSaveName(in);
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void LureMetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".%03d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
#if PLUGIN_ENABLED_DYNAMIC(LURE)
REGISTER_PLUGIN_DYNAMIC(LURE, PLUGIN_TYPE_ENGINE, LureMetaEngine);
#else
diff --git a/engines/lure/events.cpp b/engines/lure/events.cpp
index 30e0e571b7..e244f69097 100644
--- a/engines/lure/events.cpp
+++ b/engines/lure/events.cpp
@@ -29,6 +29,7 @@
#include "graphics/cursorman.h"
#include "lure/events.h"
+#include "lure/lure.h"
#include "lure/res.h"
namespace Lure {
@@ -137,11 +138,12 @@ void Mouse::setPosition(int newX, int newY) {
void Mouse::waitForRelease() {
Events &e = Events::getReference();
+ LureEngine &engine = LureEngine::getReference();
do {
- while (e.pollEvent() && !e.quitFlag) ;
+ while (e.pollEvent() && !engine.quit()) ;
g_system->delayMillis(20);
- } while (!e.quitFlag && (lButton() || rButton() || mButton()));
+ } while (!engine.quit() && (lButton() || rButton() || mButton()));
}
/*--------------------------------------------------------------------------*/
@@ -150,7 +152,6 @@ static Events *int_events = NULL;
Events::Events() {
int_events = this;
- quitFlag = false;
}
Events &Events::getReference() {
@@ -163,10 +164,6 @@ bool Events::pollEvent() {
// Handle keypress
switch (_event.type) {
- case Common::EVENT_QUIT:
- quitFlag = true;
- break;
-
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONDOWN:
@@ -190,7 +187,7 @@ void Events::waitForPress() {
bool keyButton = false;
while (!keyButton) {
while (pollEvent()) {
- if (_event.type == Common::EVENT_QUIT) return;
+ if ((_event.type == Common::EVENT_QUIT) || (_event.type == Common::EVENT_RTL)) return;
else if ((_event.type == Common::EVENT_KEYDOWN) && (_event.kbd.ascii != 0))
keyButton = true;
else if ((_event.type == Common::EVENT_LBUTTONDOWN) ||
@@ -210,10 +207,11 @@ void Events::waitForPress() {
bool Events::interruptableDelay(uint32 milliseconds) {
Events &events = Events::getReference();
+ LureEngine &engine = LureEngine::getReference();
uint32 delayCtr = g_system->getMillis() + milliseconds;
while (g_system->getMillis() < delayCtr) {
- if (events.quitFlag) return true;
+ if (engine.quit()) return true;
if (events.pollEvent()) {
if (((events.type() == Common::EVENT_KEYDOWN) && (events.event().kbd.ascii != 0)) ||
diff --git a/engines/lure/events.h b/engines/lure/events.h
index d1246f95d8..f04072aa0f 100644
--- a/engines/lure/events.h
+++ b/engines/lure/events.h
@@ -66,8 +66,6 @@ class Events {
private:
Common::Event _event;
public:
- bool quitFlag;
-
Events();
static Events &getReference();
diff --git a/engines/lure/fights.cpp b/engines/lure/fights.cpp
index dcf09ba50d..51fce850e6 100644
--- a/engines/lure/fights.cpp
+++ b/engines/lure/fights.cpp
@@ -22,6 +22,7 @@
#include "lure/fights.h"
#include "lure/luredefs.h"
#include "lure/game.h"
+#include "lure/lure.h"
#include "lure/res.h"
#include "lure/room.h"
#include "lure/sound.h"
@@ -108,15 +109,15 @@ bool FightsManager::isFighting() {
}
void FightsManager::fightLoop() {
+ LureEngine &engine = LureEngine::getReference();
Resources &res = Resources::getReference();
Game &game = Game::getReference();
Room &room = Room::getReference();
- Events &events = Events::getReference();
FighterRecord &playerFight = getDetails(PLAYER_ID);
uint32 timerVal = g_system->getMillis();
// Loop for the duration of the battle
- while (!events.quitFlag && (playerFight.fwhits != GENERAL_MAGIC_ID)) {
+ while (!engine.quit() && (playerFight.fwhits != GENERAL_MAGIC_ID)) {
checkEvents();
if (g_system->getMillis() > timerVal + GAME_FRAME_DELAY) {
@@ -184,6 +185,7 @@ const KeyMapping keyList[] = {
{Common::KEYCODE_INVALID, 0}};
void FightsManager::checkEvents() {
+ LureEngine &engine = LureEngine::getReference();
Game &game = Game::getReference();
Events &events = Events::getReference();
Mouse &mouse = Mouse::getReference();
@@ -196,7 +198,7 @@ void FightsManager::checkEvents() {
if (events.type() == Common::EVENT_KEYDOWN) {
switch (events.event().kbd.keycode) {
case Common::KEYCODE_ESCAPE:
- events.quitFlag = true;
+ engine.quitGame();
return;
case Common::KEYCODE_d:
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp
index f9b31c21c5..479877f229 100644
--- a/engines/lure/game.cpp
+++ b/engines/lure/game.cpp
@@ -23,10 +23,10 @@
*
*/
-#include "lure/lure.h"
#include "lure/game.h"
#include "lure/animseq.h"
#include "lure/fights.h"
+#include "lure/lure.h"
#include "lure/res_struct.h"
#include "lure/room.h"
#include "lure/scripts.h"
@@ -125,6 +125,7 @@ void Game::nextFrame() {
void Game::execute() {
OSystem &system = *g_system;
+ LureEngine &engine = LureEngine::getReference();
Room &room = Room::getReference();
Resources &res = Resources::getReference();
Events &events = Events::getReference();
@@ -137,12 +138,20 @@ void Game::execute() {
screen.empty();
screen.setPaletteEmpty();
+
+ bool _loadSavegame = false;
+
+ if (engine.gameToLoad() != -1)
+ _loadSavegame = engine.loadGame(engine.gameToLoad());
+
+ if (!_loadSavegame) {
+ // Flag for starting game
+ setState(GS_RESTART);
+ }
- // Flag for starting game
- setState(GS_RESTART);
bool initialRestart = true;
- while (!events.quitFlag) {
+ while (!engine.quit()) {
if ((_state & GS_RESTART) != 0) {
res.reset();
@@ -162,7 +171,7 @@ void Game::execute() {
mouse.cursorOn();
// Main game loop
- while (!events.quitFlag && ((_state & GS_RESTART) == 0)) {
+ while (!engine.quit() && ((_state & GS_RESTART) == 0)) {
// If time for next frame, allow everything to update
if (system.getMillis() > timerVal + GAME_FRAME_DELAY) {
timerVal = system.getMillis();
@@ -291,10 +300,7 @@ void Game::execute() {
if (restartFlag)
setState(GS_RESTART);
-
- } else if ((_state & GS_RESTART) == 0)
- // Exiting game
- events.quitFlag = true;
+ }
}
}
@@ -892,7 +898,7 @@ void Game::doShowCredits() {
void Game::doQuit() {
Sound.pause();
if (getYN())
- Events::getReference().quitFlag = true;
+ LureEngine::getReference().quitGame();
Sound.resume();
}
@@ -977,6 +983,7 @@ bool Game::getYN() {
Events &events = Events::getReference();
Screen &screen = Screen::getReference();
Resources &res = Resources::getReference();
+ LureEngine &engine = LureEngine::getReference();
Common::Language l = LureEngine::getReference().getLanguage();
Common::KeyCode y = Common::KEYCODE_y;
@@ -1018,7 +1025,7 @@ bool Game::getYN() {
}
g_system->delayMillis(10);
- } while (!events.quitFlag && !breakFlag);
+ } while (!engine.quit() && !breakFlag);
screen.update();
if (!vKbdFlag)
diff --git a/engines/lure/game.h b/engines/lure/game.h
index 5054074fb2..06dcee750f 100644
--- a/engines/lure/game.h
+++ b/engines/lure/game.h
@@ -27,6 +27,7 @@
#define LURE_GAME_H
+#include "common/config-manager.h"
#include "engines/engine.h"
#include "lure/luredefs.h"
#include "lure/menu.h"
@@ -85,8 +86,8 @@ public:
bool &debugFlag() { return _debugFlag; }
bool fastTextFlag() { return _fastTextFlag; }
bool soundFlag() { return _soundFlag; }
- uint8 sfxVolume() { return _sfxVolume; }
- uint8 musicVolume() { return _musicVolume; }
+ uint8 sfxVolume() { return ConfMan.getInt("sfx_volume"); }
+ uint8 musicVolume() { return ConfMan.getInt("music_volume"); }
Debugger &debugger() { return *_debugger; }
// Menu item support methods
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index 4d3e172dc5..b4cbf4a833 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -55,17 +55,18 @@ static const AnimRecord anim_screens[] = {
bool Introduction::showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize) {
Screen &screen = Screen::getReference();
- Events &events = Events::getReference();
bool isEGA = LureEngine::getReference().isEGA();
screen.screen().loadScreen(screenId);
screen.update();
Palette p(paletteId);
+ if (LureEngine::getReference().quit()) return true;
+
if (isEGA) screen.setPalette(&p);
else screen.paletteFadeIn(&p);
bool result = interruptableDelay(delaySize);
- if (events.quitFlag) return true;
+ if (LureEngine::getReference().quit()) return true;
if (!isEGA)
screen.paletteFadeOut();
@@ -83,6 +84,8 @@ bool Introduction::interruptableDelay(uint32 milliseconds) {
if (events.interruptableDelay(milliseconds)) {
if (events.type() == Common::EVENT_KEYDOWN)
return events.event().kbd.keycode == 27;
+ else if (LureEngine::getReference().quit())
+ return true;
else if (events.type() == Common::EVENT_LBUTTONDOWN)
return false;
}
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index ea760ddb4f..8cd76cbc73 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -92,6 +92,7 @@ int LureEngine::init() {
_room = new Room();
_fights = new FightsManager();
+ _gameToLoad = -1;
_initialised = true;
return 0;
}
@@ -121,31 +122,38 @@ LureEngine &LureEngine::getReference() {
}
int LureEngine::go() {
-
- if (ConfMan.getBool("copy_protection")) {
- CopyProtectionDialog *dialog = new CopyProtectionDialog();
- bool result = dialog->show();
- delete dialog;
- if (_events->quitFlag)
- return 0;
-
- if (!result)
- error("Sorry - copy protection failed");
- }
-
Game *gameInstance = new Game();
+
+ // If requested, load a savegame instead of showing the intro
+ if (ConfMan.hasKey("save_slot")) {
+ _gameToLoad = ConfMan.getInt("save_slot");
+ if (_gameToLoad < 0 || _gameToLoad > 999)
+ _gameToLoad = -1;
+ }
+
+ if (_gameToLoad == -1) {
+ if (ConfMan.getBool("copy_protection")) {
+ CopyProtectionDialog *dialog = new CopyProtectionDialog();
+ bool result = dialog->show();
+ delete dialog;
+ if (quit())
+ return 0;
+
+ if (!result)
+ error("Sorry - copy protection failed");
+ }
- if (ConfMan.getInt("boot_param") == 0) {
- // Show the introduction
- Sound.loadSection(Sound.isRoland() ? ROLAND_INTRO_SOUND_RESOURCE_ID : ADLIB_INTRO_SOUND_RESOURCE_ID);
-
- Introduction *intro = new Introduction();
- intro->show();
- delete intro;
+ if (ConfMan.getInt("boot_param") == 0) {
+ // Show the introduction
+ Sound.loadSection(Sound.isRoland() ? ROLAND_INTRO_SOUND_RESOURCE_ID : ADLIB_INTRO_SOUND_RESOURCE_ID);
+ Introduction *intro = new Introduction();
+ intro->show();
+ delete intro;
+ }
}
// Play the game
- if (!_events->quitFlag) {
+ if (!quit()) {
// Play the game
Sound.loadSection(Sound.isRoland() ? ROLAND_MAIN_SOUND_RESOURCE_ID : ADLIB_MAIN_SOUND_RESOURCE_ID);
gameInstance->execute();
@@ -246,6 +254,10 @@ void LureEngine::GUIError(const char *msg, ...) {
Engine::GUIErrorMessage(buffer);
}
+void LureEngine::syncSoundSettings() {
+ Sound.syncSounds();
+}
+
Common::String *LureEngine::detectSave(int slotNumber) {
Common::ReadStream *f = this->_saveFileMan->openForLoading(
generateSaveName(slotNumber));
@@ -274,4 +286,23 @@ Common::String *LureEngine::detectSave(int slotNumber) {
return result;
}
+Common::String getSaveName(Common::InSaveFile *in) {
+ // Check for header
+ char saveName[MAX_DESC_SIZE];
+ char buffer[5];
+ in->read(&buffer[0], 5);
+ if (memcmp(&buffer[0], "lure", 5) == 0) {
+ // Check language version
+ in->readByte();
+ in->readByte();
+ char *p = saveName;
+ int decCtr = MAX_DESC_SIZE - 1;
+ while ((decCtr > 0) && ((*p++ = in->readByte()) != 0)) --decCtr;
+ *p = '\0';
+
+ }
+
+ return Common::String(saveName);
+}
+
} // End of namespace Lure
diff --git a/engines/lure/lure.h b/engines/lure/lure.h
index 1c5b40e54b..2c1a70329e 100644
--- a/engines/lure/lure.h
+++ b/engines/lure/lure.h
@@ -30,6 +30,7 @@
#include "common/rect.h"
#include "sound/mixer.h"
#include "common/file.h"
+#include "common/savefile.h"
#include "lure/disk.h"
#include "lure/res.h"
@@ -47,6 +48,7 @@ struct LureGameDescription;
class LureEngine : public Engine {
private:
bool _initialised;
+ int _gameToLoad;
uint8 _saveVersion;
Disk *_disk;
Resources *_resources;
@@ -70,9 +72,11 @@ public:
virtual int init();
virtual int go();
virtual void pauseEngineIntern(bool pause);
+ virtual void syncSoundSettings();
Disk &disk() { return *_disk; }
+ int gameToLoad() { return _gameToLoad; }
bool loadGame(uint8 slotNumber);
bool saveGame(uint8 slotNumber, Common::String &caption);
Common::String *detectSave(int slotNumber);
@@ -84,7 +88,7 @@ public:
Common::Platform getPlatform() const;
bool isEGA() const { return (getFeatures() & GF_EGA) != 0; }
};
-
+ Common::String getSaveName(Common::InSaveFile *in);
} // End of namespace Lure
#endif
diff --git a/engines/lure/menu.cpp b/engines/lure/menu.cpp
index 0b4ef06081..562f54da20 100644
--- a/engines/lure/menu.cpp
+++ b/engines/lure/menu.cpp
@@ -116,6 +116,7 @@ Menu &Menu::getReference() {
uint8 Menu::execute() {
OSystem &system = *g_system;
+ LureEngine &engine = LureEngine::getReference();
Mouse &mouse = Mouse::getReference();
Events &events = Events::getReference();
Screen &screen = Screen::getReference();
@@ -130,7 +131,7 @@ uint8 Menu::execute() {
while (mouse.lButton() || mouse.rButton()) {
while (events.pollEvent()) {
- if (events.quitFlag) return MENUITEM_NONE;
+ if (engine.quit()) return MENUITEM_NONE;
if (mouse.y() < MENUBAR_Y_SIZE) {
MenuRecord *p = getMenuAt(mouse.x());
@@ -467,6 +468,7 @@ Action PopupMenu::Show(int numEntries, Action *actions) {
uint16 PopupMenu::Show(int numEntries, const char *actions[]) {
if (numEntries == 0) return 0xffff;
+ LureEngine &engine = LureEngine::getReference();
Events &e = Events::getReference();
Mouse &mouse = Mouse::getReference();
OSystem &system = *g_system;
@@ -545,7 +547,7 @@ uint16 PopupMenu::Show(int numEntries, const char *actions[]) {
}
while (e.pollEvent()) {
- if (e.quitFlag) {
+ if (engine.quit()) {
selectedIndex = 0xffff;
goto bail_out;
diff --git a/engines/lure/scripts.cpp b/engines/lure/scripts.cpp
index 7490f05b24..495f8046bb 100644
--- a/engines/lure/scripts.cpp
+++ b/engines/lure/scripts.cpp
@@ -26,6 +26,7 @@
#include "lure/animseq.h"
#include "lure/fights.h"
#include "lure/game.h"
+#include "lure/lure.h"
#include "lure/res.h"
#include "lure/room.h"
#include "lure/screen.h"
@@ -190,6 +191,7 @@ void Script::addSound(uint16 soundIndex, uint16 v2, uint16 v3) {
}
void Script::endgameSequence(uint16 v1, uint16 v2, uint16 v3) {
+ LureEngine &engine = LureEngine::getReference();
Screen &screen = Screen::getReference();
Mouse &mouse = Mouse::getReference();
Events &events = Events::getReference();
@@ -219,7 +221,7 @@ void Script::endgameSequence(uint16 v1, uint16 v2, uint16 v3) {
anim->show();
if (!events.interruptableDelay(30000)) {
// No key yet pressed, so keep waiting
- while (Sound.musicInterface_CheckPlaying(6) && !events.quitFlag) {
+ while (Sound.musicInterface_CheckPlaying(6) && !engine.quit()) {
if (events.interruptableDelay(20))
break;
}
@@ -227,7 +229,7 @@ void Script::endgameSequence(uint16 v1, uint16 v2, uint16 v3) {
delete anim;
screen.paletteFadeOut();
- events.quitFlag = true;
+ engine.quitGame();
}
// Setup the pig fight in the cave
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 285f66e4e2..569058b282 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -220,10 +220,12 @@ void SoundManager::addSound(uint8 soundIndex, bool tidyFlag) {
newEntry->channel = channelCtr;
newEntry->numChannels = numChannels;
newEntry->flags = rec.flags;
+
if (_isRoland)
newEntry->volume = rec.volume;
else /* resource volumes do not seem to work well with our adlib emu */
newEntry->volume = 240; /* 255 causes clipping with adlib */
+
_activeSounds.push_back(SoundList::value_type(newEntry));
musicInterface_Play(rec.soundNumber, channelCtr, numChannels);
@@ -280,6 +282,23 @@ uint8 SoundManager::descIndexOf(uint8 soundNumber) {
return 0xff; // Couldn't find entry
}
+// Used to sync the volume for all channels with the Config Manager
+//
+void SoundManager::syncSounds() {
+ Game &game = Game::getReference();
+ musicInterface_TidySounds();
+
+ g_system->lockMutex(_soundMutex);
+ MusicListIterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ if ((*i)->isMusic())
+ (*i)->setVolume(game.musicVolume());
+ else
+ (*i)->setVolume(game.sfxVolume());
+ }
+ g_system->unlockMutex(_soundMutex);
+}
+
SoundDescResource *SoundManager::findSound(uint8 soundNumber) {
debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::findSound soundNumber=%d", soundNumber);
SoundListIterator i;
@@ -402,9 +421,8 @@ void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, u
return;
bool isMusic = (soundNumber & 0x80) != 0;
- uint8 volume = isMusic ? game.musicVolume() : game.sfxVolume();
- if (!game.soundFlag() || (volume == 0))
+ if (!game.soundFlag())
// Don't play sounds if sound is turned off
return;
@@ -563,12 +581,12 @@ void SoundManager::doTimer() {
/*------------------------------------------------------------------------*/
MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
- uint8 channelNum, uint8 soundNum, bool isMusic, uint8 numChannels, void *soundData, uint32 size) {
+ uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size) {
_driver = driver;
_channels = channels;
_soundNumber = soundNum;
_channelNumber = channelNum;
- _isMusic = isMusic;
+ _isMusic = isMus;
_numChannels = numChannels;
_volume = 0;
@@ -576,7 +594,11 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
/* 90 is power on default for midi compliant devices */
_channels[_channelNumber + i].volume = 90;
}
- setVolume(240); /* 255 causes clipping with mastervol 192 and adlib */
+
+ if (_isMusic)
+ setVolume(ConfMan.getInt("music_volume"));
+ else
+ setVolume(ConfMan.getInt("sfx_volume"));
_passThrough = false;
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index c5a31a6c28..cf5dca7e96 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -66,7 +66,7 @@ private:
public:
MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
- uint8 channelNum, uint8 soundNum, bool isMusic, uint8 numChannels, void *soundData, uint32 size);
+ uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size);
~MidiMusic();
void setVolume(int volume);
int getVolume() { return _volume; }
@@ -98,6 +98,7 @@ public:
uint8 channelNumber() { return _channelNumber; }
uint8 soundNumber() { return _soundNumber; }
bool isPlaying() { return _isPlaying; }
+ bool isMusic() {return _isMusic; }
};
class SoundManager: public Common::Singleton<SoundManager> {
@@ -142,6 +143,7 @@ public:
void stopSound(uint8 soundIndex);
void killSound(uint8 soundNumber);
void setVolume(uint8 soundNumber, uint8 volume);
+ void syncSounds();
void tidySounds();
uint8 descIndexOf(uint8 soundNumber);
SoundDescResource *findSound(uint8 soundNumber);
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index 64394545d1..23cc9043cf 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -506,6 +506,7 @@ Surface *Surface::getScreen(uint16 resourceId) {
bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool varLength, int16 x, int16 y) {
OSystem &system = *g_system;
+ LureEngine &engine = LureEngine::getReference();
Mouse &mouse = Mouse::getReference();
Events &events = Events::getReference();
Screen &screen = Screen::getReference();
@@ -533,7 +534,7 @@ bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool
// Loop until the input string changes
refreshFlag = false;
while (!refreshFlag && !abortFlag) {
- abortFlag = events.quitFlag;
+ abortFlag = engine.quit();
if (abortFlag) break;
while (events.pollEvent()) {
@@ -975,7 +976,7 @@ bool SaveRestoreDialog::show(bool saveDialog) {
// Provide highlighting of lines to select a save slot
while (!abortFlag && !(mouse.lButton() && (selectedLine != -1))
&& !mouse.rButton() && !mouse.mButton()) {
- abortFlag = events.quitFlag;
+ abortFlag = engine.quit();
if (abortFlag) break;
while (events.pollEvent()) {
@@ -1178,7 +1179,7 @@ bool RestartRestoreDialog::show() {
// Event loop for making selection
bool buttonPressed = false;
- while (!events.quitFlag) {
+ while (!engine.quit()) {
// Handle events
while (events.pollEvent()) {
if ((events.type() == Common::EVENT_LBUTTONDOWN) && (highlightedButton != -1)) {
@@ -1230,7 +1231,7 @@ bool RestartRestoreDialog::show() {
Sound.killSounds();
- if (!restartFlag && !events.quitFlag) {
+ if (!restartFlag && !engine.quit()) {
// Need to show Restore game dialog
if (!SaveRestoreDialog::show(false))
// User cancelled, so fall back on Restart
@@ -1299,6 +1300,7 @@ bool CopyProtectionDialog::show() {
Screen &screen = Screen::getReference();
Events &events = Events::getReference();
Common::RandomSource rnd;
+ LureEngine &engine = LureEngine::getReference();
screen.setPaletteEmpty();
Palette p(COPY_PROTECTION_RESOURCE_ID - 1);
@@ -1349,7 +1351,7 @@ bool CopyProtectionDialog::show() {
// Clear any prior try
_charIndex = 0;
- while (!events.quitFlag) {
+ while (!engine.quit()) {
while (events.pollEvent() && (_charIndex < 4)) {
if (events.type() == Common::EVENT_KEYDOWN) {
if ((events.event().kbd.keycode == Common::KEYCODE_BACKSPACE) && (_charIndex > 0)) {
@@ -1383,7 +1385,7 @@ bool CopyProtectionDialog::show() {
break;
}
- if (events.quitFlag)
+ if (engine.quit())
return false;
// At this point, two page numbers have been entered - validate them
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index 5b8bdab9d6..11131783e2 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -406,10 +406,12 @@ void Converse::loadConversation(const char *convName) {
convS->read(buffer, 8);
if (debugFlag) printf("Conversation name: %s\n", buffer);
- while(!convS->eos()) {
+ while(true) {
chunkPos = convS->pos();
- if (debugFlag) printf("***** Pos: %i -> ", chunkPos);
chunk = convS->readUint32LE(); // read chunk
+ if (convS->eos()) break;
+
+ if (debugFlag) printf("***** Pos: %i -> ", chunkPos);
switch(chunk) {
case CHUNK_DECL: // Declare
if (debugFlag) printf("DECL chunk\n");
@@ -544,10 +546,10 @@ void Converse::loadConversation(const char *convName) {
curNode, _convNodes[curNode]->entries.size() - 1);
// Seek to chunk data (i.e. TEXT/MESG tag, which is usually right
// after this chunk but it can be further on in conditional reply chunks
- assert(data >= convS->pos());
+ assert((int)data >= convS->pos());
// If the entry's data is not right after the entry, remember the position
// to return to after the data is read
- if (chunk == CHUNK_CRPL && data != convS->pos())
+ if (chunk == CHUNK_CRPL && (int)data != convS->pos())
returnAddress = convS->pos();
convS->seek(data, SEEK_SET);
}
@@ -714,7 +716,7 @@ void Converse::loadConversationMads(const char *convName) {
printf("Chunk 0\n");
printf("Conv stream size: %i\n", convS->size());
- while(!convS->eos()) {
+ while(!convS->eos()) { // FIXME (eos changed)
printf("%i ", convS->readByte());
}
printf("\n");
@@ -725,7 +727,7 @@ void Converse::loadConversationMads(const char *convName) {
printf("Chunk 1\n");
printf("Conv stream size: %i\n", convS->size());
- while(!convS->eos()) {
+ while(!convS->eos()) { // FIXME (eos changed)
printf("%i ", convS->readByte());
}
printf("\n");
@@ -736,7 +738,7 @@ void Converse::loadConversationMads(const char *convName) {
printf("Chunk 2\n");
printf("Conv stream size: %i\n", convS->size());
- while(!convS->eos()) {
+ while(!convS->eos()) { // FIXME (eos changed)
printf("%i ", convS->readByte());
}
printf("\n");
@@ -790,7 +792,7 @@ void Converse::loadConversationMads(const char *convName) {
convS->read(buffer, 14); // speech file
printf("Speech file: %s\n", buffer);
- while(!convS->eos()) {
+ while(!convS->eos()) { // FIXME: eos changed
printf("%i ", convS->readByte());
}
printf("\n");
@@ -803,9 +805,12 @@ void Converse::loadConversationMads(const char *convName) {
printf("Chunk 1: conversation nodes\n");
printf("Conv stream size: %i\n", convS->size());
- while(!convS->eos()) {
+ while(true) {
+ uint16 id = convS->readUint16LE();
+ if (convS->eos()) break;
+
curEntry = new ConvEntry();
- curEntry->id = convS->readUint16LE();
+ curEntry->id = id;
curEntry->entryCount = convS->readUint16LE();
curEntry->flags = convS->readUint16LE();
if (curEntry->entryCount == 1 && curEntry->flags != 65535) {
@@ -839,10 +844,13 @@ void Converse::loadConversationMads(const char *convName) {
*buffer = 0;
- while(!convS->eos()) {
+ while(true) {
//if (curPos == 0)
// printf("%i: Offset %i: ", _convStrings.size(), convS->pos());
- buffer[curPos++] = convS->readByte();
+ uint8 b = convS->readByte();
+ if (convS->eos()) break;
+
+ buffer[curPos++] = b;
if (buffer[curPos - 1] == '~') { // filter out special characters
curPos--;
continue;
@@ -892,9 +900,12 @@ void Converse::loadConversationMads(const char *convName) {
//printf("Chunk 3 - MESG chunk data\n");
//printf("Conv stream size: %i\n", convS->size());
- while(!convS->eos()) {
+ while(true) {
+ uint16 index = convS->readUint16LE();
+ if (convS->eos()) break;
+
curMessage = new MessageEntry();
- stringIndex = convS->readUint16LE();
+ stringIndex = index;
stringCount = convS->readUint16LE();
*buffer = 0;
//printf("Message: %i\n", _madsMessageList.size());
@@ -915,7 +926,7 @@ void Converse::loadConversationMads(const char *convName) {
convS = convData.getItemStream(6);
printf("Chunk 6\n");
printf("Conv stream size: %i\n", convS->size());
- /*while(!convS->eos()) {
+ /*while(!convS->eos()) { // FIXME (eos changed)
printf("%i ", convS->readByte());
printf("%i ", convS->readByte());
printf("%i ", convS->readByte());
@@ -954,8 +965,10 @@ void Converse::readConvEntryActions(Common::SubReadStream *convS, ConvEntry *cur
int messageIndex = 0;
int unk = 0;
- while(!convS->eos()) {
+ while(true) {
chunk = convS->readByte();
+ if (convS->eos()) break;
+
type = convS->readByte();
switch (chunk) {
diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp
index 58c68979d1..98d007f67e 100644
--- a/engines/m4/globals.cpp
+++ b/engines/m4/globals.cpp
@@ -295,8 +295,11 @@ void Globals::loadMadsVocab() {
char buffer[30];
strcpy(buffer, "");
- while(!vocabS->eos()) {
- buffer[curPos++] = vocabS->readByte();
+ while(true) {
+ uint8 b = vocabS->readByte();
+ if (vocabS->eos()) break;
+
+ buffer[curPos++] = b;
if (buffer[curPos - 1] == '\0') {
// end of string, add it to the strings list
_madsVocab.push_back(strdup(buffer));
@@ -315,8 +318,11 @@ void Globals::loadMadsQuotes() {
char buffer[128];
strcpy(buffer, "");
- while(!quoteS->eos()) {
- buffer[curPos++] = quoteS->readByte();
+ while(true) {
+ uint8 b = quoteS->readByte();
+ if (quoteS->eos()) break;
+
+ buffer[curPos++] = b;
if (buffer[curPos - 1] == '\0') {
// end of string, add it to the strings list
_madsQuotes.push_back(strdup(buffer));
diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp
index b2c0eda1ce..44d7f653d1 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -107,9 +107,9 @@ M4Engine::M4Engine(OSystem *syst, const M4GameDescription *gameDesc) :
// FIXME
_vm = this;
- Common::File::addDefaultDirectory(_gameDataPath);
- Common::File::addDefaultDirectory("goodstuf");
- Common::File::addDefaultDirectory("resource");
+ Common::File::addDefaultDirectory(_gameDataDir);
+ Common::File::addDefaultDirectory("goodstuf"); // FIXME: This is nonsense
+ Common::File::addDefaultDirectory("resource"); // FIXME: This is nonsense
Common::addSpecialDebugLevel(kDebugScript, "script", "Script debug level");
Common::addSpecialDebugLevel(kDebugConversations, "conversations", "Conversations debugging");
diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp
index c51daa84c4..71b45ca77c 100644
--- a/engines/m4/mads_anim.cpp
+++ b/engines/m4/mads_anim.cpp
@@ -247,15 +247,16 @@ void TextviewView::scriptDone() {
}
void TextviewView::processLines() {
+ _script->readLine_OLD(_currentLine, 79);
if (_script->eos())
error("Attempted to read past end of response file");
while (!_script->eos()) {
- _script->readLine(_currentLine, 79);
-
// Commented out line, so go loop for another
- if (_currentLine[0] == '#')
+ if (_currentLine[0] == '#') {
+ _script->readLine_OLD(_currentLine, 79);
continue;
+ }
// Process the line
char *cStart = strchr(_currentLine, '[');
@@ -284,6 +285,8 @@ void TextviewView::processLines() {
processText();
break;
}
+
+ _script->readLine_OLD(_currentLine, 79);
}
}
@@ -594,6 +597,7 @@ void AnimviewView::scriptDone() {
}
void AnimviewView::processLines() {
+ _script->readLine_OLD(_currentLine, 79);
if (_script->eos()) {
// end of script, end animation
scriptDone();
@@ -601,8 +605,6 @@ void AnimviewView::processLines() {
}
while (!_script->eos()) {
- _script->readLine(_currentLine, 79);
-
// Process the line
char *cStart = strchr(_currentLine, '-');
if (cStart) {
@@ -635,6 +637,8 @@ void AnimviewView::processLines() {
//printf("File: %s\n", _currentLine);
break;
}
+
+ _script->readLine_OLD(_currentLine, 79);
}
}
diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp
index 51dd8654ae..3f1da2a369 100644
--- a/engines/m4/midi.cpp
+++ b/engines/m4/midi.cpp
@@ -269,7 +269,7 @@ byte *MidiPlayer::convertHMPtoSMF(byte *data, uint32 inSize, uint32 &outSize) {
byte lastCmd = 0;
// Now we can finally convert the track
- uint32 endPos = readS.pos() + trackLength;
+ int32 endPos = readS.pos() + trackLength;
while (readS.pos() < endPos) {
// Convert the VLQ
byte vlq[4];
diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp
index 5070a2b79c..265e4dae0b 100644
--- a/engines/m4/resource.cpp
+++ b/engines/m4/resource.cpp
@@ -76,11 +76,11 @@ FileSystem::FileSystem(const char *hashFilename) {
}
/* load hagfile records and update the list */
- while (!hashFile.eof()) {
+ while (!hashFile.eos()) {
HashHagEntry entry;
hashFile.read(entry.filename, kM4MaxFilenameSize);
entry.fileIndex = hashFile.readByte();
- if (hashFile.eof())
+ if (hashFile.eos())
break;
changeExtension(_hagEntries[entry.fileIndex].filename, entry.filename, "HAG");
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index e5870bfeec..354e5bbb86 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -350,7 +350,7 @@ public:
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
- const Common::ADGameDescription *fallbackDetect(const FSList *fslist) const;
+ const Common::ADGameDescription *fallbackDetect(const Common::FSList *fslist) const;
};
@@ -362,7 +362,7 @@ bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
-const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const FSList *fslist) const {
+const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const Common::FSList *fslist) const {
// Set the default values for the fallback descriptor's ADGameDescription part.
Made::g_fallbackDesc.desc.language = Common::UNK_LANG;
Made::g_fallbackDesc.desc.platform = Common::kPlatformPC;
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index c3b36d3b8c..0b58a11774 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -63,6 +63,8 @@ void MusicPlayer::setVolume(int volume) {
_masterVolume = volume;
+ Common::StackLock lock(_mutex);
+
for (int i = 0; i < 16; ++i) {
if (_channel[i]) {
_channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
index 831f1fab8e..6fe0f1c80d 100644
--- a/engines/made/pmvplayer.cpp
+++ b/engines/made/pmvplayer.cpp
@@ -95,13 +95,13 @@ void PmvPlayer::play(const char *filename) {
// get it to work well?
_audioStream = Audio::makeAppendableAudioStream(soundFreq, Audio::Mixer::FLAG_UNSIGNED);
- while (!_abort && !_fd->eof()) {
+ while (!_abort && !_fd->eos()) {
int32 frameTime = _vm->_system->getMillis();
readChunk(chunkType, chunkSize);
- if (_fd->eof())
+ if (_fd->eos())
break;
frameData = new byte[chunkSize];
diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp
index 287574c312..a61d122041 100644
--- a/engines/made/redreader.cpp
+++ b/engines/made/redreader.cpp
@@ -55,9 +55,11 @@ Common::MemoryReadStream *RedReader::loadFromRed(const char *redFilename, const
bool RedReader::seekFile(Common::File &fd, FileEntry &fileEntry, const char *filename) {
char arcFilename[13];
- while (!fd.eof()) {
+ while (true) {
fd.skip(8); // skip unknown
fileEntry.compSize = fd.readUint32LE();
+ if (fd.eos()) break;
+
fileEntry.origSize = fd.readUint32LE();
fd.skip(10); // skip unknown
fd.read(arcFilename, 13);
diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp
index ee96af601a..6e9cf5c01a 100644
--- a/engines/made/screenfx.cpp
+++ b/engines/made/screenfx.cpp
@@ -132,7 +132,7 @@ void ScreenEffects::setBlendedPalette(byte *palette, byte *newPalette, int color
if (!_screen->isPaletteLocked()) {
int32 mulValue = (value * 64) / maxValue;
for (int i = 0; i < colorCount * 3; i++)
- _fxPalette[i] = CLIP(newPalette[i] - (newPalette[i] - palette[i]) * mulValue / 64, 0, 255);
+ _fxPalette[i] = CLIP<int32>(newPalette[i] - (newPalette[i] - palette[i]) * mulValue / 64, 0, 255);
_screen->setRGBPalette(_fxPalette, 0, 256);
}
}
diff --git a/engines/metaengine.h b/engines/metaengine.h
index aef860e0f9..3a9f930eec 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -28,14 +28,17 @@
#include "common/scummsys.h"
#include "common/str.h"
#include "common/error.h"
-#include "common/fs.h"
-#include "base/game.h"
+#include "engines/game.h"
#include "base/plugins.h"
class Engine;
class OSystem;
+namespace Common {
+ class FSList;
+}
+
/**
* A meta engine is essentially a factory for Engine instances with the
* added ability of listing and detecting supported games.
@@ -62,7 +65,7 @@ public:
* (possibly empty) list of games supported by the engine which it was able
* to detect amongst the given files.
*/
- virtual GameList detectGames(const FSList &fslist) const = 0;
+ virtual GameList detectGames(const Common::FSList &fslist) const = 0;
/**
* Tries to instantiate an engine instance based on the settings of
@@ -79,9 +82,9 @@ public:
/**
* Return a list of all save states associated with the given target.
*
- * In general, the caller will already have ensured that this (Meta)Engine
- * is responsible for the specified target by using findGame on it resp.
- * on the associated gameid from the relevant ConfMan entry, if present.
+ * The caller has to ensure that this (Meta)Engine is responsible
+ * for the specified target (by using findGame on it respectively
+ * on the associated gameid from the relevant ConfMan entry, if present).
*
* The default implementation returns an empty list.
*
@@ -91,6 +94,92 @@ public:
virtual SaveStateList listSaves(const char *target) const {
return SaveStateList();
}
+
+ /**
+ * Remove the specified save state.
+ *
+ * For most engines this just amounts to calling _saveFileMan->removeSaveFile().
+ * Engines which keep an index file will also update it accordingly.
+ *
+ * @param target name of a config manager target
+ * @param slot slot number of the save state to be removed
+ */
+ virtual void removeSaveState(const char *target, int slot) const {};
+
+ /**
+ * Returns meta infos from the specified save state.
+ *
+ * Depending on the MetaEngineFeatures set this can include
+ * thumbnails, save date / time, play time.
+ *
+ * @param target name of a config manager target
+ * @param slot slot number of the save state
+ */
+ virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const { return SaveStateDescriptor(); }
+
+ /** @name MetaEngineFeature flags */
+ //@{
+
+ /**
+ * A feature in this context means an ability of the engine which can be
+ * either available or not.
+ */
+ enum MetaEngineFeature {
+ /** 'Return to launcher' feature (i.e. EVENT_RTL is handled) */
+ kSupportsRTL = 0,
+
+ /**
+ * Listing Save States (i.e. implements the listSaves() method;
+ * used for --list-saves support)
+ */
+ kSupportsListSaves = 1,
+
+ /** Loading from the Launcher / command line (-x) */
+ kSupportsDirectLoad = 2,
+
+ /**
+ * Deleting Saves from the Launcher (i.e. implements the
+ * removeSaveState() method)
+ */
+ kSupportsDeleteSave = 3,
+
+ /**
+ * Features meta infos for savestates (i.e. implements the
+ * querySaveMetaInfos method properly)
+ */
+ kSupportsMetaInfos = 4,
+
+ /**
+ * Features a thumbnail in savegames (i.e. includes a thumbnail
+ * in savestates returned via querySaveMetaInfo).
+ * This flag may only be set when 'kSupportsMetaInfos' is set.
+ */
+ kSupportsThumbnails = 5,
+
+ /**
+ * Features 'save_date' and 'save_time' entries in the
+ * savestate returned by querySaveMetaInfo. Those values
+ * indicate the date/time the savegame was created.
+ * This flag may only be set when 'kSupportsMetaInfos' is set.
+ */
+ kSupportsSaveDate = 6,
+
+ /**
+ * Features 'play_time' entry in the savestate returned by
+ * querySaveMetaInfo. It indicates how long the user played
+ * the game till the save.
+ * This flag may only be set when 'kSupportsMetaInfos' is set.
+ */
+ kSupportsSavePlayTime = 7
+ };
+
+ /**
+ * Determine whether the engine supports the specified MetaEngine feature.
+ * Used by e.g. the launcher to determine whether to enable the "Load" button.
+ */
+ virtual bool hasFeature(MetaEngineFeature f) const { return false; };
+
+ //@}
};
@@ -107,7 +196,7 @@ private:
public:
GameDescriptor findGame(const Common::String &gameName, const EnginePlugin **plugin = NULL) const;
- GameList detectGames(const FSList &fslist) const;
+ GameList detectGames(const Common::FSList &fslist) const;
const EnginePlugin::List &getPlugins() const;
};
diff --git a/engines/module.mk b/engines/module.mk
index 6cfe9b36fa..8102046c5b 100644
--- a/engines/module.mk
+++ b/engines/module.mk
@@ -1,7 +1,9 @@
MODULE := engines
MODULE_OBJS := \
- engine.o
+ dialogs.o \
+ engine.o \
+ game.o
# Include common rules
include $(srcdir)/rules.mk
diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp
index 222954ec3a..290aa5e625 100644
--- a/engines/parallaction/balloons.cpp
+++ b/engines/parallaction/balloons.cpp
@@ -246,6 +246,8 @@ class BalloonManager_ns : public BalloonManager {
static int16 _dialogueBalloonX[5];
+ byte _textColors[2];
+
struct Balloon {
Common::Rect outerBox;
Common::Rect innerBox;
@@ -266,16 +268,18 @@ public:
void freeBalloons();
int setLocationBalloon(char *text, bool endGame);
- int setDialogueBalloon(char *text, uint16 winding, byte textColor);
- int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
- void setBalloonText(uint id, char *text, byte textColor);
+ int setDialogueBalloon(char *text, uint16 winding, TextColor textColor);
+ int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, TextColor textColor);
+ void setBalloonText(uint id, char *text, TextColor textColor);
int hitTestDialogueBalloon(int x, int y);
};
int16 BalloonManager_ns::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 };
BalloonManager_ns::BalloonManager_ns(Gfx *gfx) : _numBalloons(0), _gfx(gfx) {
-
+ _textColors[kSelectedColor] = 0;
+ _textColors[kUnselectedColor] = 3;
+ _textColors[kNormalColor] = 0;
}
BalloonManager_ns::~BalloonManager_ns() {
@@ -314,7 +318,7 @@ int BalloonManager_ns::createBalloon(int16 w, int16 h, int16 winding, uint16 bor
winding = (winding == 0 ? 1 : 0);
Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
s.moveTo(r.width()/2 - 5, r.bottom - 1);
- _gfx->blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR_NS);
+ _gfx->blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, 100, BALLOON_TRANSPARENT_COLOR_NS);
}
_numBalloons++;
@@ -323,7 +327,7 @@ int BalloonManager_ns::createBalloon(int16 w, int16 h, int16 winding, uint16 bor
}
-int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
+int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, TextColor textColor) {
int16 w, h;
@@ -336,7 +340,7 @@ int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w
Balloon *balloon = &_intBalloons[id];
StringWriter_NS sw(_vm->_dialogueFont);
- sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
+ sw.write(text, MAX_BALLOON_WIDTH, _textColors[textColor], balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -347,7 +351,7 @@ int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w
return id;
}
-int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
+int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, TextColor textColor) {
int16 w, h;
@@ -361,7 +365,7 @@ int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textC
Balloon *balloon = &_intBalloons[id];
StringWriter_NS sw(_vm->_dialogueFont);
- sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
+ sw.write(text, MAX_BALLOON_WIDTH, _textColors[textColor], balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -377,12 +381,12 @@ int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textC
return id;
}
-void BalloonManager_ns::setBalloonText(uint id, char *text, byte textColor) {
+void BalloonManager_ns::setBalloonText(uint id, char *text, TextColor textColor) {
Balloon *balloon = getBalloon(id);
balloon->surface->fillRect(balloon->innerBox, 1);
StringWriter_NS sw(_vm->_dialogueFont);
- sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
+ sw.write(text, MAX_BALLOON_WIDTH, _textColors[textColor], balloon->surface);
}
@@ -398,7 +402,7 @@ int BalloonManager_ns::setLocationBalloon(char *text, bool endGame) {
int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR_NS);
Balloon *balloon = &_intBalloons[id];
StringWriter_NS sw(_vm->_dialogueFont);
- sw.write(text, MAX_BALLOON_WIDTH, 0, balloon->surface);
+ sw.write(text, MAX_BALLOON_WIDTH, _textColors[kNormalColor], balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -513,8 +517,6 @@ public:
StringWriter_BR(Font *font) : WrappedLineFormatter(font) { }
void write(const char *text, uint maxWidth, byte color, Graphics::Surface *surf) {
- maxWidth = 216;
-
StringExtent_BR se(_font);
se.calc(text, maxWidth);
_width = se.width() + 10;
@@ -534,6 +536,8 @@ public:
class BalloonManager_br : public BalloonManager {
+ byte _textColors[2];
+
struct Balloon {
Common::Rect box;
Graphics::Surface *surface;
@@ -550,7 +554,7 @@ class BalloonManager_br : public BalloonManager {
void cacheAnims();
void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
- int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
+ int createBalloon(int16 w, int16 h, uint16 borderThickness);
Balloon *getBalloon(uint id);
Graphics::Surface *expandBalloon(Frames *data, int frameNum);
@@ -562,9 +566,9 @@ public:
void freeBalloons();
int setLocationBalloon(char *text, bool endGame);
- int setDialogueBalloon(char *text, uint16 winding, byte textColor);
- int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
- void setBalloonText(uint id, char *text, byte textColor);
+ int setDialogueBalloon(char *text, uint16 winding, TextColor textColor);
+ int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, TextColor textColor);
+ void setBalloonText(uint id, char *text, TextColor textColor);
int hitTestDialogueBalloon(int x, int y);
};
@@ -585,12 +589,12 @@ Graphics::Surface *BalloonManager_br::expandBalloon(Frames *data, int frameNum)
Graphics::Surface *surf = new Graphics::Surface;
surf->create(rect.width(), rect.height(), 1);
- _gfx->unpackBlt(rect, data->getData(frameNum), data->getRawSize(frameNum), surf, 0, BALLOON_TRANSPARENT_COLOR_BR);
+ _gfx->unpackBlt(rect, data->getData(frameNum), data->getRawSize(frameNum), surf, LAYER_FOREGROUND, 100, BALLOON_TRANSPARENT_COLOR_BR);
return surf;
}
-int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
+int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, TextColor textColor) {
cacheAnims();
int id = _numBalloons;
@@ -613,7 +617,7 @@ int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w
balloon->surface = expandBalloon(src, srcFrame);
src->getRect(srcFrame, balloon->box);
- _writer.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
+ _writer.write(text, 216, _textColors[textColor], balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -626,7 +630,7 @@ int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w
return id;
}
-int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
+int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, TextColor textColor) {
cacheAnims();
int id = _numBalloons;
@@ -637,11 +641,11 @@ int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textC
if (winding == 0) {
src = _rightBalloon;
- srcFrame = id;
+ srcFrame = 0;
} else
if (winding == 1) {
src = _leftBalloon;
- srcFrame = 0;
+ srcFrame = id;
}
assert(src);
@@ -649,7 +653,7 @@ int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textC
balloon->surface = expandBalloon(src, srcFrame);
src->getRect(srcFrame, balloon->box);
- _writer.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
+ _writer.write(text, 216, _textColors[textColor], balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -657,32 +661,51 @@ int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textC
balloon->obj->y = balloon->box.top;
balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR;
- if (id > 0) {
- balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].box.height();
- }
-
_numBalloons++;
return id;
}
-void BalloonManager_br::setBalloonText(uint id, char *text, byte textColor) { }
+void BalloonManager_br::setBalloonText(uint id, char *text, TextColor textColor) {
+ Balloon *balloon = getBalloon(id);
+
+ StringWriter_BR sw(_vm->_dialogueFont);
+ sw.write(text, 216, _textColors[textColor], balloon->surface);
+}
+
+int BalloonManager_br::createBalloon(int16 w, int16 h, uint16 borderThickness) {
+ assert(_numBalloons < 5);
+
+ int id = _numBalloons;
+ Balloon *balloon = &_intBalloons[id];
+
+ balloon->surface = new Graphics::Surface;
+ balloon->surface->create(w, h, 1);
+
+ Common::Rect rect(w, h);
+ balloon->surface->fillRect(rect, 1);
+ rect.grow(-borderThickness);
+ balloon->surface->fillRect(rect, 15);
+
+ _numBalloons++;
+
+ return id;
+}
int BalloonManager_br::setLocationBalloon(char *text, bool endGame) {
-/*
- int16 w, h;
+ StringExtent_BR se(_vm->_dialogueFont);
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+ se.calc(text, 240);
- int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR);
+ int id = createBalloon(se.width() + 20, se.height() + 30, 2);
Balloon *balloon = &_intBalloons[id];
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH);
- // TODO: extract some text to make a name for obj
+ _writer.write(text, 240, kNormalColor, balloon->surface);
+
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
balloon->obj->x = 5;
balloon->obj->y = 5;
-*/
+
return 0;
}
@@ -691,11 +714,9 @@ int BalloonManager_br::hitTestDialogueBalloon(int x, int y) {
Common::Point p;
for (uint i = 0; i < _numBalloons; i++) {
- p.x = x - _intBalloons[i].obj->x;
- p.y = y - _intBalloons[i].obj->y;
-
- if (_intBalloons[i].box.contains(p))
+ if (_intBalloons[i].box.contains(x, y)) {
return i;
+ }
}
return -1;
@@ -723,6 +744,10 @@ void BalloonManager_br::cacheAnims() {
BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx),
_leftBalloon(0), _rightBalloon(0), _writer(_vm->_dialogueFont) {
+
+ _textColors[kSelectedColor] = 12;
+ _textColors[kUnselectedColor] = 0;
+ _textColors[kNormalColor] = 0;
}
BalloonManager_br::~BalloonManager_br() {
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 0f89ca22d1..7915daa0b8 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -32,6 +32,7 @@
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
+#include "parallaction/saveload.h"
#include "parallaction/sound.h"
@@ -170,7 +171,7 @@ void Parallaction_ns::_c_fade(void *parm) {
_gfx->setPalette(pal);
_gfx->updateScreen();
- g_system->delayMillis(20);
+ _vm->_system->delayMillis(20);
}
return;
@@ -305,7 +306,7 @@ void Parallaction_ns::_c_endComment(void *param) {
_gfx->setPalette(_gfx->_palette);
_gfx->updateScreen();
- g_system->delayMillis(20);
+ _vm->_system->delayMillis(20);
}
_input->waitForButtonEvent(kMouseLeftUp);
@@ -324,10 +325,10 @@ void Parallaction_ns::_c_frankenstein(void *parm) {
}
for (uint16 _di = 0; _di < 30; _di++) {
- g_system->delayMillis(20);
+ _vm->_system->delayMillis(20);
_gfx->setPalette(pal0);
_gfx->updateScreen();
- g_system->delayMillis(20);
+ _vm->_system->delayMillis(20);
_gfx->setPalette(pal1);
_gfx->updateScreen();
}
@@ -341,7 +342,7 @@ void Parallaction_ns::_c_frankenstein(void *parm) {
void Parallaction_ns::_c_finito(void *parm) {
- setPartComplete(_char);
+ _saveLoad->setPartComplete(_char.getBaseName());
cleanInventory();
cleanupGame();
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index 0476b01454..d2444c642e 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -243,9 +243,20 @@ public:
return "Nippon Safes Inc. (C) Dynabyte";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
};
+bool ParallactionMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
bool ParallactionMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Parallaction::PARALLACTIONGameDescription *gd = (const Parallaction::PARALLACTIONGameDescription *)desc;
bool res = true;
@@ -265,6 +276,43 @@ bool ParallactionMetaEngine::createInstance(OSystem *syst, Engine **engine, cons
return res;
}
+SaveStateList ParallactionMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ Common::String pattern = target;
+ pattern += ".0??";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 2 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 2);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ Common::String saveDesc = in->readLine();
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void ParallactionMetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".0%02d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
#if PLUGIN_ENABLED_DYNAMIC(PARALLACTION)
REGISTER_PLUGIN_DYNAMIC(PARALLACTION, PLUGIN_TYPE_ENGINE, ParallactionMetaEngine);
#else
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 205d702aa0..a2de3cbbf3 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -173,7 +173,7 @@ bool DialogueManager::displayAnswer(uint16 i) {
// display suitable answers
if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) {
- int id = _vm->_balloonMan->setDialogueBalloon(a->_text, 1, 3);
+ int id = _vm->_balloonMan->setDialogueBalloon(a->_text, 1, BalloonManager::kUnselectedColor);
assert(id >= 0);
_visAnswers[id] = i;
@@ -203,7 +203,7 @@ bool DialogueManager::displayAnswers() {
if (_numVisAnswers == 1) {
int id = _vm->_gfx->setItem(_answerer, _ballonPos._answerChar.x, _ballonPos._answerChar.y);
_vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
- _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, 0);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, BalloonManager::kNormalColor);
} else
if (_numVisAnswers > 1) {
int id = _vm->_gfx->setItem(_answerer, _ballonPos._answerChar.x, _ballonPos._answerChar.y);
@@ -218,7 +218,7 @@ bool DialogueManager::displayAnswers() {
bool DialogueManager::displayQuestion() {
if (!scumm_stricmp(_q->_text, "NULL")) return false;
- _vm->_balloonMan->setSingleBalloon(_q->_text, _ballonPos._questionBalloon.x, _ballonPos._questionBalloon.y, _q->_mood & 0x10, 0);
+ _vm->_balloonMan->setSingleBalloon(_q->_text, _ballonPos._questionBalloon.x, _ballonPos._questionBalloon.y, _q->_mood & 0x10, BalloonManager::kNormalColor);
int id = _vm->_gfx->setItem(_questioner, _ballonPos._questionChar.x, _ballonPos._questionChar.y);
_vm->_gfx->setItemFrame(id, _q->_mood & 0xF);
@@ -256,7 +256,7 @@ int16 DialogueManager::askPassword() {
}
if (_passwordChanged) {
- _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, BalloonManager::kNormalColor);
_passwordChanged = false;
}
@@ -286,11 +286,11 @@ int16 DialogueManager::selectAnswerN() {
if (_selection != _oldSelection) {
if (_oldSelection != -1) {
- _vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, 3);
+ _vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, BalloonManager::kUnselectedColor);
}
if (_selection != -1) {
- _vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, 0);
+ _vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, BalloonManager::kSelectedColor);
_vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[_selection]]->_mood & 0xF);
}
}
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 2923f239d4..30d820c6d2 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -29,10 +29,12 @@
#define PATH_LEN 200
#include "common/fs.h"
-
#include "common/file.h"
+
#include "graphics/surface.h"
+#include "parallaction/graphics.h"
+
namespace Parallaction {
class Table;
@@ -102,10 +104,10 @@ public:
Common::String name() const;
bool openArchivedFile(const char *name);
void closeArchivedFile();
- uint32 size() const;
- uint32 pos() const;
+ int32 size() const;
+ int32 pos() const;
bool eos() const;
- void seek(int32 offs, int whence = SEEK_SET);
+ bool seek(int32 offs, int whence = SEEK_SET);
uint32 read(void *dataPtr, uint32 dataSize);
};
@@ -209,21 +211,21 @@ protected:
Parallaction *_vm;
- FilesystemNode _baseDir;
- FilesystemNode _partDir;
+ Common::FilesystemNode _baseDir;
+ Common::FilesystemNode _partDir;
- FilesystemNode _aniDir;
- FilesystemNode _bkgDir;
- FilesystemNode _mscDir;
- FilesystemNode _mskDir;
- FilesystemNode _pthDir;
- FilesystemNode _rasDir;
- FilesystemNode _scrDir;
- FilesystemNode _sfxDir;
- FilesystemNode _talDir;
+ Common::FilesystemNode _aniDir;
+ Common::FilesystemNode _bkgDir;
+ Common::FilesystemNode _mscDir;
+ Common::FilesystemNode _mskDir;
+ Common::FilesystemNode _pthDir;
+ Common::FilesystemNode _rasDir;
+ Common::FilesystemNode _scrDir;
+ Common::FilesystemNode _sfxDir;
+ Common::FilesystemNode _talDir;
protected:
- void errorFileNotFound(const FilesystemNode &dir, const Common::String &filename);
+ void errorFileNotFound(const Common::FilesystemNode &dir, const Common::String &filename);
Font *createFont(const char *name, Common::ReadStream &stream);
Sprites* createSprites(Common::ReadStream &stream);
void loadBitmap(Common::SeekableReadStream &stream, Graphics::Surface &surf, byte *palette);
@@ -271,14 +273,14 @@ protected:
Font *createFont(const char *name, Common::SeekableReadStream &stream);
void loadBackground(BackgroundInfo& info, Common::SeekableReadStream &stream);
- FilesystemNode _baseBkgDir;
- FilesystemNode _fntDir;
- FilesystemNode _commonAniDir;
- FilesystemNode _commonBkgDir;
- FilesystemNode _commonMscDir;
- FilesystemNode _commonMskDir;
- FilesystemNode _commonPthDir;
- FilesystemNode _commonTalDir;
+ Common::FilesystemNode _baseBkgDir;
+ Common::FilesystemNode _fntDir;
+ Common::FilesystemNode _commonAniDir;
+ Common::FilesystemNode _commonBkgDir;
+ Common::FilesystemNode _commonMscDir;
+ Common::FilesystemNode _commonMskDir;
+ Common::FilesystemNode _commonPthDir;
+ Common::FilesystemNode _commonTalDir;
public:
AmigaDisk_br(Parallaction *vm);
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index f52567bea2..24893b7b05 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -91,7 +91,7 @@ struct Sprites : public Frames {
-void DosDisk_br::errorFileNotFound(const FilesystemNode &dir, const Common::String &filename) {
+void DosDisk_br::errorFileNotFound(const Common::FilesystemNode &dir, const Common::String &filename) {
error("File '%s' not found in directory '%s'", filename.c_str(), dir.getDisplayName().c_str());
}
@@ -134,7 +134,7 @@ GfxObj* DosDisk_br::loadTalk(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadTalk(%s)", name);
Common::String path(name);
- FilesystemNode node = _talDir.getChild(path);
+ Common::FilesystemNode node = _talDir.getChild(path);
if (!node.exists()) {
path += ".tal";
node = _talDir.getChild(path);
@@ -160,11 +160,11 @@ Script* DosDisk_br::loadLocation(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadLocation");
Common::String langs[4] = { "it", "fr", "en", "ge" };
- FilesystemNode locDir = _partDir.getChild(langs[_language]);
+ Common::FilesystemNode locDir = _partDir.getChild(langs[_language]);
Common::String path(name);
path += ".slf";
- FilesystemNode node = locDir.getChild(path);
+ Common::FilesystemNode node = locDir.getChild(path);
if (!node.exists()) {
path = Common::String(name) + ".loc";
node = locDir.getChild(path);
@@ -183,7 +183,7 @@ Script* DosDisk_br::loadScript(const char* name) {
Common::String path(name);
path += ".scr";
- FilesystemNode node = _scrDir.getChild(path);
+ Common::FilesystemNode node = _scrDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_scrDir, path);
}
@@ -221,7 +221,7 @@ Frames* DosDisk_br::loadPointer(const char *name) {
Common::String path(name);
path += ".ras";
- FilesystemNode node = _baseDir.getChild(path);
+ Common::FilesystemNode node = _baseDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_baseDir, path);
}
@@ -240,7 +240,7 @@ Font* DosDisk_br::loadFont(const char* name) {
Common::String path(name);
path += ".fnt";
- FilesystemNode node = _baseDir.getChild(path);
+ Common::FilesystemNode node = _baseDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_baseDir, path);
}
@@ -255,7 +255,7 @@ GfxObj* DosDisk_br::loadObjects(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadObjects");
Common::String path(name);
- FilesystemNode node = _partDir.getChild(path);
+ Common::FilesystemNode node = _partDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_partDir, path);
}
@@ -274,7 +274,7 @@ GfxObj* DosDisk_br::loadStatic(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadStatic");
Common::String path(name);
- FilesystemNode node = _rasDir.getChild(path);
+ Common::FilesystemNode node = _rasDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_rasDir, path);
}
@@ -312,7 +312,7 @@ Frames* DosDisk_br::loadFrames(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadFrames");
Common::String path(name);
- FilesystemNode node = _aniDir.getChild(path);
+ Common::FilesystemNode node = _aniDir.getChild(path);
if (!node.exists()) {
path += ".ani";
node = _aniDir.getChild(path);
@@ -336,7 +336,7 @@ void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
Common::String path(name);
path += ".bmp";
- FilesystemNode node = _baseDir.getChild(path);
+ Common::FilesystemNode node = _baseDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_baseDir, path);
}
@@ -363,7 +363,7 @@ void DosDisk_br::loadMask(const char *name, MaskBuffer &buffer) {
}
Common::String filepath;
- FilesystemNode node;
+ Common::FilesystemNode node;
Common::File stream;
filepath = Common::String(name) + ".msk";
@@ -384,7 +384,7 @@ void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char
debugC(5, kDebugDisk, "DosDisk_br::loadScenery");
Common::String filepath;
- FilesystemNode node;
+ Common::FilesystemNode node;
Common::File stream;
if (name) {
@@ -447,7 +447,7 @@ Table* DosDisk_br::loadTable(const char* name) {
Common::String path(name);
path += ".tab";
- FilesystemNode node = _partDir.getChild(path);
+ Common::FilesystemNode node = _partDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_partDir, path);
}
@@ -518,7 +518,7 @@ AmigaDisk_br::AmigaDisk_br(Parallaction *vm) : DosDisk_br(vm) {
_baseBkgDir = _baseDir.getChild("backs");
- FilesystemNode commonDir = _baseDir.getChild("common");
+ Common::FilesystemNode commonDir = _baseDir.getChild("common");
_commonAniDir = commonDir.getChild("anims");
_commonBkgDir = commonDir.getChild("backs");
_commonMscDir = commonDir.getChild("msc");
@@ -566,7 +566,7 @@ void AmigaDisk_br::loadScenery(BackgroundInfo& info, const char* name, const cha
debugC(1, kDebugDisk, "AmigaDisk_br::loadScenery '%s', '%s' '%s'", name, mask, path);
Common::String filepath;
- FilesystemNode node;
+ Common::FilesystemNode node;
Common::File stream;
if (name) {
@@ -630,7 +630,7 @@ void AmigaDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
Common::String path(name);
path += ".bkg";
- FilesystemNode node = _baseBkgDir.getChild(path);
+ Common::FilesystemNode node = _baseBkgDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_baseBkgDir, path);
}
@@ -644,7 +644,7 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadStatic '%s'", name);
Common::String path(name);
- FilesystemNode node = _rasDir.getChild(path);
+ Common::FilesystemNode node = _rasDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_rasDir, path);
}
@@ -687,7 +687,7 @@ Frames* AmigaDisk_br::loadFrames(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadFrames '%s'", name);
Common::String path(name);
- FilesystemNode node = _aniDir.getChild(path);
+ Common::FilesystemNode node = _aniDir.getChild(path);
if (!node.exists()) {
path += ".ani";
node = _aniDir.getChild(path);
@@ -713,7 +713,7 @@ GfxObj* AmigaDisk_br::loadTalk(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadTalk '%s'", name);
Common::String path(name);
- FilesystemNode node = _talDir.getChild(path);
+ Common::FilesystemNode node = _talDir.getChild(path);
if (!node.exists()) {
path += ".tal";
node = _talDir.getChild(path);
@@ -740,7 +740,7 @@ Font* AmigaDisk_br::loadFont(const char* name) {
Common::String path(name);
path += ".font";
- FilesystemNode node = _fntDir.getChild(path);
+ Common::FilesystemNode node = _fntDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_fntDir, path);
}
@@ -773,7 +773,7 @@ Common::SeekableReadStream* AmigaDisk_br::loadMusic(const char* name) {
debugC(5, kDebugDisk, "AmigaDisk_br::loadMusic");
Common::String path(name);
- FilesystemNode node = _mscDir.getChild(path);
+ Common::FilesystemNode node = _mscDir.getChild(path);
if (!node.exists()) {
// TODO (Kirben): error out when music file is not found?
return 0;
@@ -789,7 +789,7 @@ Common::ReadStream* AmigaDisk_br::loadSound(const char* name) {
debugC(5, kDebugDisk, "AmigaDisk_br::loadSound");
Common::String path(name);
- FilesystemNode node = _sfxDir.getChild(path);
+ Common::FilesystemNode node = _sfxDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_sfxDir, path);
}
@@ -803,7 +803,7 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name) {
debugC(5, kDebugDisk, "AmigaDisk_br::loadObjects");
Common::String path(name);
- FilesystemNode node = _partDir.getChild(path);
+ Common::FilesystemNode node = _partDir.getChild(path);
if (!node.exists()) {
errorFileNotFound(_partDir, path);
}
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 55e6fc5e77..54d4d1e5da 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -156,19 +156,19 @@ void Archive::closeArchivedFile() {
}
-uint32 Archive::size() const {
+int32 Archive::size() const {
return (_file == true ? _fileEndOffset - _fileOffset : 0);
}
-uint32 Archive::pos() const {
+int32 Archive::pos() const {
return (_file == true ? _fileCursor - _fileOffset : 0 );
}
bool Archive::eos() const {
- return (_file == true ? _fileCursor == _fileEndOffset : true );
+ return (_file == true ? _fileCursor == _fileEndOffset : true ); // FIXME (eos definition change)
}
-void Archive::seek(int32 offs, int whence) {
+bool Archive::seek(int32 offs, int whence) {
assert(_file == true && _fileCursor <= _fileEndOffset);
switch (whence) {
@@ -184,7 +184,7 @@ void Archive::seek(int32 offs, int whence) {
}
assert(_fileCursor <= _fileEndOffset && _fileCursor >= _fileOffset);
- _archive.seek(_fileCursor, SEEK_SET);
+ return _archive.seek(_fileCursor, SEEK_SET);
}
uint32 Archive::read(void *dataPtr, uint32 dataSize) {
@@ -234,16 +234,16 @@ public:
return _input->read(data, dataSize);
}
- uint32 pos() const {
+ int32 pos() const {
return _input->pos();
}
- uint32 size() const {
+ int32 size() const {
return _input->size();
}
- void seek(int32 offset, int whence) {
- _input->seek(offset, whence);
+ bool seek(int32 offset, int whence) {
+ return _input->seek(offset, whence);
}
};
@@ -798,11 +798,11 @@ public:
if (_dispose) delete _stream;
}
- uint32 size() const {
+ int32 size() const {
return _stream->size();
}
- uint32 pos() const {
+ int32 pos() const {
return _stream->pos();
}
@@ -810,8 +810,8 @@ public:
return _stream->eos();
}
- void seek(int32 offs, int whence = SEEK_SET) {
- _stream->seek(offs, whence);
+ bool seek(int32 offs, int whence = SEEK_SET) {
+ return _stream->seek(offs, whence);
}
uint32 read(void *dataPtr, uint32 dataSize) {
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index fe7b1b2903..bcc4a5b532 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -546,27 +546,4 @@ ProgramExec_br::ProgramExec_br(Parallaction_br *vm) : ProgramExec_ns(vm), _vm(vm
ProgramExec_br::~ProgramExec_br() {
}
-#if 0
-void Parallaction_br::jobWaitRemoveLabelJob(void *parm, Job *job) {
-
-}
-
-void Parallaction_br::jobPauseSfx(void *parm, Job *job) {
-
-}
-
-
-void Parallaction_br::jobStopFollower(void *parm, Job *job) {
-
-}
-
-
-void Parallaction_br::jobScroll(void *parm, Job *job) {
-
-}
-#endif
-
-
-
-
} // namespace Parallaction
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index 4ea7d601e0..2ce50f498e 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -247,32 +247,6 @@ DECLARE_COMMAND_OPCODE(close) {
_vm->updateDoor(_ctxt.cmd->u._zone, true);
}
-void Parallaction::showZone(ZonePtr z, bool visible) {
- if (!z) {
- return;
- }
-
- if (visible) {
- z->_flags &= ~kFlagsRemove;
- z->_flags |= kFlagsActive;
- } else {
- z->_flags |= kFlagsRemove;
- }
-
- if ((z->_type & 0xFFFF) == kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, visible);
-
- GetData *data = z->u.get;
- if (data->hasMask && _gfx->_backgroundInfo->hasMask) {
- if (visible) {
- _gfx->_backgroundInfo->mask.bltOr(data->gfxobj->x, data->gfxobj->y, data->_mask[0], 0, 0, data->_mask->w, data->_mask->h);
- } else {
- _gfx->_backgroundInfo->mask.bltCopy(data->gfxobj->x, data->gfxobj->y, data->_mask[1], 0, 0, data->_mask->w, data->_mask->h);
- }
- }
- }
-}
-
DECLARE_COMMAND_OPCODE(on) {
_vm->showZone(_ctxt.cmd->u._zone, true);
}
@@ -304,7 +278,8 @@ DECLARE_COMMAND_OPCODE(drop){
DECLARE_COMMAND_OPCODE(quit) {
- _engineFlags |= kEngineQuit;
+ _vm->_quit = true;
+ _vm->quitGame();
}
@@ -318,66 +293,6 @@ DECLARE_COMMAND_OPCODE(stop) {
}
-void Parallaction_ns::drawAnimations() {
- debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n");
-
- uint16 layer = 0;
-
- for (AnimationList::iterator it = _location._animations.begin(); it != _location._animations.end(); it++) {
-
- AnimationPtr anim = *it;
- GfxObj *obj = anim->gfxobj;
-
- // Validation is performed here, so that every animation is affected, instead that only the ones
- // who *own* a script. In fact, some scripts can change values in other animations.
- // The right way to do this would be to enforce validation when any variable is modified from
- // a script.
- anim->validateScriptVars();
-
- if ((anim->_flags & kFlagsActive) && ((anim->_flags & kFlagsRemove) == 0)) {
-
- if (anim->_flags & kFlagsNoMasked)
- layer = LAYER_FOREGROUND;
- else {
- if (getGameType() == GType_Nippon) {
- // Layer in NS depends on where the animation is on the screen, for each animation.
- layer = _gfx->_backgroundInfo->getLayer(anim->getFrameY() + anim->height());
- } else {
- // Layer in BRA is calculated from Z value. For characters it is the same as NS,
- // but other animations can have Z set from scripts independently from their
- // position on the screen.
- layer = _gfx->_backgroundInfo->getLayer(anim->getZ());
- }
- }
-
- if (obj) {
- _gfx->showGfxObj(obj, true);
- obj->frame = anim->getF();
- obj->x = anim->getX();
- obj->y = anim->getY();
- obj->z = anim->getZ();
- obj->layer = layer;
- }
- }
-
- if (((anim->_flags & kFlagsActive) == 0) && (anim->_flags & kFlagsRemove)) {
- anim->_flags &= ~kFlagsRemove;
- }
-
- if ((anim->_flags & kFlagsActive) && (anim->_flags & kFlagsRemove)) {
- anim->_flags &= ~kFlagsActive;
- anim->_flags |= kFlagsRemove;
- if (obj) {
- _gfx->showGfxObj(obj, false);
- }
- }
- }
-
- debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n");
-
- return;
-}
-
void ProgramExec::runScript(ProgramPtr script, AnimationPtr a) {
debugC(9, kDebugExec, "runScript(Animation = %s)", a->_name);
@@ -442,7 +357,7 @@ void CommandExec::runList(CommandList::iterator first, CommandList::iterator las
_ctxt.suspend = false;
for ( ; first != last; first++) {
- if (_engineFlags & kEngineQuit)
+ if (_vm->quit())
break;
CommandPtr cmd = *first;
@@ -532,239 +447,6 @@ CommandExec_ns::~CommandExec_ns() {
}
-//
-// ZONE TYPE: EXAMINE
-//
-
-void Parallaction::enterCommentMode(ZonePtr z) {
- if (!z) {
- return;
- }
-
- _commentZone = z;
-
- ExamineData *data = _commentZone->u.examine;
-
- if (!data->_description) {
- return;
- }
-
- // TODO: move this balloons stuff into DialogueManager and BalloonManager
- if (getGameType() == GType_Nippon) {
- int id;
- if (data->_filename) {
- if (data->_cnv == 0) {
- data->_cnv = _disk->loadStatic(data->_filename);
- }
-
- _gfx->setHalfbriteMode(true);
- _balloonMan->setSingleBalloon(data->_description, 0, 90, 0, 0);
- Common::Rect r;
- data->_cnv->getRect(0, r);
- id = _gfx->setItem(data->_cnv, 140, (_screenHeight - r.height())/2);
- _gfx->setItemFrame(id, 0);
- id = _gfx->setItem(_char._head, 100, 152);
- _gfx->setItemFrame(id, 0);
- } else {
- _balloonMan->setSingleBalloon(data->_description, 140, 10, 0, 0);
- id = _gfx->setItem(_char._talk, 190, 80);
- _gfx->setItemFrame(id, 0);
- }
- } else
- if (getGameType() == GType_BRA) {
- _balloonMan->setSingleBalloon(data->_description, 0, 0, 1, 0);
- int id = _gfx->setItem(_char._talk, 10, 80);
- _gfx->setItemFrame(id, 0);
- }
-
- _input->_inputMode = Input::kInputModeComment;
-}
-
-void Parallaction::exitCommentMode() {
- _input->_inputMode = Input::kInputModeGame;
-
- hideDialogueStuff();
- _gfx->setHalfbriteMode(false);
-
- _cmdExec->run(_commentZone->_commands, _commentZone);
- _commentZone = nullZonePtr;
-}
-
-void Parallaction::runCommentFrame() {
- if (_input->_inputMode != Input::kInputModeComment) {
- return;
- }
-
- if (_input->getLastButtonEvent() == kMouseLeftUp) {
- exitCommentMode();
- }
-}
-
-
-void Parallaction::runZone(ZonePtr z) {
- debugC(3, kDebugExec, "runZone (%s)", z->_name);
-
- uint16 subtype = z->_type & 0xFFFF;
-
- debugC(3, kDebugExec, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
- switch(subtype) {
-
- case kZoneExamine:
- enterCommentMode(z);
- return;
-
- case kZoneGet:
- pickupItem(z);
- break;
-
- case kZoneDoor:
- if (z->_flags & kFlagsLocked) break;
- updateDoor(z, !(z->_flags & kFlagsClosed));
- break;
-
- case kZoneHear:
- _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
- break;
-
- case kZoneSpeak:
- enterDialogueMode(z);
- return;
- }
-
- debugC(3, kDebugExec, "runZone completed");
-
- _cmdExec->run(z->_commands, z);
-
- return;
-}
-
-//
-// ZONE TYPE: DOOR
-//
-void Parallaction::updateDoor(ZonePtr z, bool close) {
- z->_flags = close ? (z->_flags |= kFlagsClosed) : (z->_flags &= ~kFlagsClosed);
-
- if (z->u.door->gfxobj) {
- uint frame = (close ? 0 : 1);
-// z->u.door->gfxobj->setFrame(frame);
- z->u.door->gfxobj->frame = frame;
- }
-
- return;
-}
-
-
-
-//
-// ZONE TYPE: GET
-//
-
-bool Parallaction::pickupItem(ZonePtr z) {
- if (z->_flags & kFlagsFixed) {
- return false;
- }
-
- int slot = addInventoryItem(z->u.get->_icon);
- if (slot != -1) {
- showZone(z, false);
- }
-
- return (slot != -1);
-}
-
-
-
-ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
-// printf("hitZone(%i, %i, %i)", type, x, y);
-
- uint16 _di = y;
- uint16 _si = x;
-
- for (ZoneList::iterator it = _location._zones.begin(); it != _location._zones.end(); it++) {
-// printf("Zone name: %s", z->_name);
-
- ZonePtr z = *it;
-
- if (z->_flags & kFlagsRemove) continue;
-
- Common::Rect r;
- z->getBox(r);
- r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
- r.bottom++;
-
- r.grow(-1); // allows some tolerance for mouse click
-
- if (!r.contains(_si, _di)) {
-
- // out of Zone, so look for special values
- if ((z->getX() == -2) || (z->getX() == -3)) {
-
- // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
- // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
- // but we need to check it separately here. The same workaround is applied in freeZones.
- if ((((z->_type & 0xFFFF) == kZoneMerge) && (((_si == z->u.merge->_obj1) && (_di == z->u.merge->_obj2)) || ((_si == z->u.merge->_obj2) && (_di == z->u.merge->_obj1)))) ||
- (((z->_type & 0xFFFF) == kZoneGet) && ((_si == z->u.get->_icon) || (_di == z->u.get->_icon)))) {
-
- // special Zone
- if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
- return z;
- if (z->_type == type)
- return z;
- if ((z->_type & 0xFFFF0000) == type)
- return z;
-
- }
- }
-
- if (z->getX() != -1)
- continue;
- if (_si < _char._ani->getFrameX())
- continue;
- if (_si > (_char._ani->getFrameX() + _char._ani->width()))
- continue;
- if (_di < _char._ani->getFrameY())
- continue;
- if (_di > (_char._ani->getFrameY() + _char._ani->height()))
- continue;
-
- }
-
- // normal Zone
- if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
- return z;
- if (z->_type == type)
- return z;
- if ((z->_type & 0xFFFF0000) == type)
- return z;
-
- }
-
-
- int16 _a, _b, _c, _d, _e, _f;
- for (AnimationList::iterator ait = _location._animations.begin(); ait != _location._animations.end(); ait++) {
-
- AnimationPtr a = *ait;
-
- _a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
- _e = ((_si >= a->getFrameX() + a->width()) || (_si <= a->getFrameX())) ? 0 : 1; // _e: horizontal range
- _f = ((_di >= a->getFrameY() + a->height()) || (_di <= a->getFrameY())) ? 0 : 1; // _f: vertical range
-
- _b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
- _c = (a->_type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
- _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
-
- if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
-
- return a;
-
- }
-
- }
-
- return nullZonePtr;
-}
-
-
void CommandExec_ns::init() {
Common::Array<const Opcode*> *table = 0;
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 1c373dda44..8eb9753edd 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -32,7 +32,7 @@
namespace Parallaction {
-GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : _frames(frames), _keep(true), x(0), y(0), z(0), _flags(kGfxObjNormal), type(objType), frame(0), layer(3) {
+GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : _frames(frames), _keep(true), x(0), y(0), z(0), _flags(kGfxObjNormal), type(objType), frame(0), layer(3), scale(100) {
if (name) {
_name = strdup(name);
} else {
@@ -180,9 +180,9 @@ void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf, bool scene) {
data = obj->getData(obj->frame);
if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) {
- blt(rect, data, &surf, obj->layer, obj->transparentKey);
+ blt(rect, data, &surf, obj->layer, obj->scale, obj->transparentKey);
} else {
- unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, obj->transparentKey);
+ unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, obj->scale, obj->transparentKey);
}
}
@@ -233,7 +233,7 @@ void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surf
blt(r, _unpackedBitmap, surf, z, transparentColor);
}
#endif
-void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
+void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor) {
byte *d = _unpackedBitmap;
uint pixelsLeftInLine = r.width();
@@ -259,11 +259,154 @@ void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surf
d += repeat;
}
- blt(r, _unpackedBitmap, surf, z, transparentColor);
+ blt(r, _unpackedBitmap, surf, z, scale, transparentColor);
}
-void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) {
+void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor) {
+ if (scale == 100) {
+ // use optimized path
+ bltMaskNoScale(r, data, surf, z, transparentColor);
+ return;
+ }
+
+ Common::Rect q(r);
+ Common::Rect clipper(surf->w, surf->h);
+ q.clip(clipper);
+ if (!q.isValidRect()) return;
+
+ uint inc = r.width() * (100 - scale);
+ uint thr = r.width() * 100;
+ uint xAccum = 0, yAccum = 0;
+
+ Common::Point dp;
+ dp.x = q.left + (r.width() * (100 - scale)) / 200;
+ dp.y = q.top + (r.height() * (100 - scale)) / 100;
+ q.translate(-r.left, -r.top);
+ byte *s = data + q.left + q.top * r.width();
+ byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
+
+ uint line = 0, col = 0;
+
+ for (uint16 i = 0; i < q.height(); i++) {
+ yAccum += inc;
+
+ if (yAccum >= thr) {
+ yAccum -= thr;
+ s += r.width();
+ continue;
+ }
+
+ xAccum = 0;
+ byte *d2 = d;
+ col = 0;
+
+ for (uint16 j = 0; j < q.width(); j++) {
+ xAccum += inc;
+
+ if (xAccum >= thr) {
+ xAccum -= thr;
+ s++;
+ continue;
+ }
+
+ if (*s != transparentColor) {
+ byte v = _backgroundInfo->mask.getValue(dp.x + col, dp.y + line);
+ if (z >= v) *d2 = *s;
+ }
+
+ s++;
+ d2++;
+ col++;
+ }
+
+ s += r.width() - q.width();
+ d += surf->w;
+ line++;
+ }
+
+}
+
+void Gfx::bltMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) {
+ if (!_backgroundInfo->mask.data || (z == LAYER_FOREGROUND)) {
+ // use optimized path
+ bltNoMaskNoScale(r, data, surf, transparentColor);
+ return;
+ }
+
+ Common::Point dp;
+ Common::Rect q(r);
+
+ Common::Rect clipper(surf->w, surf->h);
+
+ q.clip(clipper);
+ if (!q.isValidRect()) return;
+
+ dp.x = q.left;
+ dp.y = q.top;
+
+ q.translate(-r.left, -r.top);
+
+ byte *s = data + q.left + q.top * r.width();
+ byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
+
+ uint sPitch = r.width() - q.width();
+ uint dPitch = surf->w - q.width();
+
+ for (uint16 i = 0; i < q.height(); i++) {
+
+ for (uint16 j = 0; j < q.width(); j++) {
+ if (*s != transparentColor) {
+ byte v = _backgroundInfo->mask.getValue(dp.x + j, dp.y + i);
+ if (z >= v) *d = *s;
+ }
+
+ s++;
+ d++;
+ }
+
+ s += sPitch;
+ d += dPitch;
+ }
+
+}
+
+void Gfx::bltNoMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, byte transparentColor) {
+ Common::Point dp;
+ Common::Rect q(r);
+
+ Common::Rect clipper(surf->w, surf->h);
+
+ q.clip(clipper);
+ if (!q.isValidRect()) return;
+
+ dp.x = q.left;
+ dp.y = q.top;
+
+ q.translate(-r.left, -r.top);
+
+ byte *s = data + q.left + q.top * r.width();
+ byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
+
+ uint sPitch = r.width() - q.width();
+ uint dPitch = surf->w - q.width();
+
+ for (uint16 i = q.top; i < q.bottom; i++) {
+ for (uint16 j = q.left; j < q.right; j++) {
+ if (*s != transparentColor)
+ *d = *s;
+
+ s++;
+ d++;
+ }
+
+ s += sPitch;
+ d += dPitch;
+ }
+}
+
+
+void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor) {
Common::Point dp;
Common::Rect q(r);
@@ -308,40 +451,7 @@ void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16
}
} else {
- if (_backgroundInfo->mask.data && (z < LAYER_FOREGROUND)) {
-
- for (uint16 i = 0; i < q.height(); i++) {
-
- for (uint16 j = 0; j < q.width(); j++) {
- if (*s != transparentColor) {
- byte v = _backgroundInfo->mask.getValue(dp.x + j, dp.y + i);
- if (z >= v) *d = *s;
- }
-
- s++;
- d++;
- }
-
- s += sPitch;
- d += dPitch;
- }
-
- } else {
-
- for (uint16 i = q.top; i < q.bottom; i++) {
- for (uint16 j = q.left; j < q.right; j++) {
- if (*s != transparentColor)
- *d = *s;
-
- s++;
- d++;
- }
-
- s += sPitch;
- d += dPitch;
- }
-
- }
+ bltMaskScale(r, data, surf, z, scale, transparentColor);
}
}
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 1c2cb58b5b..2bd3935f01 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -34,8 +34,9 @@
namespace Parallaction {
// this is the size of the receiving buffer for unpacked frames,
-// since BRA uses some insanely big animations.
-#define MAXIMUM_UNPACKED_BITMAP_SIZE 640*401
+// since BRA uses some insanely big animations (the largest is
+// part0/ani/dino.ani).
+#define MAXIMUM_UNPACKED_BITMAP_SIZE 641*401
void Gfx::registerVar(const Common::String &name, int32 initialValue) {
@@ -251,7 +252,7 @@ void Gfx::setPalette(Palette pal) {
byte sysPal[256*4];
uint n = pal.fillRGBA(sysPal);
- g_system->setPalette(sysPal, 0, n);
+ _vm->_system->setPalette(sysPal, 0, n);
}
void Gfx::setBlackPalette() {
@@ -327,7 +328,7 @@ void Gfx::drawInventory() {
_vm->_inventoryRenderer->getRect(r);
byte *data = _vm->_inventoryRenderer->getData();
- g_system->copyRectToScreen(data, r.width(), r.left, r.top, r.width(), r.height());
+ _vm->_system->copyRectToScreen(data, r.width(), r.left, r.top, r.width(), r.height());
}
void Gfx::drawItems() {
@@ -335,11 +336,11 @@ void Gfx::drawItems() {
return;
}
- Graphics::Surface *surf = g_system->lockScreen();
+ Graphics::Surface *surf = _vm->_system->lockScreen();
for (uint i = 0; i < _numItems; i++) {
drawGfxObject(_items[i].data, *surf, false);
}
- g_system->unlockScreen();
+ _vm->_system->unlockScreen();
}
void Gfx::drawBalloons() {
@@ -347,15 +348,15 @@ void Gfx::drawBalloons() {
return;
}
- Graphics::Surface *surf = g_system->lockScreen();
+ Graphics::Surface *surf = _vm->_system->lockScreen();
for (uint i = 0; i < _balloons.size(); i++) {
drawGfxObject(_balloons[i], *surf, false);
}
- g_system->unlockScreen();
+ _vm->_system->unlockScreen();
}
void Gfx::clearScreen() {
- g_system->clearScreen();
+ _vm->_system->clearScreen();
}
void Gfx::beginFrame() {
@@ -377,7 +378,7 @@ void Gfx::beginFrame() {
*data++ = _backgroundInfo->mask.getValue(x, y);
}
}
-#if 1
+#if 0
Common::DumpFile dump;
dump.open("maskdump.bin");
dump.write(_bitmapMask.pixels, _bitmapMask.w * _bitmapMask.h);
@@ -437,11 +438,11 @@ void Gfx::updateScreen() {
backgroundPitch = _bitmapMask.pitch;
break;
}
- g_system->copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo->x, _backgroundInfo->y, w, h);
+ _vm->_system->copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo->x, _backgroundInfo->y, w, h);
}
if (_varDrawPathZones == 1) {
- Graphics::Surface *surf = g_system->lockScreen();
+ Graphics::Surface *surf = _vm->_system->lockScreen();
ZoneList::iterator b = _vm->_location._zones.begin();
ZoneList::iterator e = _vm->_location._zones.end();
for (; b != e; b++) {
@@ -450,13 +451,13 @@ void Gfx::updateScreen() {
surf->frameRect(Common::Rect(z->getX(), z->getY(), z->getX() + z->width(), z->getY() + z->height()), 2);
}
}
- g_system->unlockScreen();
+ _vm->_system->unlockScreen();
}
_varRenderMode = _varAnimRenderMode;
// TODO: transform objects coordinates to be drawn with scrolling
- Graphics::Surface *surf = g_system->lockScreen();
+ Graphics::Surface *surf = _vm->_system->lockScreen();
drawGfxObjects(*surf);
if (_halfbrite) {
@@ -480,7 +481,7 @@ void Gfx::updateScreen() {
}
}
- g_system->unlockScreen();
+ _vm->_system->unlockScreen();
_varRenderMode = _varMiscRenderMode;
@@ -489,7 +490,7 @@ void Gfx::updateScreen() {
drawBalloons();
drawLabels();
- g_system->updateScreen();
+ _vm->_system->updateScreen();
return;
}
@@ -506,7 +507,7 @@ void Gfx::patchBackground(Graphics::Surface &surf, int16 x, int16 y, bool mask)
r.moveTo(x, y);
uint16 z = (mask) ? _backgroundInfo->getLayer(y) : LAYER_FOREGROUND;
- blt(r, (byte*)surf.pixels, &_backgroundInfo->bg, z, 0);
+ blt(r, (byte*)surf.pixels, &_backgroundInfo->bg, z, 100, 0);
}
void Gfx::fillBackground(const Common::Rect& r, byte color) {
@@ -600,30 +601,41 @@ void Gfx::updateFloatingLabel() {
return;
}
- int16 _si, _di;
-
- Common::Point cursor;
- _vm->_input->getCursorPos(cursor);
+ struct FloatingLabelTraits {
+ Common::Point _offsetWithItem;
+ Common::Point _offsetWithoutItem;
+ int _minX;
+ int _minY;
+ int _maxX;
+ int _maxY;
+ } *traits;
Common::Rect r;
_labels[_floatingLabel]->getRect(0, r);
- if (_vm->_input->_activeItem._id != 0) {
- _si = cursor.x + 16 - r.width()/2;
- _di = cursor.y + 34;
+ if (_vm->getGameType() == GType_Nippon) {
+ FloatingLabelTraits traits_NS = {
+ Common::Point(16 - r.width()/2, 34),
+ Common::Point(8 - r.width()/2, 21),
+ 0, 0, _vm->_screenWidth - r.width(), 190
+ };
+ traits = &traits_NS;
} else {
- _si = cursor.x + 8 - r.width()/2;
- _di = cursor.y + 21;
+ // FIXME: _maxY for BRA is not constant (390), but depends on _vm->_subtitleY
+ FloatingLabelTraits traits_BR = {
+ Common::Point(34 - r.width()/2, 70),
+ Common::Point(16 - r.width()/2, 37),
+ 0, 0, _vm->_screenWidth - r.width(), 390
+ };
+ traits = &traits_BR;
}
- if (_si < 0) _si = 0;
- if (_di > 190) _di = 190;
-
- if (r.width() + _si > _vm->_screenWidth)
- _si = _vm->_screenWidth - r.width();
+ Common::Point cursor;
+ _vm->_input->getCursorPos(cursor);
+ Common::Point offset = (_vm->_input->_activeItem._id) ? traits->_offsetWithItem : traits->_offsetWithoutItem;
- _labels[_floatingLabel]->x = _si;
- _labels[_floatingLabel]->y = _di;
+ _labels[_floatingLabel]->x = CLIP(cursor.x + offset.x, traits->_minX, traits->_maxX);
+ _labels[_floatingLabel]->y = CLIP(cursor.y + offset.y, traits->_minY, traits->_maxY);
}
@@ -703,13 +715,13 @@ void Gfx::drawLabels() {
updateFloatingLabel();
- Graphics::Surface* surf = g_system->lockScreen();
+ Graphics::Surface* surf = _vm->_system->lockScreen();
for (uint i = 0; i < _labels.size(); i++) {
drawGfxObject(_labels[i], *surf, false);
}
- g_system->unlockScreen();
+ _vm->_system->unlockScreen();
}
@@ -737,10 +749,10 @@ void Gfx::grabBackground(const Common::Rect& r, Graphics::Surface &dst) {
Gfx::Gfx(Parallaction* vm) :
_vm(vm), _disk(vm->_disk) {
- g_system->beginGFXTransaction();
- g_system->initSize(_vm->_screenWidth, _vm->_screenHeight);
+ _vm->_system->beginGFXTransaction();
+ _vm->_system->initSize(_vm->_screenWidth, _vm->_screenHeight);
_vm->initCommonGFX(_vm->getGameType() == GType_BRA);
- g_system->endGFXTransaction();
+ _vm->_system->endGFXTransaction();
setPalette(_palette);
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 471f71dfa8..ac9f096d7e 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -313,6 +313,7 @@ struct Cnv : public Frames {
uint16 _height; //
byte** field_8; // unused
byte* _data;
+ bool _freeData;
public:
Cnv() {
@@ -320,12 +321,14 @@ public:
_data = NULL;
}
- Cnv(uint16 numFrames, uint16 width, uint16 height, byte* data) : _count(numFrames), _width(width), _height(height), _data(data) {
+ Cnv(uint16 numFrames, uint16 width, uint16 height, byte* data, bool freeData = false)
+ : _count(numFrames), _width(width), _height(height), _data(data), _freeData(freeData) {
}
~Cnv() {
- free(_data);
+ if (_freeData)
+ free(_data);
}
byte* getFramePtr(uint16 index) {
@@ -410,6 +413,7 @@ public:
uint frame;
uint layer;
uint transparentKey;
+ uint scale;
GfxObj(uint type, Frames *frames, const char *name = NULL);
virtual ~GfxObj();
@@ -495,13 +499,19 @@ enum {
class BalloonManager {
public:
+ enum TextColor {
+ kSelectedColor = 0,
+ kUnselectedColor = 1,
+ kNormalColor = 2
+ };
+
virtual ~BalloonManager() { }
virtual void freeBalloons() = 0;
virtual int setLocationBalloon(char *text, bool endGame) = 0;
- virtual int setDialogueBalloon(char *text, uint16 winding, byte textColor) = 0;
- virtual int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) = 0;
- virtual void setBalloonText(uint id, char *text, byte textColor) = 0;
+ virtual int setDialogueBalloon(char *text, uint16 winding, TextColor textColor) = 0;
+ virtual int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, TextColor textColor) = 0;
+ virtual void setBalloonText(uint id, char *text, TextColor textColor) = 0;
virtual int hitTestDialogueBalloon(int x, int y) = 0;
};
@@ -640,8 +650,12 @@ public:
void drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color);
void drawGfxObject(GfxObj *obj, Graphics::Surface &surf, bool scene);
- void blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor);
- void unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor);
+ void blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor);
+ void unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor);
+
+ void bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor);
+ void bltMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor);
+ void bltNoMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, byte transparentColor);
};
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index 3315433762..c687a15026 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -28,6 +28,7 @@
#include "parallaction/gui.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
+#include "parallaction/saveload.h"
namespace Parallaction {
@@ -40,11 +41,11 @@ protected:
Palette blackPal;
Palette pal;
- Parallaction_br *_vm;
+ Parallaction *_vm;
int _fadeSteps;
public:
- SplashInputState_BR(Parallaction_br *vm, const Common::String &name, MenuInputHelper *helper) : MenuInputState(name, helper), _vm(vm) {
+ SplashInputState_BR(Parallaction *vm, const Common::String &name, MenuInputHelper *helper) : MenuInputState(name, helper), _vm(vm) {
}
virtual MenuInputState* run() {
@@ -52,8 +53,6 @@ public:
pal.fadeTo(blackPal, 1);
_vm->_gfx->setPalette(pal);
_fadeSteps--;
- // TODO: properly implement timers to avoid delay calls
- _vm->_system->delayMillis(20);
return this;
}
@@ -75,7 +74,7 @@ public:
_vm->showSlide(_slideName.c_str(), CENTER_LABEL_HORIZONTAL, CENTER_LABEL_VERTICAL);
_vm->_input->setMouseState(MOUSE_DISABLED);
- _startTime = g_system->getMillis();
+ _startTime = _vm->_system->getMillis();
_fadeSteps = -1;
}
};
@@ -152,6 +151,8 @@ class MainMenuInputState_BR : public MenuInputState {
static const char *_menuStrings[NUM_MENULINES];
static const MenuOptions _options[NUM_MENULINES];
+ static const char *_firstLocation[];
+
int _availItems;
int _selection;
@@ -166,16 +167,18 @@ class MainMenuInputState_BR : public MenuInputState {
void performChoice(int selectedItem) {
switch (selectedItem) {
- case kMenuQuit:
- _engineFlags |= kEngineQuit;
+ case kMenuQuit: {
+ _vm->_quit = true;
+ _vm->quitGame();
break;
+ }
case kMenuLoadGame:
warning("loadgame not yet implemented");
break;
default:
- _vm->startPart(selectedItem);
+ _vm->scheduleLocationSwitch(_firstLocation[selectedItem]);
}
}
@@ -213,31 +216,40 @@ public:
virtual void enter() {
_vm->_gfx->clearScreen();
- int x = 0, y = 0;
+ int x = 0, y = 0, i = 0;
if (_vm->getPlatform() == Common::kPlatformPC) {
x = 20;
y = 50;
}
_vm->showSlide("tbra", x, y);
- // TODO: load progress from savefile
- int progress = 3;
- _availItems = 4 + progress;
+ _availItems = 4;
+
+ bool complete[3];
+ _vm->_saveLoad->getGamePartProgress(complete, 3);
+ for (i = 0; i < 3 && complete[i]; i++, _availItems++) ;
// TODO: keep track of and destroy menu item frames/surfaces
- int i;
for (i = 0; i < _availItems; i++) {
_lines[i] = new GfxObj(0, renderMenuItem(_menuStrings[i]), "MenuItem");
uint id = _vm->_gfx->setItem(_lines[i], MENUITEMS_X, MENUITEMS_Y + MENUITEM_HEIGHT * i, 0xFF);
_vm->_gfx->setItemFrame(id, 0);
}
_selection = -1;
- _vm->setArrowCursor();
+ _vm->_input->setArrowCursor();
_vm->_input->setMouseState(MOUSE_ENABLED_SHOW);
}
};
+const char *MainMenuInputState_BR::_firstLocation[] = {
+ "intro.0",
+ "museo.1",
+ "start.2",
+ "bolscoi.3",
+ "treno.4"
+};
+
const char *MainMenuInputState_BR::_menuStrings[NUM_MENULINES] = {
"SEE INTRO",
"NEW GAME",
@@ -264,29 +276,24 @@ const MainMenuInputState_BR::MenuOptions MainMenuInputState_BR::_options[NUM_MEN
-void Parallaction_br::startGui() {
+void Parallaction_br::startGui(bool showSplash) {
_menuHelper = new MenuInputHelper;
- new SplashInputState0_BR(this, _menuHelper);
- new SplashInputState1_BR(this, _menuHelper);
- new MainMenuInputState_BR(this, _menuHelper);
- _menuHelper->setState("intro0");
- _input->_inputMode = Input::kInputModeMenu;
-
- do {
- _input->readInput();
- if (!_menuHelper->run()) break;
- _gfx->beginFrame();
- _gfx->updateScreen();
- } while (true);
+ new MainMenuInputState_BR(this, _menuHelper);
- delete _menuHelper;
- _menuHelper = 0;
+ if (showSplash) {
+ new SplashInputState0_BR(this, _menuHelper);
+ new SplashInputState1_BR(this, _menuHelper);
+ _menuHelper->setState("intro0");
+ } else {
+ _menuHelper->setState("mainmenu");
+ }
- _input->_inputMode = Input::kInputModeGame;
+ _input->_inputMode = Input::kInputModeMenu;
}
+
} // namespace Parallaction
diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp
index 815c27bd1c..73cc1be12e 100644
--- a/engines/parallaction/gui_ns.cpp
+++ b/engines/parallaction/gui_ns.cpp
@@ -29,6 +29,7 @@
#include "parallaction/gui.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
+#include "parallaction/saveload.h"
#include "parallaction/sound.h"
@@ -41,14 +42,14 @@ protected:
Common::String _nextState;
uint32 _startTime;
- Parallaction_ns *_vm;
+ Parallaction *_vm;
public:
- SplashInputState_NS(Parallaction_ns *vm, const Common::String &name, MenuInputHelper *helper) : MenuInputState(name, helper), _vm(vm) {
+ SplashInputState_NS(Parallaction *vm, const Common::String &name, MenuInputHelper *helper) : MenuInputState(name, helper), _vm(vm) {
}
virtual MenuInputState* run() {
- uint32 curTime = g_system->getMillis();
+ uint32 curTime = _vm->_system->getMillis();
if (curTime - _startTime > _timeOut) {
_vm->freeBackground();
return _helper->getState(_nextState);
@@ -59,14 +60,14 @@ public:
virtual void enter() {
_vm->_input->setMouseState(MOUSE_DISABLED);
_vm->showSlide(_slideName.c_str());
- _startTime = g_system->getMillis();
+ _startTime = _vm->_system->getMillis();
}
};
class SplashInputState0_NS : public SplashInputState_NS {
public:
- SplashInputState0_NS(Parallaction_ns *vm, MenuInputHelper *helper) : SplashInputState_NS(vm, "intro0", helper) {
+ SplashInputState0_NS(Parallaction *vm, MenuInputHelper *helper) : SplashInputState_NS(vm, "intro0", helper) {
_slideName = "intro";
_timeOut = 2000;
_nextState = "intro1";
@@ -76,7 +77,7 @@ public:
class SplashInputState1_NS : public SplashInputState_NS {
public:
- SplashInputState1_NS(Parallaction_ns *vm, MenuInputHelper *helper) : SplashInputState_NS(vm, "intro1", helper) {
+ SplashInputState1_NS(Parallaction *vm, MenuInputHelper *helper) : SplashInputState_NS(vm, "intro1", helper) {
_slideName = "minintro";
_timeOut = 2000;
_nextState = "chooselanguage";
@@ -111,10 +112,10 @@ class ChooseLanguageInputState_NS : public MenuInputState {
static const Common::Rect _amigaLanguageSelectBlocks[4];
const Common::Rect *_blocks;
- Parallaction_ns *_vm;
+ Parallaction *_vm;
public:
- ChooseLanguageInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("chooselanguage", helper), _vm(vm) {
+ ChooseLanguageInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("chooselanguage", helper), _vm(vm) {
_allowChoice = false;
_nextState = "selectgame";
@@ -178,7 +179,7 @@ public:
uint id = _vm->_gfx->createLabel(_vm->_introFont, "SELECT LANGUAGE", 1);
_vm->_gfx->showLabel(id, 60, 30);
- _vm->setArrowCursor();
+ _vm->_input->setArrowCursor();
}
};
@@ -203,13 +204,13 @@ class SelectGameInputState_NS : public MenuInputState {
uint _labels[2];
- Parallaction_ns *_vm;
+ Parallaction *_vm;
static const char *newGameMsg[4];
static const char *loadGameMsg[4];
public:
- SelectGameInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("selectgame", helper), _vm(vm) {
+ SelectGameInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("selectgame", helper), _vm(vm) {
_choice = 0;
_oldChoice = -1;
@@ -271,10 +272,10 @@ const char *SelectGameInputState_NS::loadGameMsg[4] = {
class LoadGameInputState_NS : public MenuInputState {
bool _result;
- Parallaction_ns *_vm;
+ Parallaction *_vm;
public:
- LoadGameInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("loadgame", helper), _vm(vm) { }
+ LoadGameInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("loadgame", helper), _vm(vm) { }
virtual MenuInputState* run() {
if (!_result) {
@@ -284,19 +285,19 @@ public:
}
virtual void enter() {
- _result = _vm->loadGame();
+ _result = _vm->_saveLoad->loadGame();
}
};
class NewGameInputState_NS : public MenuInputState {
- Parallaction_ns *_vm;
+ Parallaction *_vm;
static const char *introMsg3[4];
public:
- NewGameInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("newgame", helper), _vm(vm) {
+ NewGameInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("newgame", helper), _vm(vm) {
}
virtual MenuInputState* run() {
@@ -344,14 +345,15 @@ const char *NewGameInputState_NS::introMsg3[4] = {
class StartDemoInputState_NS : public MenuInputState {
- Parallaction_ns *_vm;
+ Parallaction *_vm;
public:
- StartDemoInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("startdemo", helper), _vm(vm) {
+ StartDemoInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("startdemo", helper), _vm(vm) {
}
virtual MenuInputState* run() {
_vm->scheduleLocationSwitch("fognedemo.dough");
+ _vm->_input->setMouseState(MOUSE_ENABLED_SHOW);
return 0;
}
@@ -371,7 +373,7 @@ class SelectCharacterInputState_NS : public MenuInputState {
static const Common::Rect codeSelectBlocks[9];
static const Common::Rect codeTrueBlocks[9];
- Parallaction_ns *_vm;
+ Parallaction *_vm;
int guiGetSelectedBlock(const Common::Point &p) {
@@ -388,7 +390,7 @@ class SelectCharacterInputState_NS : public MenuInputState {
_vm->_gfx->invertBackground(codeTrueBlocks[selection]);
_vm->_gfx->updateScreen();
_vm->beep();
- g_system->delayMillis(100);
+ _vm->_system->delayMillis(100);
_vm->_gfx->invertBackground(codeTrueBlocks[selection]);
_vm->_gfx->updateScreen();
}
@@ -424,7 +426,7 @@ class SelectCharacterInputState_NS : public MenuInputState {
public:
- SelectCharacterInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("selectcharacter", helper), _vm(vm) {
+ SelectCharacterInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("selectcharacter", helper), _vm(vm) {
_keys = (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT)) ? _amigaKeys : _pcKeys;
_block.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1);
}
@@ -443,7 +445,7 @@ public:
}
void delay() {
- if (g_system->getMillis() - _startTime < 2000) {
+ if (_vm->_system->getMillis() - _startTime < 2000) {
return;
}
cleanup();
@@ -485,7 +487,7 @@ public:
_vm->_gfx->patchBackground(_emptySlots, SLOT_X, SLOT_Y, false);
_vm->_gfx->hideLabel(_labels[0]);
_vm->_gfx->showLabel(_labels[1], 60, 30);
- _startTime = g_system->getMillis();
+ _startTime = _vm->_system->getMillis();
_state = DELAY;
}
@@ -508,7 +510,6 @@ public:
error("If you read this, either your CPU or transivity is broken (we believe the former).");
}
- _vm->_inTestResult = false;
_vm->cleanupGame();
_vm->scheduleLocationSwitch(_charStartLocation[character]);
}
@@ -555,7 +556,7 @@ public:
cleanup();
- _vm->setArrowCursor();
+ _vm->_input->setArrowCursor();
_vm->_input->setMouseState(MOUSE_ENABLED_SHOW);
_state = CHOICE;
}
@@ -620,7 +621,7 @@ const Common::Rect SelectCharacterInputState_NS::codeTrueBlocks[9] = {
class ShowCreditsInputState_NS : public MenuInputState {
- Parallaction_ns *_vm;
+ Parallaction *_vm;
int _current;
uint32 _startTime;
@@ -632,7 +633,7 @@ class ShowCreditsInputState_NS : public MenuInputState {
static const Credit _credits[6];
public:
- ShowCreditsInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("showcredits", helper), _vm(vm) {
+ ShowCreditsInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("showcredits", helper), _vm(vm) {
}
void drawCurrentLabel() {
@@ -646,14 +647,14 @@ public:
virtual MenuInputState* run() {
if (_current == -1) {
- _startTime = g_system->getMillis();
+ _startTime = _vm->_system->getMillis();
_current = 0;
drawCurrentLabel();
return this;
}
int event = _vm->_input->getLastButtonEvent();
- uint32 curTime = g_system->getMillis();
+ uint32 curTime = _vm->_system->getMillis();
if ((event == kMouseLeftUp) || (curTime - _startTime > 5500)) {
_current++;
_startTime = curTime;
@@ -685,11 +686,11 @@ const ShowCreditsInputState_NS::Credit ShowCreditsInputState_NS::_credits[6] = {
};
class EndIntroInputState_NS : public MenuInputState {
- Parallaction_ns *_vm;
+ Parallaction *_vm;
bool _isDemo;
public:
- EndIntroInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("endintro", helper), _vm(vm) {
+ EndIntroInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("endintro", helper), _vm(vm) {
_isDemo = (_vm->getFeatures() & GF_DEMO) != 0;
}
@@ -701,7 +702,8 @@ public:
}
if (_isDemo) {
- _engineFlags |= kEngineQuit;
+ _vm->_quit = true;
+ _vm->quitGame();
return 0;
}
@@ -722,7 +724,7 @@ public:
class EndPartInputState_NS : public MenuInputState {
- Parallaction_ns *_vm;
+ Parallaction *_vm;
bool _allPartsComplete;
// part completion messages
@@ -738,7 +740,7 @@ class EndPartInputState_NS : public MenuInputState {
public:
- EndPartInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("endpart", helper), _vm(vm) {
+ EndPartInputState_NS(Parallaction *vm, MenuInputHelper *helper) : MenuInputState("endpart", helper), _vm(vm) {
}
virtual MenuInputState* run() {
@@ -758,20 +760,23 @@ public:
}
virtual void enter() {
- _allPartsComplete = _vm->allPartsComplete();
+ bool completed[3];
+ _vm->_saveLoad->getGamePartProgress(completed, 3);
+ _allPartsComplete = (completed[0] && completed[1] && completed[2]);
_vm->_input->setMouseState(MOUSE_DISABLED);
+ uint16 language = _vm->getInternLanguage();
uint id[4];
if (_allPartsComplete) {
- id[0] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg4[_language], 1);
- id[1] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg5[_language], 1);
- id[2] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg6[_language], 1);
- id[3] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg7[_language], 1);
+ id[0] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg4[language], 1);
+ id[1] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg5[language], 1);
+ id[2] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg6[language], 1);
+ id[3] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg7[language], 1);
} else {
- id[0] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg0[_language], 1);
- id[1] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg1[_language], 1);
- id[2] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg2[_language], 1);
- id[3] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg3[_language], 1);
+ id[0] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg0[language], 1);
+ id[1] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg1[language], 1);
+ id[2] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg2[language], 1);
+ id[3] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg3[language], 1);
}
_vm->_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 70);
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index 287618e803..c91421e15e 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -31,6 +31,58 @@
namespace Parallaction {
+#define MOUSEARROW_WIDTH_NS 16
+#define MOUSEARROW_HEIGHT_NS 16
+
+#define MOUSECOMBO_WIDTH_NS 32 // sizes for cursor + selected inventory item
+#define MOUSECOMBO_HEIGHT_NS 32
+
+struct MouseComboProperties {
+ int _xOffset;
+ int _yOffset;
+ int _width;
+ int _height;
+};
+/*
+// TODO: improve NS's handling of normal cursor before merging cursor code.
+MouseComboProperties _mouseComboProps_NS = {
+ 7, // combo x offset (the icon from the inventory will be rendered from here)
+ 7, // combo y offset (ditto)
+ 32, // combo (arrow + icon) width
+ 32 // combo (arrow + icon) height
+};
+*/
+MouseComboProperties _mouseComboProps_BR = {
+ 8, // combo x offset (the icon from the inventory will be rendered from here)
+ 8, // combo y offset (ditto)
+ 68, // combo (arrow + icon) width
+ 68 // combo (arrow + icon) height
+};
+
+Input::Input(Parallaction *vm) : _vm(vm) {
+ _gameType = _vm->getGameType();
+ _transCurrentHoverItem = 0;
+ _hasDelayedAction = false; // actived when the character needs to move before taking an action
+ _mouseState = MOUSE_DISABLED;
+ _activeItem._index = 0;
+ _activeItem._id = 0;
+ _mouseButtons = 0;
+ _delayedActionZone = nullZonePtr;
+
+ initCursors();
+}
+
+Input::~Input() {
+ if (_gameType == GType_Nippon) {
+ delete _mouseArrow;
+ }
+
+ delete _comboArrow;
+ delete _dinoCursor;
+ delete _dougCursor;
+ delete _donnaCursor;
+}
+
// FIXME: the engine has 3 event loops. The following routine hosts the main one,
// and it's called from 8 different places in the code. There exist 2 more specialised
// loops which could possibly be merged into this one with some effort in changing
@@ -79,8 +131,9 @@ void Input::readInput() {
_mousePos = e.mouse;
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _engineFlags |= kEngineQuit;
+ _vm->_quit = true;
return;
default:
@@ -127,9 +180,9 @@ void Input::waitForButtonEvent(uint32 buttonEventMask, int32 timeout) {
}
-void Input::updateGameInput() {
+int Input::updateGameInput() {
- readInput();
+ int event = kEvNone;
if (!isMouseEnabled() ||
(_engineFlags & kEngineWalking) ||
@@ -141,44 +194,38 @@ void Input::updateGameInput() {
(_engineFlags & kEngineChangeLocation) == 0
);
- return;
+ return event;
}
if (_hasKeyPressEvent && (_vm->getFeatures() & GF_DEMO) == 0) {
- if (_keyPressed.keycode == Common::KEYCODE_l) _inputData._event = kEvLoadGame;
- if (_keyPressed.keycode == Common::KEYCODE_s) _inputData._event = kEvSaveGame;
+ if (_keyPressed.keycode == Common::KEYCODE_l) event = kEvLoadGame;
+ if (_keyPressed.keycode == Common::KEYCODE_s) event = kEvSaveGame;
}
- if (_inputData._event == kEvNone) {
- _inputData._mousePos = _mousePos;
+ if (event == kEvNone) {
translateGameInput();
}
+ return event;
}
-InputData* Input::updateInput() {
+int Input::updateInput() {
- _inputData._event = kEvNone;
+ int event = kEvNone;
+ readInput();
switch (_inputMode) {
- case kInputModeComment:
- case kInputModeDialogue:
- case kInputModeMenu:
- readInput();
- break;
-
case kInputModeGame:
- updateGameInput();
+ event = updateGameInput();
break;
case kInputModeInventory:
- readInput();
updateInventoryInput();
break;
}
- return &_inputData;
+ return event;
}
void Input::trackMouse(ZonePtr z) {
@@ -212,7 +259,7 @@ void Input::takeAction(ZonePtr z) {
void Input::walkTo(const Common::Point &dest) {
stopHovering();
- _vm->setArrowCursor();
+ setArrowCursor();
_vm->_char.scheduleWalk(dest.x, dest.y);
}
@@ -252,7 +299,6 @@ bool Input::translateGameInput() {
if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) {
- _inputData._zone = z;
if (z->_flags & kFlagsNoWalk) {
// character doesn't need to walk to take specified action
takeAction(z);
@@ -269,7 +315,7 @@ bool Input::translateGameInput() {
}
_vm->beep();
- _vm->setArrowCursor();
+ setArrowCursor();
return true;
}
@@ -285,7 +331,7 @@ void Input::enterInventoryMode() {
_activeItem._index = (_activeItem._id >> 16) & 0xFFFF;
_engineFlags |= kEngineDragging;
} else {
- _vm->setArrowCursor();
+ setArrowCursor();
}
}
@@ -320,12 +366,12 @@ void Input::exitInventoryMode() {
_vm->closeInventory();
if (pos == -1) {
- _vm->setArrowCursor();
+ setArrowCursor();
} else {
const InventoryItem *item = _vm->getInventoryItem(pos);
if (item->_index != 0) {
_activeItem._id = item->_id;
- _vm->setInventoryCursor(item->_index);
+ setInventoryCursor(item->_index);
}
}
_vm->resumeJobs();
@@ -373,4 +419,96 @@ bool Input::isMouseEnabled() {
return (_mouseState == MOUSE_ENABLED_SHOW) || (_mouseState == MOUSE_ENABLED_HIDE);
}
+
+void Input::initCursors() {
+
+ _dinoCursor = _donnaCursor = _dougCursor = 0;
+
+ switch (_gameType) {
+ case GType_Nippon:
+ _comboArrow = _vm->_disk->loadPointer("pointer");
+ _mouseArrow = new Cnv(1, MOUSEARROW_WIDTH_NS, MOUSEARROW_HEIGHT_NS, _resMouseArrow_NS, false);
+ break;
+
+ case GType_BRA:
+ if (_vm->getPlatform() == Common::kPlatformPC) {
+ _dinoCursor = _vm->_disk->loadPointer("pointer1");
+ _dougCursor = _vm->_disk->loadPointer("pointer2");
+ _donnaCursor = _vm->_disk->loadPointer("pointer3");
+
+ Graphics::Surface *surf = new Graphics::Surface;
+ surf->create(_mouseComboProps_BR._width, _mouseComboProps_BR._height, 1);
+ _comboArrow = new SurfaceToFrames(surf);
+
+ // TODO: choose the pointer depending on the active character
+ // For now, we pick Donna's
+ _mouseArrow = _donnaCursor;
+ } else {
+ // TODO: Where are the Amiga cursors?
+ _mouseArrow = 0;
+ }
+ break;
+
+ default:
+ warning("Input::initCursors: unknown gametype");
+ }
+
+}
+
+void Input::setArrowCursor() {
+
+ switch (_gameType) {
+ case GType_Nippon:
+ debugC(1, kDebugInput, "setting mouse cursor to arrow");
+ // this stuff is needed to avoid artifacts with labels and selected items when switching cursors
+ stopHovering();
+ _activeItem._id = 0;
+ _vm->_system->setMouseCursor(_mouseArrow->getData(0), MOUSEARROW_WIDTH_NS, MOUSEARROW_HEIGHT_NS, 0, 0, 0);
+ break;
+
+ case GType_BRA: {
+ if (_vm->getPlatform() == Common::kPlatformAmiga)
+ return;
+
+ Common::Rect r;
+ _mouseArrow->getRect(0, r);
+ _vm->_system->setMouseCursor(_mouseArrow->getData(0), r.width(), r.height(), 0, 0, 0);
+ _vm->_system->showMouse(true);
+ _activeItem._id = 0;
+ break;
+ }
+
+ default:
+ warning("Input::setArrowCursor: unknown gametype");
+ }
+
+}
+
+void Input::setInventoryCursor(ItemName name) {
+ assert(name > 0);
+
+ switch (_gameType) {
+ case GType_Nippon: {
+ byte *v8 = _comboArrow->getData(0);
+ // FIXME: destination offseting is not clear
+ _vm->_inventoryRenderer->drawItem(name, v8 + 7 * MOUSECOMBO_WIDTH_NS + 7, MOUSECOMBO_WIDTH_NS);
+ _vm->_system->setMouseCursor(v8, MOUSECOMBO_WIDTH_NS, MOUSECOMBO_HEIGHT_NS, 0, 0, 0);
+ break;
+ }
+
+ case GType_BRA: {
+ byte *src = _mouseArrow->getData(0);
+ byte *dst = _comboArrow->getData(0);
+ memcpy(dst, src, _comboArrow->getSize(0));
+ // FIXME: destination offseting is not clear
+ _vm->_inventoryRenderer->drawItem(name, dst + _mouseComboProps_BR._yOffset * _mouseComboProps_BR._width + _mouseComboProps_BR._xOffset, _mouseComboProps_BR._width);
+ _vm->_system->setMouseCursor(dst, _mouseComboProps_BR._width, _mouseComboProps_BR._height, 0, 0, 0);
+ }
+
+ default:
+ warning("Input::setInventoryCursor: unknown gametype");
+ }
+
+}
+
} // namespace Parallaction
diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h
index c1e912db74..e7d20c0d2e 100644
--- a/engines/parallaction/input.h
+++ b/engines/parallaction/input.h
@@ -41,14 +41,6 @@ enum {
kMouseRightDown = 8
};
-struct InputData {
- uint16 _event;
- Common::Point _mousePos;
- int16 _inventoryIndex;
- ZonePtr _zone;
- uint _label;
-};
-
enum MouseTriState {
MOUSE_ENABLED_SHOW,
MOUSE_ENABLED_HIDE,
@@ -56,10 +48,7 @@ enum MouseTriState {
};
class Input {
- void updateGameInput();
-
- // input-only
- InputData _inputData;
+ int updateGameInput();
bool _hasKeyPressEvent;
Common::KeyState _keyPressed;
@@ -69,7 +58,7 @@ class Input {
int16 _transCurrentHoverItem;
- InputData *translateInput();
+ void translateInput();
bool translateGameInput();
bool updateInventoryInput();
void takeAction(ZonePtr z);
@@ -85,6 +74,17 @@ class Input {
void enterInventoryMode();
void exitInventoryMode();
+ int _gameType;
+
+ static byte _resMouseArrow_NS[256];
+ Frames *_mouseArrow;
+ Frames *_comboArrow;
+ Frames *_dinoCursor;
+ Frames *_dougCursor;
+ Frames *_donnaCursor;
+
+ void initCursors();
+
public:
enum {
kInputModeGame = 0,
@@ -95,18 +95,8 @@ public:
};
- Input(Parallaction *vm) : _vm(vm) {
- _transCurrentHoverItem = 0;
- _hasDelayedAction = false; // actived when the character needs to move before taking an action
- _mouseState = MOUSE_DISABLED;
- _activeItem._index = 0;
- _activeItem._id = 0;
- _mouseButtons = 0;
- _delayedActionZone = nullZonePtr;
- }
-
- virtual ~Input() { }
-
+ Input(Parallaction *vm);
+ virtual ~Input();
void getCursorPos(Common::Point& p) {
p = _mousePos;
@@ -116,7 +106,7 @@ public:
InventoryItem _activeItem;
void readInput();
- InputData* updateInput();
+ int updateInput();
void trackMouse(ZonePtr z);
void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1);
uint32 getLastButtonEvent() { return _mouseButtons; }
@@ -129,6 +119,9 @@ public:
void setMouseState(MouseTriState state);
MouseTriState getMouseState();
bool isMouseEnabled();
+
+ void setArrowCursor();
+ void setInventoryCursor(ItemName name);
};
} // namespace Parallaction
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index d2332643ed..b4776250c6 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -180,7 +180,6 @@ Zone::~Zone() {
case kZoneDoor:
free(u.door->_location);
- free(u.door->_background);
u.door->gfxobj->release();
delete u.door;
break;
@@ -191,7 +190,6 @@ Zone::~Zone() {
break;
case kZoneGet:
- free(u.get->_backup);
u.get->gfxobj->release();
delete u.get;
break;
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index 15550c65c6..431d12504e 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -192,23 +192,19 @@ struct Dialogue {
~Dialogue();
};
-struct GetData { // size = 24
+struct GetData {
uint32 _icon;
GfxObj *gfxobj;
- byte *_backup;
- uint16 field_14; // unused
- uint16 field_16; // unused
MaskBuffer _mask[2];
bool hasMask;
GetData() {
_icon = 0;
- _backup = NULL;
gfxobj = NULL;
hasMask = false;
}
};
-struct SpeakData { // size = 36
+struct SpeakData {
char _name[32];
Dialogue *_dialogue;
@@ -217,30 +213,25 @@ struct SpeakData { // size = 36
_dialogue = NULL;
}
};
-struct ExamineData { // size = 28
+struct ExamineData {
GfxObj *_cnv;
- uint16 _opBase; // unused
- uint16 field_12; // unused
char* _description;
char* _filename;
ExamineData() {
- _opBase = 0;
_description = NULL;
_filename = NULL;
_cnv = NULL;
}
};
-struct DoorData { // size = 28
+struct DoorData {
char* _location;
GfxObj *gfxobj;
- byte* _background;
Common::Point _startPos;
uint16 _startFrame;
DoorData() {
_location = NULL;
- _background = NULL;
_startFrame = 0;
gfxobj = NULL;
}
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index c810d22b33..828cb4d021 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -35,6 +35,7 @@
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
#include "parallaction/debug.h"
+#include "parallaction/saveload.h"
#include "parallaction/sound.h"
@@ -47,7 +48,6 @@ Parallaction *_vm = NULL;
// public stuff
char _saveData1[30] = { '\0' };
-uint16 _language = 0;
uint32 _engineFlags = 0;
uint16 _score = 1;
@@ -66,7 +66,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
// FIXME
_vm = this;
- Common::File::addDefaultDirectory( _gameDataPath );
+ Common::File::addDefaultDirectory(_gameDataDir);
Common::addSpecialDebugLevel(kDebugDialogue, "dialogue", "Dialogues debug level");
Common::addSpecialDebugLevel(kDebugParser, "parser", "Parser debug level");
@@ -100,8 +100,6 @@ Parallaction::~Parallaction() {
cleanupGui();
- delete _comboArrow;
-
delete _localFlagNames;
delete _gfx;
delete _soundMan;
@@ -116,7 +114,6 @@ int Parallaction::init() {
_objectsNames = NULL;
_globalFlagsNames = NULL;
_location._hasSound = false;
- _baseTime = 0;
_numLocations = 0;
_location._startPosition.x = -1000;
_location._startPosition.y = -1000;
@@ -124,6 +121,8 @@ int Parallaction::init() {
_location._comment = NULL;
_location._endComment = NULL;
+ _quit = false;
+
_pathBuffer = 0;
_screenSize = _screenWidth * _screenHeight;
@@ -134,6 +133,7 @@ int Parallaction::init() {
initInventory(); // needs to be pushed into subclass
+ // this needs _disk to be already setup
_input = new Input(this);
_gfx = new Gfx(this);
@@ -147,14 +147,6 @@ int Parallaction::init() {
return 0;
}
-
-void Parallaction::clearSet(OpcodeSet &opcodes) {
- for (Common::Array<const Opcode*>::iterator i = opcodes.begin(); i != opcodes.end(); ++i)
- delete *i;
- opcodes.clear();
-}
-
-
void Parallaction::updateView() {
if ((_engineFlags & kEnginePauseJobs) && (_input->_inputMode != Input::kInputModeInventory)) {
@@ -163,7 +155,7 @@ void Parallaction::updateView() {
_gfx->animatePalette();
_gfx->updateScreen();
- g_system->delayMillis(30);
+ _vm->_system->delayMillis(30);
}
@@ -278,7 +270,15 @@ void Parallaction::freeLocation() {
return;
}
+void Parallaction::showSlide(const char *name, int x, int y) {
+ BackgroundInfo *info = new BackgroundInfo;
+ _disk->loadSlide(*info, name);
+ info->x = (x == CENTER_LABEL_HORIZONTAL) ? ((_vm->_screenWidth - info->width) >> 1) : x;
+ info->y = (y == CENTER_LABEL_VERTICAL) ? ((_vm->_screenHeight - info->height) >> 1) : y;
+
+ _gfx->setBackground(kBackgroundSlide, info);
+}
void Parallaction::freeBackground() {
@@ -303,22 +303,19 @@ void Parallaction::showLocationComment(const char *text, bool end) {
}
-void Parallaction::processInput(InputData *data) {
- if (!data) {
- return;
- }
+void Parallaction::processInput(int event) {
- switch (data->_event) {
+ switch (event) {
case kEvSaveGame:
_input->stopHovering();
- saveGame();
- setArrowCursor();
+ _saveLoad->saveGame();
+ _input->setArrowCursor();
break;
case kEvLoadGame:
_input->stopHovering();
- loadGame();
- setArrowCursor();
+ _saveLoad->loadGame();
+ _input->setArrowCursor();
break;
}
@@ -328,8 +325,8 @@ void Parallaction::processInput(InputData *data) {
void Parallaction::runGame() {
- InputData *data = _input->updateInput();
- if (_engineFlags & kEngineQuit)
+ int event = _input->updateInput();
+ if (quit())
return;
runGuiFrame();
@@ -337,10 +334,10 @@ void Parallaction::runGame() {
runCommentFrame();
if (_input->_inputMode == Input::kInputModeGame) {
- processInput(data);
+ processInput(event);
runPendingZones();
- if (_engineFlags & kEngineQuit)
+ if (quit())
return;
if (_engineFlags & kEngineChangeLocation) {
@@ -403,7 +400,7 @@ void Parallaction::doLocationEnterTransition() {
pal.fadeTo(_gfx->_palette, 4);
_gfx->setPalette(pal);
_gfx->updateScreen();
- g_system->delayMillis(20);
+ _vm->_system->delayMillis(20);
}
_gfx->setPalette(_gfx->_palette);
@@ -431,6 +428,387 @@ uint32 Parallaction::getLocationFlags() {
+void Parallaction::drawAnimations() {
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n");
+
+ uint16 layer = 0, scale = 100;
+
+ for (AnimationList::iterator it = _location._animations.begin(); it != _location._animations.end(); it++) {
+
+ AnimationPtr anim = *it;
+ GfxObj *obj = anim->gfxobj;
+
+ // Validation is performed here, so that every animation is affected, instead that only the ones
+ // who *own* a script. In fact, some scripts can change values in other animations.
+ // The right way to do this would be to enforce validation when any variable is modified from
+ // a script.
+ anim->validateScriptVars();
+
+ if ((anim->_flags & kFlagsActive) && ((anim->_flags & kFlagsRemove) == 0)) {
+
+ if (anim->_flags & kFlagsNoMasked)
+ layer = LAYER_FOREGROUND;
+ else {
+ if (getGameType() == GType_Nippon) {
+ // Layer in NS depends on where the animation is on the screen, for each animation.
+ layer = _gfx->_backgroundInfo->getLayer(anim->getFrameY() + anim->height());
+ } else {
+ // Layer in BRA is calculated from Z value. For characters it is the same as NS,
+ // but other animations can have Z set from scripts independently from their
+ // position on the screen.
+ layer = _gfx->_backgroundInfo->getLayer(anim->getZ());
+ }
+ }
+
+ if (getGameType() == GType_BRA) {
+ if (anim->_flags & (kFlagsScaled | kFlagsCharacter)) {
+ if (anim->getZ() <= _location._zeta0) {
+ if (anim->getZ() >= _location._zeta1) {
+ scale = ((anim->getZ() - _location._zeta1) * (100 - _location._zeta2)) / (_location._zeta0 - _location._zeta1) + _location._zeta2;
+ } else {
+ scale = _location._zeta2;
+ }
+ }
+ }
+ }
+
+ if (obj) {
+ _gfx->showGfxObj(obj, true);
+ obj->frame = anim->getF();
+ obj->x = anim->getX();
+ obj->y = anim->getY();
+ obj->z = anim->getZ();
+ obj->layer = layer;
+ obj->scale = scale;
+ }
+ }
+
+ if (((anim->_flags & kFlagsActive) == 0) && (anim->_flags & kFlagsRemove)) {
+ anim->_flags &= ~kFlagsRemove;
+ }
+
+ if ((anim->_flags & kFlagsActive) && (anim->_flags & kFlagsRemove)) {
+ anim->_flags &= ~kFlagsActive;
+ anim->_flags |= kFlagsRemove;
+ if (obj) {
+ _gfx->showGfxObj(obj, false);
+ }
+ }
+ }
+
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n");
+
+ return;
+}
+
+
+void Parallaction::showZone(ZonePtr z, bool visible) {
+ if (!z) {
+ return;
+ }
+
+ if (visible) {
+ z->_flags &= ~kFlagsRemove;
+ z->_flags |= kFlagsActive;
+ } else {
+ z->_flags |= kFlagsRemove;
+ }
+
+ if ((z->_type & 0xFFFF) == kZoneGet) {
+ _gfx->showGfxObj(z->u.get->gfxobj, visible);
+
+ GetData *data = z->u.get;
+ if (data->hasMask && _gfx->_backgroundInfo->hasMask) {
+ if (visible) {
+ _gfx->_backgroundInfo->mask.bltOr(data->gfxobj->x, data->gfxobj->y, data->_mask[0], 0, 0, data->_mask->w, data->_mask->h);
+ } else {
+ _gfx->_backgroundInfo->mask.bltCopy(data->gfxobj->x, data->gfxobj->y, data->_mask[1], 0, 0, data->_mask->w, data->_mask->h);
+ }
+ }
+ }
+}
+
+
+//
+// ZONE TYPE: EXAMINE
+//
+
+void Parallaction::enterCommentMode(ZonePtr z) {
+ if (!z) {
+ return;
+ }
+
+ _commentZone = z;
+
+ ExamineData *data = _commentZone->u.examine;
+
+ if (!data->_description) {
+ return;
+ }
+
+ // TODO: move this balloons stuff into DialogueManager and BalloonManager
+ if (getGameType() == GType_Nippon) {
+ int id;
+ if (data->_filename) {
+ if (data->_cnv == 0) {
+ data->_cnv = _disk->loadStatic(data->_filename);
+ }
+
+ _gfx->setHalfbriteMode(true);
+ _balloonMan->setSingleBalloon(data->_description, 0, 90, 0, BalloonManager::kNormalColor);
+ Common::Rect r;
+ data->_cnv->getRect(0, r);
+ id = _gfx->setItem(data->_cnv, 140, (_screenHeight - r.height())/2);
+ _gfx->setItemFrame(id, 0);
+ id = _gfx->setItem(_char._head, 100, 152);
+ _gfx->setItemFrame(id, 0);
+ } else {
+ _balloonMan->setSingleBalloon(data->_description, 140, 10, 0, BalloonManager::kNormalColor);
+ id = _gfx->setItem(_char._talk, 190, 80);
+ _gfx->setItemFrame(id, 0);
+ }
+ } else
+ if (getGameType() == GType_BRA) {
+ _balloonMan->setSingleBalloon(data->_description, 0, 0, 1, BalloonManager::kNormalColor);
+ int id = _gfx->setItem(_char._talk, 10, 80);
+ _gfx->setItemFrame(id, 0);
+ }
+
+ _input->_inputMode = Input::kInputModeComment;
+}
+
+void Parallaction::exitCommentMode() {
+ _input->_inputMode = Input::kInputModeGame;
+
+ hideDialogueStuff();
+ _gfx->setHalfbriteMode(false);
+
+ _cmdExec->run(_commentZone->_commands, _commentZone);
+ _commentZone = nullZonePtr;
+}
+
+void Parallaction::runCommentFrame() {
+ if (_input->_inputMode != Input::kInputModeComment) {
+ return;
+ }
+
+ if (_input->getLastButtonEvent() == kMouseLeftUp) {
+ exitCommentMode();
+ }
+}
+
+
+void Parallaction::runZone(ZonePtr z) {
+ debugC(3, kDebugExec, "runZone (%s)", z->_name);
+
+ uint16 subtype = z->_type & 0xFFFF;
+
+ debugC(3, kDebugExec, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
+ switch(subtype) {
+
+ case kZoneExamine:
+ enterCommentMode(z);
+ return;
+
+ case kZoneGet:
+ pickupItem(z);
+ break;
+
+ case kZoneDoor:
+ if (z->_flags & kFlagsLocked) break;
+ updateDoor(z, !(z->_flags & kFlagsClosed));
+ break;
+
+ case kZoneHear:
+ _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
+ break;
+
+ case kZoneSpeak:
+ enterDialogueMode(z);
+ return;
+ }
+
+ debugC(3, kDebugExec, "runZone completed");
+
+ _cmdExec->run(z->_commands, z);
+
+ return;
+}
+
+//
+// ZONE TYPE: DOOR
+//
+void Parallaction::updateDoor(ZonePtr z, bool close) {
+ z->_flags = close ? (z->_flags |= kFlagsClosed) : (z->_flags &= ~kFlagsClosed);
+
+ if (z->u.door->gfxobj) {
+ uint frame = (close ? 0 : 1);
+// z->u.door->gfxobj->setFrame(frame);
+ z->u.door->gfxobj->frame = frame;
+ }
+
+ return;
+}
+
+
+
+//
+// ZONE TYPE: GET
+//
+
+bool Parallaction::pickupItem(ZonePtr z) {
+ if (z->_flags & kFlagsFixed) {
+ return false;
+ }
+
+ int slot = addInventoryItem(z->u.get->_icon);
+ if (slot != -1) {
+ showZone(z, false);
+ }
+
+ return (slot != -1);
+}
+
+// FIXME: input coordinates must be offseted to handle scrolling!
+bool Parallaction::checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
+ // not a special zone
+ if ((z->getX() != -2) && (z->getX() != -3)) {
+ return false;
+ }
+
+ // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
+ // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
+ // but we need to check it separately here. The same workaround is applied in freeZones.
+ if ((((z->_type & 0xFFFF) == kZoneMerge) && (((x == z->u.merge->_obj1) && (y == z->u.merge->_obj2)) || ((x == z->u.merge->_obj2) && (y == z->u.merge->_obj1)))) ||
+ (((z->_type & 0xFFFF) == kZoneGet) && ((x == z->u.get->_icon) || (y == z->u.get->_icon)))) {
+
+ // WORKAROUND for bug 2070751: special zones are only used in NS, to allow the
+ // the EXAMINE/USE action to be applied on some particular item in the inventory.
+ // The usage a verb requires at least an item match, so type can't be 0, as it
+ // was in the original code. This bug has been here since the beginning, and was
+ // hidden by label code, which filtered the bogus matches produced here.
+
+ // look for action + item match
+ if (z->_type == type)
+ return true;
+ // look for item match, but don't accept 0 types
+ if (((z->_type & 0xFFFF0000) == type) && (type))
+ return true;
+ }
+
+ return false;
+}
+
+// FIXME: input coordinates must be offseted to handle scrolling!
+bool Parallaction::checkZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
+ if (z->_flags & kFlagsRemove)
+ return false;
+
+ debugC(5, kDebugExec, "checkZoneBox for %s (type = %x, x = %i, y = %i)", z->_name, type, x, y);
+
+ Common::Rect r;
+ z->getBox(r);
+ r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
+ r.bottom++;
+
+ r.grow(-1); // allows some tolerance for mouse click
+
+ if (!r.contains(x, y)) {
+
+ // check for special zones (items defined in common.loc)
+ if (checkSpecialZoneBox(z, type, x, y))
+ return true;
+
+ if (z->getX() != -1)
+ return false;
+ if ((int)x < _char._ani->getFrameX())
+ return false;
+ if ((int)x > (_char._ani->getFrameX() + _char._ani->width()))
+ return false;
+ if ((int)y < _char._ani->getFrameY())
+ return false;
+ if ((int)y > (_char._ani->getFrameY() + _char._ani->height()))
+ return false;
+ }
+
+ // normal Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return true;
+ if (z->_type == type)
+ return true;
+ if ((z->_type & 0xFFFF0000) == type)
+ return true;
+
+ return false;
+}
+
+// FIXME: input coordinates must be offseted to handle scrolling!
+bool Parallaction::checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y) {
+ if (z->_flags & kFlagsRemove)
+ return false;
+
+ if ((z->_flags & kFlagsAnimLinked) == 0)
+ return false;
+
+ debugC(5, kDebugExec, "checkLinkedAnimBox for %s (type = %x, x = %i, y = %i)", z->_name, type, x, y);
+
+ AnimationPtr anim = z->_linkedAnim;
+ Common::Rect r(anim->getFrameX(), anim->getFrameY(), anim->getFrameX() + anim->width() + 1, anim->getFrameY() + anim->height() + 1);
+
+ if (!r.contains(x, y)) {
+ return false;
+ }
+
+ // NOTE: the implementation of the following lines is a different in the
+ // original... it is working so far, though
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return true;
+ if (z->_type == type)
+ return true;
+ if ((z->_type & 0xFFFF0000) == type)
+ return true;
+
+ return false;
+}
+
+ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
+ uint16 _di = y;
+ uint16 _si = x;
+
+ for (ZoneList::iterator it = _location._zones.begin(); it != _location._zones.end(); it++) {
+ if (checkLinkedAnimBox(*it, type, x, y)) {
+ return *it;
+ }
+ if (checkZoneBox(*it, type, x, y)) {
+ return *it;
+ }
+ }
+
+
+ int16 _a, _b, _c, _d, _e, _f;
+ for (AnimationList::iterator ait = _location._animations.begin(); ait != _location._animations.end(); ait++) {
+
+ AnimationPtr a = *ait;
+
+ _a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
+ _e = ((_si >= a->getFrameX() + a->width()) || (_si <= a->getFrameX())) ? 0 : 1; // _e: horizontal range
+ _f = ((_di >= a->getFrameY() + a->height()) || (_di <= a->getFrameY())) ? 0 : 1; // _f: vertical range
+
+ _b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
+ _c = (a->_type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
+ _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
+
+ if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
+
+ return a;
+
+ }
+
+ }
+
+ return nullZonePtr;
+}
+
ZonePtr Parallaction::findZone(const char *name) {
@@ -443,7 +821,7 @@ ZonePtr Parallaction::findZone(const char *name) {
void Parallaction::freeZones() {
- debugC(2, kDebugExec, "freeZones: kEngineQuit = %i", _engineFlags & kEngineQuit);
+ debugC(2, kDebugExec, "freeZones: _vm->_quit = %i", _vm->_quit);
ZoneList::iterator it = _location._zones.begin();
@@ -452,7 +830,7 @@ void Parallaction::freeZones() {
// NOTE : this condition has been relaxed compared to the original, to allow the engine
// to retain special - needed - zones that were lost across location switches.
ZonePtr z = *it;
- if (((z->getY() == -1) || (z->getX() == -2)) && ((_engineFlags & kEngineQuit) == 0)) {
+ if (((z->getY() == -1) || (z->getX() == -2)) && (_quit == 0)) {
debugC(2, kDebugExec, "freeZones preserving zone '%s'", z->_name);
it++;
} else {
@@ -514,7 +892,7 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation) {
_ani->setY(100);
_ani->setZ(10);
_ani->setF(0);
- _ani->_flags = kFlagsActive | kFlagsNoName;
+ _ani->_flags = kFlagsActive | kFlagsNoName | kFlagsCharacter;
_ani->_type = kZoneYou;
strncpy(_ani->_name, "yourself", ZONENAME_LENGTH);
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index fb004a25b7..d7add635cd 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -29,6 +29,7 @@
#include "common/str.h"
#include "common/stack.h"
#include "common/array.h"
+#include "common/func.h"
#include "common/savefile.h"
#include "engines/engine.h"
@@ -44,8 +45,6 @@
#define PATH_LEN 200
-extern OSystem *g_system;
-
namespace Parallaction {
enum {
@@ -71,35 +70,7 @@ enum {
};
-// high values mean high priority
-
-enum {
- kPriority0 = 0,
- kPriority1 = 1,
- kPriority2 = 2,
- kPriority3 = 3,
- kPriority4 = 4,
- kPriority5 = 5,
- kPriority6 = 6,
- kPriority7 = 7,
- kPriority8 = 8,
- kPriority9 = 9,
- kPriority10 = 10,
- kPriority11 = 11,
- kPriority12 = 12,
- kPriority13 = 13,
- kPriority14 = 14,
- kPriority15 = 15,
- kPriority16 = 16,
- kPriority17 = 17,
- kPriority18 = 18,
- kPriority19 = 19,
- kPriority20 = 20,
- kPriority21 = 21
-};
-
enum EngineFlags {
- kEngineQuit = (1 << 0),
kEnginePauseJobs = (1 << 1),
kEngineWalking = (1 << 3),
kEngineChangeLocation = (1 << 4),
@@ -116,10 +87,6 @@ enum {
kEvLoadGame = 4000
};
-enum {
- kCursorArrow = -1
-};
-
enum ParallactionGameType {
GType_Nippon = 1,
GType_BRA
@@ -130,10 +97,8 @@ struct PARALLACTIONGameDescription;
-extern uint16 _mouseButtons;
extern char _password[8];
extern uint16 _score;
-extern uint16 _language;
extern uint32 _engineFlags;
extern char _saveData1[];
extern uint32 _globalFlags;
@@ -238,6 +203,7 @@ public:
};
+class SaveLoad;
#define NUM_LOCATIONS 120
@@ -245,231 +211,148 @@ class Parallaction : public Engine {
friend class Debugger;
public:
-
- Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gameDesc);
- ~Parallaction();
-
- int init();
-
- virtual bool loadGame() = 0;
- virtual bool saveGame() = 0;
-
- Input *_input;
-
- void processInput(InputData* data);
-
- void pauseJobs();
- void resumeJobs();
-
- ZonePtr findZone(const char *name);
- ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
- void runZone(ZonePtr z);
- void freeZones();
-
- AnimationPtr findAnimation(const char *name);
- void freeAnimations();
-
- void setBackground(const char *background, const char *mask, const char *path);
- void freeBackground();
-
- Table *_globalFlagsNames;
- Table *_objectsNames;
- Table *_callableNames;
- Table *_localFlagNames;
-
-public:
int getGameType() const;
uint32 getFeatures() const;
Common::Language getLanguage() const;
Common::Platform getPlatform() const;
+protected: // members
+ bool detectGame(void);
+
private:
const PARALLACTIONGameDescription *_gameDescription;
+ uint16 _language;
public:
+ Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gameDesc);
+ ~Parallaction();
+
+ int init();
+
// info
int32 _screenWidth;
int32 _screenHeight;
int32 _screenSize;
- PathBuffer *_pathBuffer;
-
+ // subsystems
+ Gfx *_gfx;
+ Disk *_disk;
+ Input *_input;
SoundMan *_soundMan;
+ Debugger *_debugger;
+ SaveLoad *_saveLoad;
+ MenuInputHelper *_menuHelper;
+ Common::RandomSource _rnd;
- Gfx* _gfx;
- Disk* _disk;
+ // fonts
+ Font *_labelFont;
+ Font *_menuFont;
+ Font *_introFont;
+ Font *_dialogueFont;
- CommandExec* _cmdExec;
- ProgramExec* _programExec;
+ // game utilities
+ Table *_globalFlagsNames;
+ Table *_objectsNames;
+ Table *_callableNames;
+ Table *_localFlagNames;
+ CommandExec *_cmdExec;
+ ProgramExec *_programExec;
+ PathBuffer *_pathBuffer;
+ Inventory *_inventory;
+ BalloonManager *_balloonMan;
+ DialogueManager *_dialogueMan;
+ InventoryRenderer *_inventoryRenderer;
+
+ // game data
Character _char;
-
- void setLocationFlags(uint32 flags);
- void clearLocationFlags(uint32 flags);
- void toggleLocationFlags(uint32 flags);
- uint32 getLocationFlags();
-
uint32 _localFlags[NUM_LOCATIONS];
char _locationNames[NUM_LOCATIONS][32];
int16 _currentLocationIndex;
uint16 _numLocations;
Location _location;
-
ZonePtr _activeZone;
+ char _characterName1[50]; // only used in changeCharacter
+ ZonePtr _zoneTrap;
+ ZonePtr _commentZone;
+ bool _quit; /* The only reason this flag exists is for freeZones() to properly
+ * delete all zones when necessary. THIS FLAG IS NOT THE ENGINE QUIT FLAG,
+ * use _eventMan->shouldQuit() for that.
+ */
- Font *_labelFont;
- Font *_menuFont;
- Font *_introFont;
- Font *_dialogueFont;
-
- Common::RandomSource _rnd;
-
- Debugger *_debugger;
- Frames *_comboArrow;
-
-
-protected: // data
- uint32 _baseTime;
- char _characterName1[50]; // only used in changeCharacter
-
- Common::String _saveFileName;
-
-
-protected: // members
- bool detectGame(void);
-
- void initGlobals();
- void runGame();
- void updateView();
-
- void doLocationEnterTransition();
- virtual void changeLocation(char *location) = 0;
- virtual void runPendingZones() = 0;
- void allocateLocationSlot(const char *name);
- void finalizeLocationParsing();
- void freeLocation();
- void showLocationComment(const char *text, bool end);
-
- void displayComment(ExamineData *data);
-
- void freeCharacter();
-
- bool pickupItem(ZonePtr z);
-
- void clearSet(OpcodeSet &opcodes);
-
+protected:
+ void runGame();
+ void runGuiFrame();
+ void cleanupGui();
+ void runDialogueFrame();
+ void exitDialogueMode();
+ void runCommentFrame();
+ void enterCommentMode(ZonePtr z);
+ void exitCommentMode();
+ void processInput(int event);
+ void updateView();
+ void drawAnimations();
+ void freeCharacter();
+ void freeLocation();
+ void doLocationEnterTransition();
+ void allocateLocationSlot(const char *name);
+ void finalizeLocationParsing();
+ void showLocationComment(const char *text, bool end);
+ void setupBalloonManager();
public:
- void scheduleLocationSwitch(const char *location);
- virtual void changeCharacter(const char *name) = 0;
-
- virtual void callFunction(uint index, void* parm) { }
-
- virtual void setArrowCursor() = 0;
- virtual void setInventoryCursor(ItemName name) = 0;
-
- virtual void parseLocation(const char* name) = 0;
-
- void updateDoor(ZonePtr z, bool close);
-
- virtual void drawAnimations() = 0;
-
- void beep();
-
- ZonePtr _zoneTrap;
- PathBuilder* getPathBuilder(Character *ch);
+ void beep();
+ void pauseJobs();
+ void resumeJobs();
+ void hideDialogueStuff();
+ uint getInternLanguage();
+ void setInternLanguage(uint id);
+ void enterDialogueMode(ZonePtr z);
+ void scheduleLocationSwitch(const char *location);
+ void showSlide(const char *name, int x = 0, int y = 0);
public:
-// const char **_zoneFlagNamesRes;
-// const char **_zoneTypeNamesRes;
-// const char **_commandsNamesRes;
- const char **_callableNamesRes;
- const char **_instructionNamesRes;
-
- void highlightInventoryItem(ItemPosition pos);
- int16 getHoverInventoryItem(int16 x, int16 y);
- int addInventoryItem(ItemName item);
- int addInventoryItem(ItemName item, uint32 value);
- void dropItem(uint16 v);
- bool isItemInInventory(int32 v);
- const InventoryItem* getInventoryItem(int16 pos);
- int16 getInventoryItemIndex(int16 pos);
- void initInventory();
- void destroyInventory();
- void cleanInventory(bool keepVerbs = true);
- void openInventory();
- void closeInventory();
-
- Inventory *_inventory;
- InventoryRenderer *_inventoryRenderer;
-
- BalloonManager *_balloonMan;
-
- void setupBalloonManager();
-
- void hideDialogueStuff();
- DialogueManager *_dialogueMan;
- void enterDialogueMode(ZonePtr z);
- void exitDialogueMode();
- void runDialogueFrame();
-
- MenuInputHelper *_menuHelper;
- void runGuiFrame();
- void cleanupGui();
-
- ZonePtr _commentZone;
- void enterCommentMode(ZonePtr z);
- void exitCommentMode();
- void runCommentFrame();
-
- void setInternLanguage(uint id);
- uint getInternLanguage();
+ void setLocationFlags(uint32 flags);
+ void clearLocationFlags(uint32 flags);
+ void toggleLocationFlags(uint32 flags);
+ uint32 getLocationFlags();
+ bool checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y);
+ bool checkZoneBox(ZonePtr z, uint32 type, uint x, uint y);
+ bool checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y);
+ ZonePtr findZone(const char *name);
+ ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
+ void runZone(ZonePtr z);
+ void freeZones();
+ bool pickupItem(ZonePtr z);
+ void updateDoor(ZonePtr z, bool close);
+ void showZone(ZonePtr z, bool visible);
+ AnimationPtr findAnimation(const char *name);
+ void freeAnimations();
+ void setBackground(const char *background, const char *mask, const char *path);
+ void freeBackground();
+ void highlightInventoryItem(ItemPosition pos);
+ int16 getHoverInventoryItem(int16 x, int16 y);
+ int addInventoryItem(ItemName item);
+ int addInventoryItem(ItemName item, uint32 value);
+ void dropItem(uint16 v);
+ bool isItemInInventory(int32 v);
+ const InventoryItem* getInventoryItem(int16 pos);
+ int16 getInventoryItemIndex(int16 pos);
+ void initInventory();
+ void destroyInventory();
+ void cleanInventory(bool keepVerbs = true);
+ void openInventory();
+ void closeInventory();
- void showZone(ZonePtr z, bool visible);
+ virtual void parseLocation(const char* name) = 0;
+ virtual void changeLocation(char *location) = 0;
+ virtual void changeCharacter(const char *name) = 0;
+ virtual void callFunction(uint index, void* parm) = 0;
+ virtual void runPendingZones() = 0;
+ virtual void cleanupGame() = 0;
};
-class LocationName {
-
- Common::String _slide;
- Common::String _character;
- Common::String _location;
-
- bool _hasCharacter;
- bool _hasSlide;
- char *_buf;
-
-public:
- LocationName();
- ~LocationName();
-
- void bind(const char*);
-
- const char *location() const {
- return _location.c_str();
- }
-
- bool hasCharacter() const {
- return _hasCharacter;
- }
-
- const char *character() const {
- return _character.c_str();
- }
-
- bool hasSlide() const {
- return _hasSlide;
- }
-
- const char *slide() const {
- return _slide.c_str();
- }
-
- const char *c_str() const {
- return _buf;
- }
-};
-
class Parallaction_ns : public Parallaction {
@@ -481,70 +364,45 @@ public:
int go();
public:
- typedef void (Parallaction_ns::*Callable)(void*);
-
- virtual void callFunction(uint index, void* parm);
+ virtual void parseLocation(const char *filename);
+ virtual void changeLocation(char *location);
+ virtual void changeCharacter(const char *name);
+ virtual void callFunction(uint index, void* parm);
+ virtual void runPendingZones();
+ virtual void cleanupGame();
- bool loadGame();
- bool saveGame();
- void switchBackground(const char* background, const char* mask);
- void showSlide(const char *name, int x = 0, int y = 0);
- void setArrowCursor();
-
- // TODO: this should be private!!!!!!!
- bool _inTestResult;
- void cleanupGame();
- bool allPartsComplete();
+ void switchBackground(const char* background, const char* mask);
private:
- LocationParser_ns *_locationParser;
- ProgramParser_ns *_programParser;
-
- void initFonts();
- void freeFonts();
- void renameOldSavefiles();
- Common::String genSaveFileName(uint slot, bool oldStyle = false);
- Common::InSaveFile *getInSaveFile(uint slot);
- Common::OutSaveFile *getOutSaveFile(uint slot);
- void setPartComplete(const Character& character);
+ bool _inTestResult;
+ LocationParser_ns *_locationParser;
+ ProgramParser_ns *_programParser;
private:
- void changeLocation(char *location);
- void changeCharacter(const char *name);
- void runPendingZones();
-
- void setInventoryCursor(ItemName name);
-
-
- void doLoadGame(uint16 slot);
- void doSaveGame(uint16 slot, const char* name);
- int buildSaveFileList(Common::StringList& l);
- int selectSaveFile(uint16 arg_0, const char* caption, const char* button);
-
- void initResources();
- void initCursors();
-
- static byte _resMouseArrow[256];
- byte *_mouseArrow;
-
- static const Callable _dosCallables[25];
- static const Callable _amigaCallables[25];
+ void initFonts();
+ void freeFonts();
+ void initResources();
+ void startGui();
+ void startCreditSequence();
+ void startEndPartSequence();
+ void loadProgram(AnimationPtr a, const char *filename);
- /*
- game callables data members
- */
+ // callables data
+ typedef void (Parallaction_ns::*Callable)(void*);
+ const Callable *_callables;
ZonePtr _moveSarcZone0;
ZonePtr _moveSarcZone1;
uint16 num_foglie;
int16 _introSarcData1;
uint16 _introSarcData2; // sarcophagus stuff to be saved
uint16 _introSarcData3; // sarcophagus stuff to be saved
-
ZonePtr _moveSarcZones[5];
ZonePtr _moveSarcExaZones[5];
AnimationPtr _rightHandAnim;
+ static const Callable _dosCallables[25];
+ static const Callable _amigaCallables[25];
// common callables
void _c_play_boogie(void*);
@@ -578,20 +436,6 @@ private:
void _c_startMusic(void*);
void _c_closeMusic(void*);
void _c_HBOn(void*);
-
- const Callable *_callables;
-
-protected:
- void drawAnimations();
-
- void parseLocation(const char *filename);
- void loadProgram(AnimationPtr a, const char *filename);
-
- void selectStartLocation();
-
- void startGui();
- void startCreditSequence();
- void startEndPartSequence();
};
@@ -600,8 +444,6 @@ protected:
class Parallaction_br : public Parallaction_ns {
- typedef Parallaction_ns Super;
-
public:
Parallaction_br(OSystem* syst, const PARALLACTIONGameDescription *gameDesc) : Parallaction_ns(syst, gameDesc) { }
~Parallaction_br();
@@ -610,83 +452,55 @@ public:
int go();
public:
- typedef void (Parallaction_br::*Callable)(void*);
+ virtual void parseLocation(const char* name);
+ virtual void changeLocation(char *location);
+ virtual void changeCharacter(const char *name);
virtual void callFunction(uint index, void* parm);
- void changeCharacter(const char *name);
+ virtual void runPendingZones();
+ virtual void cleanupGame();
+
+
void setupSubtitles(char *s, char *s2, int y);
void clearSubtitles();
-
public:
Table *_countersNames;
-
const char **_audioCommandsNamesRes;
-
+ static const char *_partNames[];
int _part;
- int _progress;
-
#if 0 // disabled since I couldn't find any references to lip sync in the scripts
int16 _lipSyncVal;
uint _subtitleLipSync;
#endif
int _subtitleY;
int _subtitle[2];
-
ZonePtr _activeZone2;
-
int32 _counters[32];
-
uint32 _zoneFlags[NUM_LOCATIONS][NUM_ZONES];
- void startPart(uint part);
- void setArrowCursor();
+
private:
LocationParser_br *_locationParser;
ProgramParser_br *_programParser;
- void initResources();
- void initFonts();
- void freeFonts();
-
- void setInventoryCursor(ItemName name);
-
- void changeLocation(char *location);
- void runPendingZones();
-
- void initPart();
- void freePart();
-
- void initCursors();
-
- Frames *_dinoCursor;
- Frames *_dougCursor;
- Frames *_donnaCursor;
- Frames *_mouseArrow;
-
-
- static const char *_partNames[];
-
- void startGui();
+private:
+ void initResources();
+ void initFonts();
+ void freeFonts();
+ void freeLocation();
+ void loadProgram(AnimationPtr a, const char *filename);
+ void startGui(bool showSplash);
+ typedef void (Parallaction_br::*Callable)(void*);
+ const Callable *_callables;
static const Callable _dosCallables[6];
+ // dos callables
void _c_blufade(void*);
void _c_resetpalette(void*);
void _c_ferrcycle(void*);
void _c_lipsinc(void*);
void _c_albcycle(void*);
void _c_password(void*);
-
- const Callable *_callables;
-
- void parseLocation(const char* name);
- void loadProgram(AnimationPtr a, const char *filename);
-
-#if 0
- void jobWaitRemoveLabelJob(void *parm, Job *job);
- void jobPauseSfx(void *parm, Job *job);
- void jobStopFollower(void *parm, Job *job);
- void jobScroll(void *parm, Job *job);
-#endif
};
// FIXME: remove global
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index bb8ddc5654..a06fba43f9 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -28,31 +28,11 @@
#include "parallaction/parallaction.h"
#include "parallaction/input.h"
+#include "parallaction/saveload.h"
#include "parallaction/sound.h"
namespace Parallaction {
-struct MouseComboProperties {
- int _xOffset;
- int _yOffset;
- int _width;
- int _height;
-};
-/*
-// TODO: improve NS's handling of normal cursor before merging cursor code.
-MouseComboProperties _mouseComboProps_NS = {
- 7, // combo x offset (the icon from the inventory will be rendered from here)
- 7, // combo y offset (ditto)
- 32, // combo (arrow + icon) width
- 32 // combo (arrow + icon) height
-};
-*/
-MouseComboProperties _mouseComboProps_BR = {
- 8, // combo x offset (the icon from the inventory will be rendered from here)
- 8, // combo y offset (ditto)
- 68, // combo (arrow + icon) width
- 68 // combo (arrow + icon) height
-};
const char *Parallaction_br::_partNames[] = {
"PART0",
@@ -62,14 +42,6 @@ const char *Parallaction_br::_partNames[] = {
"PART4"
};
-const char *partFirstLocation[] = {
- "intro",
- "museo",
- "start",
- "bolscoi",
- "treno"
-};
-
int Parallaction_br::init() {
_screenWidth = 640;
@@ -96,7 +68,6 @@ int Parallaction_br::init() {
initResources();
initFonts();
- initCursors();
_locationParser = new LocationParser_br(this);
_locationParser->init();
_programParser = new ProgramParser_br(this);
@@ -112,6 +83,8 @@ int Parallaction_br::init() {
_subtitle[0] = -1;
_subtitle[1] = -1;
+ _saveLoad = new SaveLoad_br(this, _saveFileMan);
+
Parallaction::init();
return 0;
@@ -119,12 +92,6 @@ int Parallaction_br::init() {
Parallaction_br::~Parallaction_br() {
freeFonts();
-
- delete _dinoCursor;
- delete _dougCursor;
- delete _donnaCursor;
-
- delete _mouseArrow;
}
void Parallaction_br::callFunction(uint index, void* parm) {
@@ -135,25 +102,27 @@ void Parallaction_br::callFunction(uint index, void* parm) {
int Parallaction_br::go() {
- if (getFeatures() & GF_DEMO) {
- startPart(1);
- } else {
- startGui();
- }
+ bool splash = true;
- while ((_engineFlags & kEngineQuit) == 0) {
+ while (!quit()) {
+
+ if (getFeatures() & GF_DEMO) {
+ scheduleLocationSwitch("camalb.1");
+ _input->_inputMode = Input::kInputModeGame;
+ } else {
+ startGui(splash);
+ // don't show splash after first time
+ splash = false;
+ }
// initCharacter();
- _input->_inputMode = Input::kInputModeGame;
- while ((_engineFlags & (kEngineReturn | kEngineQuit)) == 0) {
+ while (((_engineFlags & kEngineReturn) == 0) && (!quit())) {
runGame();
}
_engineFlags &= ~kEngineReturn;
- freePart();
-// freeCharacter();
-
+ cleanupGame();
}
return 0;
@@ -169,70 +138,6 @@ void Parallaction_br::freeFonts() {
return;
}
-void Parallaction_br::initCursors() {
-
- if (getPlatform() == Common::kPlatformPC) {
- _dinoCursor = _disk->loadPointer("pointer1");
- _dougCursor = _disk->loadPointer("pointer2");
- _donnaCursor = _disk->loadPointer("pointer3");
-
- Graphics::Surface *surf = new Graphics::Surface;
- surf->create(_mouseComboProps_BR._width, _mouseComboProps_BR._height, 1);
- _comboArrow = new SurfaceToFrames(surf);
-
- // TODO: choose the pointer depending on the active character
- // For now, we pick Donna's
- _mouseArrow = _donnaCursor;
- } else {
- // TODO: Where are the Amiga cursors?
- }
-
-}
-
-void Parallaction_br::initPart() {
-
- memset(_counters, 0, ARRAYSIZE(_counters));
-
- _globalFlagsNames = _disk->loadTable("global");
- _objectsNames = _disk->loadTable("objects");
- _countersNames = _disk->loadTable("counters");
-
- // TODO: maybe handle this into Disk
- if (getPlatform() == Common::kPlatformPC) {
- _char._objs = _disk->loadObjects("icone.ico");
- } else {
- _char._objs = _disk->loadObjects("icons.ico");
- }
-
-}
-
-void Parallaction_br::freePart() {
-
- delete _globalFlagsNames;
- delete _objectsNames;
- delete _countersNames;
-
- _globalFlagsNames = 0;
- _objectsNames = 0;
- _countersNames = 0;
-}
-
-void Parallaction_br::startPart(uint part) {
- _part = part;
- _disk->selectArchive(_partNames[_part]);
-
- initPart();
-
- if (getFeatures() & GF_DEMO) {
- strcpy(_location._name, "camalb");
- } else {
- strcpy(_location._name, partFirstLocation[_part]);
- }
-
- parseLocation("common");
- changeLocation(_location._name);
-
-}
void Parallaction_br::runPendingZones() {
ZonePtr z;
@@ -260,8 +165,7 @@ void Parallaction_br::runPendingZones() {
}
}
-
-void Parallaction_br::changeLocation(char *location) {
+void Parallaction_br::freeLocation() {
// free open location stuff
clearSubtitles();
@@ -279,27 +183,75 @@ void Parallaction_br::changeLocation(char *location) {
_location._animations.push_front(_char._ani);
-// free(_location._comment);
-// _location._comment = 0;
+ free(_location._comment);
+ _location._comment = 0;
_location._commands.clear();
_location._aCommands.clear();
+}
+
+void Parallaction_br::cleanupGame() {
+ freeLocation();
+
+// freeCharacter();
+
+ delete _globalFlagsNames;
+ delete _objectsNames;
+ delete _countersNames;
+
+ _globalFlagsNames = 0;
+ _objectsNames = 0;
+ _countersNames = 0;
+}
+
+
+void Parallaction_br::changeLocation(char *location) {
+ char *partStr = strrchr(location, '.');
+ if (partStr) {
+ int n = partStr - location;
+ strncpy(_location._name, location, n);
+ _location._name[n] = '\0';
+
+ _part = atoi(++partStr);
+ if (getFeatures() & GF_DEMO) {
+ assert(_part == 1);
+ } else {
+ assert(_part >= 0 && _part <= 4);
+ }
+
+ _disk->selectArchive(_partNames[_part]);
+
+ memset(_counters, 0, ARRAYSIZE(_counters));
+
+ _globalFlagsNames = _disk->loadTable("global");
+ _objectsNames = _disk->loadTable("objects");
+ _countersNames = _disk->loadTable("counters");
+
+ // TODO: maybe handle this into Disk
+ if (getPlatform() == Common::kPlatformPC) {
+ _char._objs = _disk->loadObjects("icone.ico");
+ } else {
+ _char._objs = _disk->loadObjects("icons.ico");
+ }
+
+ parseLocation("common");
+ }
+
+ freeLocation();
// load new location
parseLocation(location);
-
- // kFlagsRemove is cleared because the character defaults to visible on new locations
- // script command can hide the character, anyway, so that's why the flag is cleared
- // before _location._commands are executed
+ // kFlagsRemove is cleared because the character is visible by default.
+ // Commands can hide the character, anyway.
_char._ani->_flags &= ~kFlagsRemove;
-
_cmdExec->run(_location._commands);
-// doLocationEnterTransition();
+
+ doLocationEnterTransition();
+
_cmdExec->run(_location._aCommands);
_engineFlags &= ~kEngineChangeLocation;
}
-
// FIXME: Parallaction_br::parseLocation() is now a verbatim copy of the same routine from Parallaction_ns.
void Parallaction_br::parseLocation(const char *filename) {
debugC(1, kDebugParser, "parseLocation('%s')", filename);
@@ -359,30 +311,5 @@ void Parallaction_br::changeCharacter(const char *name) {
}
-void Parallaction_br::setArrowCursor() {
- // FIXME: Where are the Amiga cursors?
- if (getPlatform() == Common::kPlatformAmiga)
- return;
-
- Common::Rect r;
- _mouseArrow->getRect(0, r);
-
- _system->setMouseCursor(_mouseArrow->getData(0), r.width(), r.height(), 0, 0, 0);
- _system->showMouse(true);
-
- _input->_activeItem._id = 0;
-}
-
-void Parallaction_br::setInventoryCursor(ItemName name) {
- assert(name > 0);
-
- byte *src = _mouseArrow->getData(0);
- byte *dst = _comboArrow->getData(0);
- memcpy(dst, src, _comboArrow->getSize(0));
-
- // FIXME: destination offseting is not clear
- _inventoryRenderer->drawItem(name, dst + _mouseComboProps_BR._yOffset * _mouseComboProps_BR._width + _mouseComboProps_BR._xOffset, _mouseComboProps_BR._width);
- _system->setMouseCursor(dst, _mouseComboProps_BR._width, _mouseComboProps_BR._height, 0, 0, 0);
-}
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 61f2859e8a..8e11931c28 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -29,27 +29,61 @@
#include "parallaction/parallaction.h"
#include "parallaction/input.h"
+#include "parallaction/saveload.h"
#include "parallaction/sound.h"
namespace Parallaction {
-#define MOUSEARROW_WIDTH 16
-#define MOUSEARROW_HEIGHT 16
+class LocationName {
-#define MOUSECOMBO_WIDTH 32 // sizes for cursor + selected inventory item
-#define MOUSECOMBO_HEIGHT 32
+ Common::String _slide;
+ Common::String _character;
+ Common::String _location;
-LocationName::LocationName() {
- _buf = 0;
- _hasSlide = false;
- _hasCharacter = false;
-}
+ bool _hasCharacter;
+ bool _hasSlide;
+ char *_buf;
+
+public:
+ LocationName() {
+ _buf = 0;
+ _hasSlide = false;
+ _hasCharacter = false;
+ }
+
+ ~LocationName() {
+ free(_buf);
+ }
+
+ void bind(const char*);
+
+ const char *location() const {
+ return _location.c_str();
+ }
+
+ bool hasCharacter() const {
+ return _hasCharacter;
+ }
+
+ const char *character() const {
+ return _character.c_str();
+ }
+
+ bool hasSlide() const {
+ return _hasSlide;
+ }
+
+ const char *slide() const {
+ return _slide.c_str();
+ }
+
+ const char *c_str() const {
+ return _buf;
+ }
+};
-LocationName::~LocationName() {
- free(_buf);
-}
/*
@@ -135,7 +169,6 @@ int Parallaction_ns::init() {
initResources();
initFonts();
- initCursors();
_locationParser = new LocationParser_ns(this);
_locationParser->init();
_programParser = new ProgramParser_ns(this);
@@ -156,6 +189,8 @@ int Parallaction_ns::init() {
_location._animations.push_front(_char._ani);
+ _saveLoad = new SaveLoad_ns(this, _saveFileMan);
+
Parallaction::init();
return 0;
@@ -181,32 +216,6 @@ void Parallaction_ns::freeFonts() {
}
-void Parallaction_ns::initCursors() {
- _comboArrow = _disk->loadPointer("pointer");
- _mouseArrow = _resMouseArrow;
-}
-
-void Parallaction_ns::setArrowCursor() {
-
- debugC(1, kDebugInput, "setting mouse cursor to arrow");
-
- // this stuff is needed to avoid artifacts with labels and selected items when switching cursors
- _input->stopHovering();
- _input->_activeItem._id = 0;
-
- _system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
-}
-
-void Parallaction_ns::setInventoryCursor(ItemName name) {
- assert(name > 0);
-
- byte *v8 = _comboArrow->getData(0);
-
- // FIXME: destination offseting is not clear
- _inventoryRenderer->drawItem(name, v8 + 7 * MOUSECOMBO_WIDTH + 7, MOUSECOMBO_WIDTH);
- _system->setMouseCursor(v8, MOUSECOMBO_WIDTH, MOUSECOMBO_HEIGHT, 0, 0, 0);
-}
-
void Parallaction_ns::callFunction(uint index, void* parm) {
assert(index < 25); // magic value 25 is maximum # of callables for Nippon Safes
@@ -216,13 +225,13 @@ void Parallaction_ns::callFunction(uint index, void* parm) {
int Parallaction_ns::go() {
- renameOldSavefiles();
+ _saveLoad->renameOldSavefiles();
_globalFlagsNames = _disk->loadTable("global");
startGui();
- while ((_engineFlags & kEngineQuit) == 0) {
+ while (!quit()) {
runGame();
}
@@ -242,7 +251,7 @@ void Parallaction_ns::switchBackground(const char* background, const char* mask)
v2 += 4;
}
- g_system->delayMillis(20);
+ _vm->_system->delayMillis(20);
_gfx->setPalette(pal);
_gfx->updateScreen();
}
@@ -253,16 +262,6 @@ void Parallaction_ns::switchBackground(const char* background, const char* mask)
}
-void Parallaction_ns::showSlide(const char *name, int x, int y) {
- BackgroundInfo *info = new BackgroundInfo;
- _disk->loadSlide(*info, name);
-
- info->x = (x == CENTER_LABEL_HORIZONTAL) ? ((_vm->_screenWidth - info->width) >> 1) : x;
- info->y = (y == CENTER_LABEL_VERTICAL) ? ((_vm->_screenHeight - info->height) >> 1) : y;
-
- _gfx->setBackground(kBackgroundSlide, info);
-}
-
void Parallaction_ns::runPendingZones() {
if (_activeZone) {
ZonePtr z = _activeZone; // speak Zone or sound
@@ -287,7 +286,7 @@ void Parallaction_ns::changeLocation(char *location) {
_zoneTrap = nullZonePtr;
- setArrowCursor();
+ _input->setArrowCursor();
_gfx->showGfxObj(_char._ani->gfxobj, false);
_location._animations.remove(_char._ani);
@@ -428,6 +427,7 @@ void Parallaction_ns::changeCharacter(const char *name) {
}
void Parallaction_ns::cleanupGame() {
+ _inTestResult = false;
_engineFlags &= ~kEngineTransformedDonna;
@@ -440,18 +440,22 @@ void Parallaction_ns::cleanupGame() {
memset(_locationNames, 0, sizeof(_locationNames));
// this flag tells freeZones to unconditionally remove *all* Zones
- _engineFlags |= kEngineQuit;
+ _vm->_quit = true;
freeZones();
freeAnimations();
// this dangerous flag can now be cleared
- _engineFlags &= ~kEngineQuit;
+ _vm->_quit = false;
// main character animation is restored
_location._animations.push_front(_char._ani);
_score = 0;
+ _soundMan->stopMusic();
+ _introSarcData3 = 200;
+ _introSarcData2 = 1;
+
return;
}
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index 8e30a631e4..a475f5701a 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -183,13 +183,12 @@ uint16 Script::readLineToken(bool errorOnEOF) {
clearTokens();
- bool inBlockComment = false, inLineComment;
+ bool inBlockComment = false;
char buf[200];
char *line = NULL;
+ char *start;
do {
- inLineComment = false;
-
line = readLine(buf, 200);
if (line == NULL) {
@@ -198,21 +197,27 @@ uint16 Script::readLineToken(bool errorOnEOF) {
else
return 0;
}
- line = Common::ltrim(line);
+ start = Common::ltrim(line);
- if (isCommentLine(line)) {
- inLineComment = true;
+ if (isCommentLine(start)) {
+ // ignore this line
+ start[0] = '\0';
} else
- if (isStartOfCommentBlock(line)) {
+ if (isStartOfCommentBlock(start)) {
+ // mark this and the following lines as comment
inBlockComment = true;
} else
- if (isEndOfCommentBlock(line)) {
+ if (isEndOfCommentBlock(start)) {
+ // comment is finished, so stop ignoring
inBlockComment = false;
+ // the current line must be skipped, though,
+ // as it contains the end-of-comment marker
+ start[0] = '\0';
}
- } while (inLineComment || inBlockComment || strlen(line) == 0);
+ } while (inBlockComment || strlen(start) == 0);
- return fillTokens(line);
+ return fillTokens(start);
}
@@ -403,7 +408,9 @@ void PreProcessor::preprocessScript(Script &script, StatementList &list) {
break;
StatementDef *def = findDef(_tokens[0]);
- assert(def);
+ if (!def) {
+ error("PreProcessor::preprocessScript: unknown statement '%s' found\n", _tokens[0]);
+ }
text = def->makeLine(script);
int score = getDefScore(def);
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index e622bfd81f..f0cc448518 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -27,6 +27,7 @@
#define PARALLACTION_PARSER_H
#include "common/stream.h"
+#include "common/stack.h"
#include "parallaction/objects.h"
#include "parallaction/walk.h"
@@ -455,7 +456,7 @@ public:
}
bool eos() const {
- return _pos == _size;
+ return _pos == _size; // FIXME (eos definition change)
}
};
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index 20800abc33..4b11c5caa4 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -497,7 +497,7 @@ DECLARE_LOCATION_PARSER(zeta) {
_vm->_location._zeta1 = atoi(_tokens[2]);
if (_tokens[3][0] != '\0') {
- _vm->_location._zeta2 = atoi(_tokens[1]);
+ _vm->_location._zeta2 = atoi(_tokens[3]);
} else {
_vm->_location._zeta2 = 50;
}
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 44613c970c..9a787d7f00 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -31,6 +31,7 @@
#include "gui/message.h"
#include "parallaction/parallaction.h"
+#include "parallaction/saveload.h"
#include "parallaction/sound.h"
@@ -57,12 +58,11 @@ protected:
GUI::StaticTextWidget *_time;
GUI::StaticTextWidget *_playtime;
GUI::ContainerWidget *_container;
- Parallaction_ns *_vm;
uint8 _fillR, _fillG, _fillB;
public:
- SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine);
+ SaveLoadChooser(const String &title, const String &buttonLabel);
~SaveLoadChooser();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
@@ -73,34 +73,39 @@ public:
virtual void reflowLayout();
};
-Common::String Parallaction_ns::genSaveFileName(uint slot, bool oldStyle) {
+Common::String SaveLoad_ns::genOldSaveFileName(uint slot) {
assert(slot < NUM_SAVESLOTS || slot == SPECIAL_SAVESLOT);
char s[20];
- sprintf(s, (oldStyle ? "game.%i" : "nippon.%.3d"), slot );
+ sprintf(s, "game.%i", slot);
return Common::String(s);
}
-Common::InSaveFile *Parallaction_ns::getInSaveFile(uint slot) {
+
+Common::String SaveLoad::genSaveFileName(uint slot) {
+ assert(slot < NUM_SAVESLOTS || slot == SPECIAL_SAVESLOT);
+
+ char s[20];
+ sprintf(s, "%s.%.3d", _saveFilePrefix.c_str(), slot);
+
+ return Common::String(s);
+}
+
+Common::InSaveFile *SaveLoad::getInSaveFile(uint slot) {
Common::String name = genSaveFileName(slot);
return _saveFileMan->openForLoading(name.c_str());
}
-Common::OutSaveFile *Parallaction_ns::getOutSaveFile(uint slot) {
+Common::OutSaveFile *SaveLoad::getOutSaveFile(uint slot) {
Common::String name = genSaveFileName(slot);
return _saveFileMan->openForSaving(name.c_str());
}
-void Parallaction_ns::doLoadGame(uint16 slot) {
-
- _soundMan->stopMusic();
+void SaveLoad_ns::doLoadGame(uint16 slot) {
- cleanupGame();
-
- _introSarcData3 = 200;
- _introSarcData2 = 1;
+ _vm->cleanupGame();
Common::InSaveFile *f = getInSaveFile(slot);
if (!f) return;
@@ -109,77 +114,77 @@ void Parallaction_ns::doLoadGame(uint16 slot) {
char n[16];
char l[16];
- f->readLine(s, 199);
+ f->readLine_OLD(s, 199);
- f->readLine(n, 15);
+ f->readLine_OLD(n, 15);
- f->readLine(l, 15);
+ f->readLine_OLD(l, 15);
- f->readLine(s, 15);
- _location._startPosition.x = atoi(s);
+ f->readLine_OLD(s, 15);
+ _vm->_location._startPosition.x = atoi(s);
- f->readLine(s, 15);
- _location._startPosition.y = atoi(s);
+ f->readLine_OLD(s, 15);
+ _vm->_location._startPosition.y = atoi(s);
- f->readLine(s, 15);
+ f->readLine_OLD(s, 15);
_score = atoi(s);
- f->readLine(s, 15);
+ f->readLine_OLD(s, 15);
_globalFlags = atoi(s);
- f->readLine(s, 15);
+ f->readLine_OLD(s, 15);
// TODO (LIST): unify (and parametrize) calls to freeZones.
// We aren't calling freeAnimations because it is not needed, since
// kChangeLocation will trigger a complete deletion. Anyway, we still
- // need to invoke freeZones here with kEngineQuit set, because the
+ // need to invoke freeZones here with _quit set, because the
// call in changeLocation preserve certain zones.
- _engineFlags |= kEngineQuit;
- freeZones();
- _engineFlags &= ~kEngineQuit;
+ _vm->_quit = true;
+ _vm->freeZones();
+ _vm->_quit = false;
- _numLocations = atoi(s);
+ _vm->_numLocations = atoi(s);
uint16 _si;
- for (_si = 0; _si < _numLocations; _si++) {
- f->readLine(s, 20);
+ for (_si = 0; _si < _vm->_numLocations; _si++) {
+ f->readLine_OLD(s, 20);
s[strlen(s)] = '\0';
- strcpy(_locationNames[_si], s);
+ strcpy(_vm->_locationNames[_si], s);
- f->readLine(s, 15);
- _localFlags[_si] = atoi(s);
+ f->readLine_OLD(s, 15);
+ _vm->_localFlags[_si] = atoi(s);
}
- cleanInventory(false);
+ _vm->cleanInventory(false);
ItemName name;
uint32 value;
for (_si = 0; _si < 30; _si++) {
- f->readLine(s, 15);
+ f->readLine_OLD(s, 15);
value = atoi(s);
- f->readLine(s, 15);
+ f->readLine_OLD(s, 15);
name = atoi(s);
- addInventoryItem(name, value);
+ _vm->addInventoryItem(name, value);
}
delete f;
// force reload of character to solve inventory
// bugs, but it's a good maneuver anyway
- strcpy(_characterName1, "null");
+ strcpy(_vm->_characterName1, "null");
char tmp[PATH_LEN];
sprintf(tmp, "%s.%s" , l, n);
- scheduleLocationSwitch(tmp);
+ _vm->scheduleLocationSwitch(tmp);
return;
}
-void Parallaction_ns::doSaveGame(uint16 slot, const char* name) {
+void SaveLoad_ns::doSaveGame(uint16 slot, const char* name) {
Common::OutSaveFile *f = getOutSaveFile(slot);
if (f == 0) {
@@ -202,30 +207,30 @@ void Parallaction_ns::doSaveGame(uint16 slot, const char* name) {
f->writeString(s);
f->writeString("\n");
- sprintf(s, "%s\n", _char.getFullName());
+ sprintf(s, "%s\n", _vm->_char.getFullName());
f->writeString(s);
sprintf(s, "%s\n", _saveData1);
f->writeString(s);
- sprintf(s, "%d\n", _char._ani->getX());
+ sprintf(s, "%d\n", _vm->_char._ani->getX());
f->writeString(s);
- sprintf(s, "%d\n", _char._ani->getY());
+ sprintf(s, "%d\n", _vm->_char._ani->getY());
f->writeString(s);
sprintf(s, "%d\n", _score);
f->writeString(s);
sprintf(s, "%u\n", _globalFlags);
f->writeString(s);
- sprintf(s, "%d\n", _numLocations);
+ sprintf(s, "%d\n", _vm->_numLocations);
f->writeString(s);
- for (uint16 _si = 0; _si < _numLocations; _si++) {
- sprintf(s, "%s\n%u\n", _locationNames[_si], _localFlags[_si]);
+ for (uint16 _si = 0; _si < _vm->_numLocations; _si++) {
+ sprintf(s, "%s\n%u\n", _vm->_locationNames[_si], _vm->_localFlags[_si]);
f->writeString(s);
}
const InventoryItem *item;
for (uint16 _si = 0; _si < 30; _si++) {
- item = getInventoryItem(_si);
+ item = _vm->getInventoryItem(_si);
sprintf(s, "%u\n%d\n", item->_id, item->_index);
f->writeString(s);
}
@@ -247,8 +252,9 @@ enum {
};
-SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine)
- : Dialog("ScummSaveLoad"), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) {
+
+SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel)
+ : Dialog("ScummSaveLoad"), _list(0), _chooseButton(0), _gfxWidget(0) {
// _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR;
_backgroundType = GUI::Theme::kDialogBackgroundSpecial;
@@ -335,7 +341,7 @@ void SaveLoadChooser::reflowLayout() {
Dialog::reflowLayout();
}
-int Parallaction_ns::buildSaveFileList(Common::StringList& l) {
+int SaveLoad_ns::buildSaveFileList(Common::StringList& l) {
char buf[200];
@@ -346,7 +352,7 @@ int Parallaction_ns::buildSaveFileList(Common::StringList& l) {
Common::InSaveFile *f = getInSaveFile(i);
if (f) {
- f->readLine(buf, 199);
+ f->readLine_OLD(buf, 199);
delete f;
count++;
@@ -359,9 +365,9 @@ int Parallaction_ns::buildSaveFileList(Common::StringList& l) {
}
-int Parallaction_ns::selectSaveFile(uint16 arg_0, const char* caption, const char* button) {
+int SaveLoad_ns::selectSaveFile(uint16 arg_0, const char* caption, const char* button) {
- SaveLoadChooser* slc = new SaveLoadChooser(caption, button, this);
+ SaveLoadChooser* slc = new SaveLoadChooser(caption, button);
Common::StringList l;
@@ -380,7 +386,7 @@ int Parallaction_ns::selectSaveFile(uint16 arg_0, const char* caption, const cha
-bool Parallaction_ns::loadGame() {
+bool SaveLoad_ns::loadGame() {
int _di = selectSaveFile( 0, "Load file", "Load" );
if (_di == -1) {
@@ -392,15 +398,15 @@ bool Parallaction_ns::loadGame() {
GUI::TimedMessageDialog dialog("Loading game...", 1500);
dialog.runModal();
- setArrowCursor();
+ _vm->_input->setArrowCursor();
return true;
}
-bool Parallaction_ns::saveGame() {
+bool SaveLoad_ns::saveGame() {
- if (!scumm_stricmp(_location._name, "caveau")) {
+ if (!scumm_stricmp(_vm->_location._name, "caveau")) {
return false;
}
@@ -418,7 +424,7 @@ bool Parallaction_ns::saveGame() {
}
-void Parallaction_ns::setPartComplete(const Character& character) {
+void SaveLoad_ns::setPartComplete(const char *part) {
char buf[30];
bool alreadyPresent = false;
@@ -426,10 +432,10 @@ void Parallaction_ns::setPartComplete(const Character& character) {
Common::InSaveFile *inFile = getInSaveFile(SPECIAL_SAVESLOT);
if (inFile) {
- inFile->readLine(buf, 29);
+ inFile->readLine_OLD(buf, 29);
delete inFile;
- if (strstr(buf, character.getBaseName())) {
+ if (strstr(buf, part)) {
alreadyPresent = true;
}
}
@@ -437,7 +443,7 @@ void Parallaction_ns::setPartComplete(const Character& character) {
if (!alreadyPresent) {
Common::OutSaveFile *outFile = getOutSaveFile(SPECIAL_SAVESLOT);
outFile->writeString(buf);
- outFile->writeString(character.getBaseName());
+ outFile->writeString(part);
outFile->finalize();
delete outFile;
}
@@ -445,17 +451,20 @@ void Parallaction_ns::setPartComplete(const Character& character) {
return;
}
-bool Parallaction_ns::allPartsComplete() {
- char buf[30];
+void SaveLoad_ns::getGamePartProgress(bool *complete, int size) {
+ assert(complete && size >= 3);
+ char buf[30];
Common::InSaveFile *inFile = getInSaveFile(SPECIAL_SAVESLOT);
- inFile->readLine(buf, 29);
+ inFile->readLine_OLD(buf, 29);
delete inFile;
- return strstr(buf, "dino") && strstr(buf, "donna") && strstr(buf, "dough");
+ complete[0] = strstr(buf, "dino");
+ complete[1] = strstr(buf, "donna");
+ complete[2] = strstr(buf, "dough");
}
-void Parallaction_ns::renameOldSavefiles() {
+void SaveLoad_ns::renameOldSavefiles() {
bool exists[NUM_SAVESLOTS];
uint num = 0;
@@ -463,7 +472,7 @@ void Parallaction_ns::renameOldSavefiles() {
for (i = 0; i < NUM_SAVESLOTS; i++) {
exists[i] = false;
- Common::String name = genSaveFileName(i, true);
+ Common::String name = genOldSaveFileName(i);
Common::InSaveFile *f = _saveFileMan->openForLoading(name.c_str());
if (f) {
exists[i] = true;
@@ -491,8 +500,8 @@ void Parallaction_ns::renameOldSavefiles() {
uint success = 0;
for (i = 0; i < NUM_SAVESLOTS; i++) {
if (exists[i]) {
- Common::String oldName = genSaveFileName(i, true);
- Common::String newName = genSaveFileName(i, false);
+ Common::String oldName = genOldSaveFileName(i);
+ Common::String newName = genSaveFileName(i);
if (_saveFileMan->renameSavefile(oldName.c_str(), newName.c_str())) {
success++;
} else {
@@ -518,4 +527,28 @@ void Parallaction_ns::renameOldSavefiles() {
}
+bool SaveLoad_br::loadGame() {
+ // TODO: implement loadgame
+ return false;
+}
+
+bool SaveLoad_br::saveGame() {
+ // TODO: implement savegame
+ return false;
+}
+
+void SaveLoad_br::getGamePartProgress(bool *complete, int size) {
+ assert(complete && size >= 3);
+
+ // TODO: implement progress loading
+
+ complete[0] = true;
+ complete[1] = true;
+ complete[2] = true;
+}
+
+void SaveLoad_br::setPartComplete(const char *part) {
+ // TODO: implement progress saving
+}
+
} // namespace Parallaction
diff --git a/engines/parallaction/saveload.h b/engines/parallaction/saveload.h
new file mode 100644
index 0000000000..10bb8aafc2
--- /dev/null
+++ b/engines/parallaction/saveload.h
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PARALLACTION_SAVELOAD_H
+#define PARALLACTION_SAVELOAD_H
+
+namespace Parallaction {
+
+struct Character;
+
+
+class SaveLoad {
+
+protected:
+ Common::SaveFileManager *_saveFileMan;
+ Common::String _saveFilePrefix;
+
+ Common::String genSaveFileName(uint slot);
+ Common::InSaveFile *getInSaveFile(uint slot);
+ Common::OutSaveFile *getOutSaveFile(uint slot);
+
+public:
+ SaveLoad(Common::SaveFileManager* saveFileMan, const char *prefix) : _saveFileMan(saveFileMan), _saveFilePrefix(prefix) { }
+ virtual ~SaveLoad() { }
+
+ virtual bool loadGame() = 0;
+ virtual bool saveGame() = 0;
+ virtual void getGamePartProgress(bool *complete, int size) = 0;
+ virtual void setPartComplete(const char *part) = 0;
+
+ virtual void renameOldSavefiles() { }
+};
+
+class SaveLoad_ns : public SaveLoad {
+
+ Parallaction_ns *_vm;
+
+ Common::String _saveFileName;
+ Common::String genOldSaveFileName(uint slot);
+
+protected:
+ void renameOldSavefiles();
+ void doLoadGame(uint16 slot);
+ void doSaveGame(uint16 slot, const char* name);
+ int buildSaveFileList(Common::StringList& l);
+ int selectSaveFile(uint16 arg_0, const char* caption, const char* button);
+
+public:
+ SaveLoad_ns(Parallaction_ns *vm, Common::SaveFileManager *saveFileMan) : SaveLoad(saveFileMan, "nippon"), _vm(vm) { }
+
+ virtual bool loadGame();
+ virtual bool saveGame();
+ virtual void getGamePartProgress(bool *complete, int size);
+ virtual void setPartComplete(const char *part);
+};
+
+class SaveLoad_br : public SaveLoad {
+
+ Parallaction_br *_vm;
+
+public:
+ SaveLoad_br(Parallaction_br *vm, Common::SaveFileManager *saveFileMan) : SaveLoad(saveFileMan, "bra"), _vm(vm) { }
+
+ virtual bool loadGame();
+ virtual bool saveGame();
+ virtual void getGamePartProgress(bool *complete, int size);
+ virtual void setPartComplete(const char *part);
+};
+
+
+} // namespace Parallaction
+
+#endif
diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp
index 2c5cf281dd..071495e8f1 100644
--- a/engines/parallaction/staticres.cpp
+++ b/engines/parallaction/staticres.cpp
@@ -29,7 +29,7 @@
namespace Parallaction {
-byte Parallaction_ns::_resMouseArrow[256] = {
+byte Input::_resMouseArrow_NS[256] = {
0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00,
0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00,
0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00,
@@ -335,12 +335,6 @@ const Parallaction_br::Callable Parallaction_br::_dosCallables[] = {
void Parallaction_ns::initResources() {
-// _zoneFlagNamesRes = _zoneFlagNamesRes_ns;
-// _zoneTypeNamesRes = _zoneTypeNamesRes_ns;
-// _commandsNamesRes = _commandsNamesRes_ns;
- _callableNamesRes = _callableNamesRes_ns;
-// _instructionNamesRes = _instructionNamesRes_ns;
-
_callableNames = new Table(ARRAYSIZE(_callableNamesRes_ns), _callableNamesRes_ns);
_localFlagNames = new FixedTable(NUM_LOCATIONS, 1);
@@ -356,13 +350,6 @@ void Parallaction_ns::initResources() {
void Parallaction_br::initResources() {
-// _zoneFlagNamesRes = _zoneFlagNamesRes_br;
-// _zoneTypeNamesRes = _zoneTypeNamesRes_br;
-// _commandsNamesRes = _commandsNamesRes_br;
- _callableNamesRes = _callableNamesRes_br;
-// _instructionNamesRes = _instructionNamesRes_br;
-// _audioCommandsNamesRes = _audioCommandsNamesRes_br;
-
_callableNames = new Table(ARRAYSIZE(_callableNamesRes_br), _callableNamesRes_br);
_localFlagNames = new FixedTable(NUM_LOCATIONS, 2);
diff --git a/engines/queen/input.cpp b/engines/queen/input.cpp
index 9f03c341c9..84e21fbcaa 100644
--- a/engines/queen/input.cpp
+++ b/engines/queen/input.cpp
@@ -118,9 +118,10 @@ void Input::delay(uint amount) {
case Common::EVENT_RBUTTONDOWN:
_mouseButton |= MOUSE_RBUTTON;
break;
-
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->quitGame();
+ if (_cutawayRunning)
+ _cutawayQuit = true;
return;
default:
diff --git a/engines/queen/journal.cpp b/engines/queen/journal.cpp
index 0327fb74b8..7846fa5c36 100644
--- a/engines/queen/journal.cpp
+++ b/engines/queen/journal.cpp
@@ -84,8 +84,8 @@ void Journal::use() {
case Common::EVENT_WHEELDOWN:
handleMouseWheel(1);
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->quitGame();
return;
default:
break;
@@ -385,16 +385,18 @@ void Journal::drawPanelText(int y, const char *text) {
char s[128];
strncpy(s, text, 127);
s[127] = 0;
+ char *p;
+
// remove leading and trailing spaces (necessary for spanish version)
- for (char *p = s + strlen(s) - 1; p >= s && *p == ' '; --p) {
+ for (p = s + strlen(s) - 1; p >= s && *p == ' '; --p) {
*p = 0;
}
text = s;
- for (char *p = s; *p == ' '; ++p) {
+ for (p = s; *p == ' '; ++p) {
text = p + 1;
}
// draw the substrings
- char *p = (char *)strchr(text, ' ');
+ p = (char *)strchr(text, ' ');
if (!p) {
int x = (128 - _vm->display()->textWidth(text)) / 2;
_vm->display()->setText(x, y, text, false);
diff --git a/engines/queen/logic.cpp b/engines/queen/logic.cpp
index 9e4770553c..7fcc761018 100644
--- a/engines/queen/logic.cpp
+++ b/engines/queen/logic.cpp
@@ -2076,6 +2076,8 @@ bool LogicDemo::changeToSpecialRoom() {
displayRoom(currentRoom(), RDM_FADE_NOJOE, 100, 2, true);
playCutaway("CLOGO.CUT");
sceneReset();
+ if (_vm->quit())
+ return true;
currentRoom(ROOM_HOTEL_LOBBY);
entryObj(584);
displayRoom(currentRoom(), RDM_FADE_JOE, 100, 2, true);
@@ -2129,7 +2131,11 @@ bool LogicGame::changeToSpecialRoom() {
} else if (currentRoom() == FOTAQ_LOGO && gameState(VAR_INTRO_PLAYED) == 0) {
displayRoom(currentRoom(), RDM_FADE_NOJOE, 100, 2, true);
playCutaway("COPY.CUT");
+ if (_vm->quit())
+ return true;
playCutaway("CLOGO.CUT");
+ if (_vm->quit())
+ return true;
if (_vm->resource()->getPlatform() != Common::kPlatformAmiga) {
if (ConfMan.getBool("alt_intro") && _vm->resource()->isCD()) {
playCutaway("CINTR.CUT");
@@ -2137,7 +2143,11 @@ bool LogicGame::changeToSpecialRoom() {
playCutaway("CDINT.CUT");
}
}
+ if (_vm->quit())
+ return true;
playCutaway("CRED.CUT");
+ if (_vm->quit())
+ return true;
_vm->display()->palSetPanel();
sceneReset();
currentRoom(ROOM_HOTEL_LOBBY);
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index 155bb66716..200c7282f9 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -132,7 +132,7 @@ int AdlibMidiDriver::open() {
adlibSetNoteVolume(i, 0);
adlibTurnNoteOff(i);
}
- _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
return 0;
}
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index c95e44b477..6cdd020b8f 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -60,9 +60,12 @@ public:
virtual const char *getName() const;
virtual const char *getCopyright() const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual GameList getSupportedGames() const;
virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const FSList &fslist) const;
+ virtual GameList detectGames(const Common::FSList &fslist) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
virtual PluginError createInstance(OSystem *syst, Engine **engine) const;
};
@@ -75,6 +78,14 @@ const char *QueenMetaEngine::getCopyright() const {
return "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis";
}
+bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
GameList QueenMetaEngine::getSupportedGames() const {
GameList games;
games.push_back(queenGameDescriptor);
@@ -88,11 +99,11 @@ GameDescriptor QueenMetaEngine::findGame(const char *gameid) const {
return GameDescriptor();
}
-GameList QueenMetaEngine::detectGames(const FSList &fslist) const {
+GameList QueenMetaEngine::detectGames(const Common::FSList &fslist) const {
GameList detectedGames;
// Iterate over all files in the given directory
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (file->isDirectory()) {
continue;
}
@@ -121,6 +132,46 @@ GameList QueenMetaEngine::detectGames(const FSList &fslist) const {
return detectedGames;
}
+SaveStateList QueenMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ char saveDesc[32];
+ Common::String pattern = target;
+ pattern += ".s??";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 2 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 2);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ for (int i = 0; i < 4; i++)
+ in->readUint32BE();
+ in->read(saveDesc, 32);
+ saveList.push_back(SaveStateDescriptor(slotNum, Common::String(saveDesc), *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void QueenMetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".s%02d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
PluginError QueenMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(engine);
*engine = new Queen::QueenEngine(syst);
@@ -180,6 +231,10 @@ void QueenEngine::checkOptionSettings() {
}
}
+void QueenEngine::syncSoundSettings() {
+ readOptionSettings();
+}
+
void QueenEngine::readOptionSettings() {
_sound->setVolume(ConfMan.getInt("music_volume"));
_sound->musicToggle(!ConfMan.getBool("music_mute"));
@@ -381,8 +436,8 @@ int QueenEngine::go() {
loadGameState(ConfMan.getInt("save_slot"));
}
_lastSaveTime = _lastUpdateTime = _system->getMillis();
- _quit = false;
- while (!_quit) {
+
+ while (!quit()) {
if (_logic->newRoom() > 0) {
_logic->update();
_logic->oldRoom(_logic->currentRoom());
@@ -428,10 +483,6 @@ int QueenEngine::init() {
_logic = new LogicGame(this);
}
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- // Set mixer music volume to maximum, since music volume is regulated by MusicPlayer's MIDI messages
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
-
_sound = Sound::makeSoundInstance(_mixer, this, _resource->getCompression());
_walk = new Walk(this);
//_talkspeedScale = (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 255.0;
diff --git a/engines/queen/queen.h b/engines/queen/queen.h
index 1eea43e882..66931e037d 100644
--- a/engines/queen/queen.h
+++ b/engines/queen/queen.h
@@ -97,13 +97,13 @@ public:
void checkOptionSettings();
void readOptionSettings();
void writeOptionSettings();
+ virtual void syncSoundSettings();
int talkSpeed() const { return _talkSpeed; }
void talkSpeed(int speed) { _talkSpeed = speed; }
bool subtitles() const { return _subtitles; }
void subtitles(bool enable) { _subtitles = enable; }
- void quitGame() { _quit = true; }
-
+
void update(bool checkPlayerInput = false);
bool canLoadOrSave() const;
@@ -137,7 +137,6 @@ protected:
int _talkSpeed;
bool _subtitles;
- bool _quit;
uint32 _lastSaveTime;
uint32 _lastUpdateTime;
diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp
index b3bd663baf..38d841e96a 100644
--- a/engines/queen/resource.cpp
+++ b/engines/queen/resource.cpp
@@ -132,7 +132,7 @@ void Resource::loadTextFile(const char *filename, Common::StringList &stringList
seekResourceFile(re->bundle, re->offset);
char buf[512];
Common::SeekableSubReadStream stream(&_resourceFile, re->offset, re->offset + re->size);
- while (stream.readLine(buf, 512)) {
+ while (stream.readLine_OLD(buf, 512)) {
stringList.push_back(buf);
}
}
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index 27cf1bf6a2..ccaac8227d 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -54,10 +54,27 @@ namespace Queen {
class AudioStreamWrapper : public Audio::AudioStream {
protected:
Audio::AudioStream *_stream;
+ int _rate;
public:
AudioStreamWrapper(Audio::AudioStream *stream) {
_stream = stream;
+
+ int rate = _stream->getRate();
+
+ // A file where the sample rate claims to be 11025 Hz is
+ // probably compressed with the old tool. We force the real
+ // sample rate, which is 11840 Hz.
+ //
+ // However, a file compressed with the newer tool is not
+ // guaranteed to have a sample rate of 11840 Hz. LAME will
+ // automatically resample it to 12000 Hz. So in all other
+ // cases, we use the rate from the file.
+
+ if (rate == 11025)
+ _rate = 11840;
+ else
+ _rate = rate;
}
~AudioStreamWrapper() {
delete _stream;
@@ -75,7 +92,7 @@ public:
return _stream->endOfStream();
}
int getRate() const {
- return 11840;
+ return _rate;
}
int32 getTotalPlayTime() {
return _stream->getTotalPlayTime();
@@ -261,8 +278,6 @@ void PCSound::playSpeech(const char *base) {
void PCSound::setVolume(int vol) {
Sound::setVolume(vol);
- // Set mixer music volume to maximum, since music volume is regulated by MusicPlayer's MIDI messages
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
_music->setVolume(vol);
}
@@ -316,7 +331,8 @@ void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *so
if (sound) {
f->read(sound, size);
byte flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE;
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, soundHandle, sound, size, 11840, flags);
+ Audio::Mixer::SoundType type = (soundHandle == &_speechHandle) ? Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType;
+ _mixer->playRaw(type, soundHandle, sound, size, 11840, flags);
}
}
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp
index ff18ef37d1..fa2ca669cd 100644
--- a/engines/queen/talk.cpp
+++ b/engines/queen/talk.cpp
@@ -807,7 +807,7 @@ void Talk::speakSegment(
switch (command) {
case SPEAK_PAUSE:
- for (i = 0; i < 10 && !_vm->input()->talkQuit(); i++) {
+ for (i = 0; i < 10 && !_vm->input()->talkQuit() && !_vm->quit(); i++) {
_vm->update();
}
return;
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index 9fffb0f8bf..e9e146013f 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -866,7 +866,7 @@ int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) {
readS._bigEndian = !_vm->isBigEndian(); // RLE has inversion BE<>LE
- while (!readS.eos()) {
+ while (readS.pos() != readS.size()) {
if (reallyFill) {
anim->frameOffsets[currentFrame] = readS.pos();
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 9c897d8ebc..a31e9b755a 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -147,9 +147,20 @@ public:
return "Inherit the Earth (C) Wyrmkeep Entertainment";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
};
+bool SagaMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
bool SagaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Saga::SAGAGameDescription *gd = (const Saga::SAGAGameDescription *)desc;
if (gd) {
@@ -158,6 +169,46 @@ bool SagaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
+SaveStateList SagaMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ char saveDesc[SAVE_TITLE_SIZE];
+ Common::String pattern = target;
+ pattern += ".s??";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 2 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 2);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ for (int i = 0; i < 3; i++)
+ in->readUint32BE();
+ in->read(saveDesc, SAVE_TITLE_SIZE);
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void SagaMetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".s%02d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
#if PLUGIN_ENABLED_DYNAMIC(SAGA)
REGISTER_PLUGIN_DYNAMIC(SAGA, PLUGIN_TYPE_ENGINE, SagaMetaEngine);
#else
diff --git a/engines/saga/input.cpp b/engines/saga/input.cpp
index ac80d87dd0..61b729b701 100644
--- a/engines/saga/input.cpp
+++ b/engines/saga/input.cpp
@@ -141,9 +141,6 @@ int SagaEngine::processInput() {
break;
case Common::EVENT_MOUSEMOVE:
break;
- case Common::EVENT_QUIT:
- shutDown();
- break;
default:
break;
}
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 256e231f57..abf8094533 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -688,7 +688,7 @@ bool Interface::processAscii(Common::KeyState keystate) {
setMode(kPanelMain);
_vm->_script->setNoPendingVerb();
} else if (ascii == 'q' || ascii == 'Q') {
- _vm->shutDown();
+ _vm->quitGame();
}
break;
case kPanelBoss:
@@ -1084,7 +1084,7 @@ void Interface::setQuit(PanelButton *panelButton) {
if (_vm->getGameId() == GID_IHNM_DEMO)
_vm->_scene->creditsScene(); // display sales info for IHNM demo
else
- _vm->shutDown();
+ _vm->quitGame();
break;
}
}
@@ -1153,6 +1153,7 @@ void Interface::setLoad(PanelButton *panelButton) {
debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
setMode(kPanelMain);
_vm->load(_vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber));
+ _vm->syncSoundSettings();
}
}
}
@@ -1616,6 +1617,7 @@ void Interface::setOption(PanelButton *panelButton) {
debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
setMode(kPanelMain);
_vm->load(_vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber));
+ _vm->syncSoundSettings();
}
}
} else {
@@ -1644,14 +1646,16 @@ void Interface::setOption(PanelButton *panelButton) {
}
break;
case kTextMusic:
- _vm->_musicVolume = (_vm->_musicVolume + 1) % 11;
- _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
- ConfMan.setInt("music_volume", _vm->_musicVolume * 25);
+ _vm->_musicVolume = _vm->_musicVolume + 25;
+ if (_vm->_musicVolume > 255) _vm->_musicVolume = 0;
+ _vm->_music->setVolume(_vm->_musicVolume, 1);
+ ConfMan.setInt("music_volume", _vm->_musicVolume);
break;
case kTextSound:
- _vm->_soundVolume = (_vm->_soundVolume + 1) % 11;
- _vm->_sound->setVolume(_vm->_soundVolume == 10 ? 255 : _vm->_soundVolume * 25);
- ConfMan.setInt("sfx_volume", _vm->_soundVolume * 25);
+ _vm->_soundVolume = _vm->_soundVolume + 25;
+ if (_vm->_soundVolume > 255) _vm->_soundVolume = 0;
+ ConfMan.setInt("sound_volume", _vm->_soundVolume);
+ _vm->_sound->setVolume();
break;
case kTextVoices:
if (_vm->_voiceFilesExist) {
@@ -1669,6 +1673,11 @@ void Interface::setOption(PanelButton *panelButton) {
_vm->_subtitlesEnabled = true; // Set it to "Text"
_vm->_voicesEnabled = false;
}
+
+ _vm->_speechVolume = _vm->_speechVolume + 25;
+ if (_vm->_speechVolume > 255) _vm->_speechVolume = 0;
+ ConfMan.setInt("speech_volume", _vm->_speechVolume);
+ _vm->_sound->setVolume();
ConfMan.setBool("subtitles", _vm->_subtitlesEnabled);
ConfMan.setBool("voices", _vm->_voicesEnabled);
@@ -2269,13 +2278,13 @@ void Interface::drawPanelButtonText(Surface *ds, InterfacePanel *panel, PanelBut
break;
case kTextMusic:
if (_vm->_musicVolume)
- textId = kText10Percent + _vm->_musicVolume - 1;
+ textId = kText10Percent + _vm->_musicVolume / 25 - 1;
else
textId = kTextOff;
break;
case kTextSound:
if (_vm->_soundVolume)
- textId = kText10Percent + _vm->_soundVolume - 1;
+ textId = kText10Percent + _vm->_soundVolume / 25 - 1;
else
textId = kTextOff;
break;
diff --git a/engines/saga/introproc_ihnm.cpp b/engines/saga/introproc_ihnm.cpp
index 6614f4098f..aaa428ca53 100644
--- a/engines/saga/introproc_ihnm.cpp
+++ b/engines/saga/introproc_ihnm.cpp
@@ -59,8 +59,12 @@ int Scene::IHNMStartProc() {
// Play Cyberdreams logo for 168 frames
if (!playTitle(0, logoLength, true)) {
+ if (_vm->quit())
+ return !SUCCESS;
// Play Dreamers Guild logo for 10 seconds
if (!playLoopingTitle(1, 10)) {
+ if (_vm->quit())
+ return !SUCCESS;
// Play the title music
_vm->_music->play(1, MUSIC_NORMAL);
// Play title screen
@@ -70,6 +74,8 @@ int Scene::IHNMStartProc() {
} else {
_vm->_music->play(1, MUSIC_NORMAL);
playTitle(0, 10);
+ if (_vm->quit())
+ return !SUCCESS;
playTitle(2, 12);
}
@@ -142,9 +148,9 @@ bool Scene::checkKey() {
while (_vm->_eventMan->pollEvent(event)) {
switch (event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
res = true;
- _vm->shutDown();
break;
case Common::EVENT_KEYDOWN:
// Don't react to modifier keys alone. The original did
@@ -187,7 +193,7 @@ bool Scene::playTitle(int title, int time, int mode) {
_vm->_gfx->getCurrentPal(pal_cut);
- while (!done) {
+ while (!done && !_vm->quit()) {
curTime = _vm->_system->getMillis();
switch (phase) {
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 732bd0b50c..5bf0c0ec03 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -249,6 +249,8 @@ void MusicPlayer::setVolume(int volume) {
_masterVolume = volume;
+ Common::StackLock lock(_mutex);
+
for (int i = 0; i < 16; ++i) {
if (_channel[i]) {
_channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
@@ -346,7 +348,7 @@ void MusicPlayer::stopMusic() {
}
}
-Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enabled) : _vm(vm), _mixer(mixer), _enabled(enabled), _adlib(false) {
+Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), _mixer(mixer), _adlib(false) {
_player = new MusicPlayer(driver);
_currentVolume = 0;
@@ -402,7 +404,7 @@ void Music::musicVolumeGauge() {
}
void Music::setVolume(int volume, int time) {
- _targetVolume = volume * 2; // ScummVM has different volume scale
+ _targetVolume = volume;
_currentVolumePercent = 0;
if (volume == -1) // Set Full volume
@@ -432,11 +434,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
uint32 loopStart;
debug(2, "Music::play %d, %d", resourceId, flags);
-
- if (!_enabled) {
- return;
- }
-
+
if (isPlaying() && _trackNumber == resourceId) {
return;
}
@@ -444,11 +442,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_trackNumber = resourceId;
_player->stopMusic();
_mixer->stopHandle(_musicHandle);
-
- if (!_vm->_musicVolume) {
- return;
- }
-
+
int realTrackNumber;
if (_vm->getGameType() == GType_ITE) {
@@ -591,7 +585,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_player->_parser = parser;
- setVolume(_vm->_musicVolume == 10 ? 255 : _vm->_musicVolume * 25);
+ setVolume(_vm->_musicVolume);
if (flags & MUSIC_LOOP)
_player->setLoop(true);
@@ -609,7 +603,7 @@ void Music::pause(void) {
}
void Music::resume(void) {
- _player->setVolume(_vm->_musicVolume == 10 ? 255 : _vm->_musicVolume * 25);
+ _player->setVolume(_vm->_musicVolume);
_player->setPlaying(true);
}
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 1953dc6f91..57ff9e0671 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -105,7 +105,7 @@ protected:
class Music {
public:
- Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enabled);
+ Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver);
~Music(void);
void setNativeMT32(bool b) { _player->setNativeMT32(b); }
bool hasNativeMT32() { return _player->hasNativeMT32(); }
@@ -133,7 +133,6 @@ private:
Audio::SoundHandle _musicHandle;
uint32 _trackNumber;
- int _enabled;
bool _adlib;
int _targetVolume;
diff --git a/engines/saga/rscfile.cpp b/engines/saga/rscfile.cpp
index e150caeca5..05b1162973 100644
--- a/engines/saga/rscfile.cpp
+++ b/engines/saga/rscfile.cpp
@@ -121,7 +121,7 @@ bool Resource::loadSagaContext(ResourceContext *context, uint32 contextOffset, u
resourceData->offset = contextOffset + readS1.readUint32();
resourceData->size = readS1.readUint32();
//sanity check
- if ((resourceData->offset > context->file->size()) || (resourceData->size > contextSize)) {
+ if ((resourceData->offset > (uint)context->file->size()) || (resourceData->size > contextSize)) {
result = false;
break;
}
@@ -181,8 +181,8 @@ bool Resource::loadMacContext(ResourceContext *context) {
macDataLength = context->file->readUint32BE();
macMapLength = context->file->readUint32BE();
- if (macDataOffset >= context->file->size() || macMapOffset >= context->file->size() ||
- macDataLength + macMapLength > context->file->size()) {
+ if (macDataOffset >= (uint)context->file->size() || macMapOffset >= (uint)context->file->size() ||
+ macDataLength + macMapLength > (uint)context->file->size()) {
return false;
}
@@ -384,24 +384,24 @@ bool Resource::createContexts() {
if (!soundFileInArray) {
if (_vm->getGameType() == GType_ITE) {
// If the sound file is not specified in the detector table, add it here
- if (Common::File::exists("sounds.rsc") || Common::File::exists("sounds.cmp")) {
+ if (Common::File::exists("sounds.rsc")) {
_contextsCount++;
soundFileIndex = _contextsCount - 1;
- if (Common::File::exists("sounds.rsc")) {
- sprintf(soundFileName, "sounds.rsc");
- } else {
- sprintf(soundFileName, "sounds.cmp");
- _vm->_gf_compressed_sounds = true;
- }
- } else if (Common::File::exists("soundsd.rsc") || Common::File::exists("soundsd.cmp")) {
+ sprintf(soundFileName, "sounds.rsc");
+ } else if (Common::File::exists("sounds.cmp")) {
_contextsCount++;
soundFileIndex = _contextsCount - 1;
- if (Common::File::exists("soundsd.rsc")) {
- sprintf(soundFileName, "soundsd.rsc");
- } else {
- sprintf(soundFileName, "soundsd.cmp");
- _vm->_gf_compressed_sounds = true;
- }
+ sprintf(soundFileName, "sounds.cmp");
+ _vm->_gf_compressed_sounds = true;
+ } else if (Common::File::exists("soundsd.rsc")) {
+ _contextsCount++;
+ soundFileIndex = _contextsCount - 1;
+ sprintf(soundFileName, "soundsd.rsc");
+ } else if (Common::File::exists("soundsd.cmp")) {
+ _contextsCount++;
+ soundFileIndex = _contextsCount - 1;
+ sprintf(soundFileName, "soundsd.cmp");
+ _vm->_gf_compressed_sounds = true;
} else {
// No sound file found, don't add any file to the array
soundFileInArray = true;
@@ -410,15 +410,15 @@ bool Resource::createContexts() {
}
} else {
// If the sound file is not specified in the detector table, add it here
- if (Common::File::exists("sfx.res") || Common::File::exists("sfx.cmp")) {
+ if (Common::File::exists("sfx.res")) {
_contextsCount++;
soundFileIndex = _contextsCount - 1;
- if (Common::File::exists("sfx.res")) {
- sprintf(soundFileName, "sfx.res");
- } else {
- sprintf(soundFileName, "sfx.cmp");
- _vm->_gf_compressed_sounds = true;
- }
+ sprintf(soundFileName, "sfx.res");
+ } else if (Common::File::exists("sfx.cmp")) {
+ _contextsCount++;
+ soundFileIndex = _contextsCount - 1;
+ sprintf(soundFileName, "sfx.cmp");
+ _vm->_gf_compressed_sounds = true;
} else {
// No sound file found, don't add any file to the array
soundFileInArray = true;
@@ -429,24 +429,24 @@ bool Resource::createContexts() {
if (!voicesFileInArray) {
if (_vm->getGameType() == GType_ITE) {
// If the voices file is not specified in the detector table, add it here
- if (Common::File::exists("voices.rsc") || Common::File::exists("voices.cmp")) {
+ if (Common::File::exists("voices.rsc")) {
_contextsCount++;
voicesFileIndex = _contextsCount - 1;
- if (Common::File::exists("voices.rsc")) {
- sprintf(_voicesFileName[0], "voices.rsc");
- } else {
- sprintf(_voicesFileName[0], "voices.cmp");
- _vm->_gf_compressed_sounds = true;
- }
- } else if (Common::File::exists("voicesd.rsc") || Common::File::exists("voicesd.cmp")) {
+ sprintf(_voicesFileName[0], "voices.rsc");
+ } else if (Common::File::exists("voices.cmp")) {
_contextsCount++;
voicesFileIndex = _contextsCount - 1;
- if (Common::File::exists("voicesd.rsc")) {
- sprintf(_voicesFileName[0], "voicesd.rsc");
- } else {
- sprintf(_voicesFileName[0], "voicesd.cmp");
- _vm->_gf_compressed_sounds = true;
- }
+ sprintf(_voicesFileName[0], "voices.cmp");
+ _vm->_gf_compressed_sounds = true;
+ } else if (Common::File::exists("voicesd.rsc")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ sprintf(_voicesFileName[0], "voicesd.rsc");
+ } else if (Common::File::exists("voicesd.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ sprintf(_voicesFileName[0], "voicesd.cmp");
+ _vm->_gf_compressed_sounds = true;
} else if (Common::File::exists("inherit the earth voices") ||
Common::File::exists("inherit the earth voices.cmp")) {
_contextsCount++;
@@ -493,15 +493,15 @@ bool Resource::createContexts() {
sprintf(_voicesFileName[0], "voicess.cmp");
_vm->_gf_compressed_sounds = true;
}
- } else if (Common::File::exists("voicesd.res") || Common::File::exists("voicesd.cmp")) {
+ } else if (Common::File::exists("voicesd.res")) {
_contextsCount++;
voicesFileIndex = _contextsCount - 1;
- if (Common::File::exists("voicesd.res")) {
- sprintf(_voicesFileName[0], "voicesd.res");
- } else {
- sprintf(_voicesFileName[0], "voicesd.cmp");
- _vm->_gf_compressed_sounds = true;
- }
+ sprintf(_voicesFileName[0], "voicesd.res");
+ } else if (Common::File::exists("voicesd.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ sprintf(_voicesFileName[0], "voicesd.cmp");
+ _vm->_gf_compressed_sounds = true;
} else {
// No voice file found, don't add any file to the array
voicesFileInArray = true;
@@ -521,20 +521,22 @@ bool Resource::createContexts() {
if (_vm->getGameType() == GType_ITE) {
// Check for digital music in ITE
- if (Common::File::exists("music.rsc") || Common::File::exists("music.cmp")) {
+ if (Common::File::exists("music.rsc")) {
_contextsCount++;
digitalMusic = true;
- if (Common::File::exists("music.cmp"))
- sprintf(musicFileName, "music.cmp");
- else
- sprintf(musicFileName, "music.rsc");
- } else if (Common::File::exists("musicd.rsc") || Common::File::exists("musicd.cmp")) {
+ sprintf(musicFileName, "music.rsc");
+ } else if (Common::File::exists("music.cmp")) {
_contextsCount++;
digitalMusic = true;
- if (Common::File::exists("musicd.cmp"))
- sprintf(musicFileName, "musicd.cmp");
- else
- sprintf(musicFileName, "musicd.rsc");
+ sprintf(musicFileName, "music.cmp");
+ } else if (Common::File::exists("musicd.rsc")) {
+ _contextsCount++;
+ digitalMusic = true;
+ sprintf(musicFileName, "musicd.rsc");
+ } else if (Common::File::exists("musicd.cmp")) {
+ _contextsCount++;
+ digitalMusic = true;
+ sprintf(musicFileName, "musicd.cmp");
} else {
digitalMusic = false;
}
@@ -661,9 +663,7 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
if (chapter < 0)
chapter = (_vm->getGameId() != GID_IHNM_DEMO) ? 8 : 7;
- // TODO
- //if (module.voiceLUT)
- // free module.voiceLUT;
+ _vm->_script->_globalVoiceLUT.freeMem();
// TODO: close chapter context, or rather reassign it in our case
@@ -769,7 +769,6 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
_vm->_sprite->_mainSprites.freeMem();
_vm->_sprite->loadList(_metaResource.mainSpritesID, _vm->_sprite->_mainSprites);
-
_vm->_actor->loadObjList(_metaResource.objectCount, _metaResource.objectsResourceID);
_vm->_resource->loadResource(resourceContext, _metaResource.cutawayListResourceID, resourcePointer, resourceLength);
@@ -805,49 +804,21 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
free(resourcePointer);
} else {
// The IHNM demo has a fixed music track and doesn't load a song table
- _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
+ _vm->_music->setVolume(_vm->_musicVolume, 1);
_vm->_music->play(3, MUSIC_LOOP);
free(resourcePointer);
}
int voiceLUTResourceID = 0;
- _vm->_script->_globalVoiceLUT.freeMem();
-
- switch (chapter) {
- case 1:
- _vm->_sndRes->setVoiceBank(1);
- voiceLUTResourceID = 23;
- break;
- case 2:
- _vm->_sndRes->setVoiceBank(2);
- voiceLUTResourceID = 24;
- break;
- case 3:
- _vm->_sndRes->setVoiceBank(3);
- voiceLUTResourceID = 25;
- break;
- case 4:
- _vm->_sndRes->setVoiceBank(4);
- voiceLUTResourceID = 26;
- break;
- case 5:
- _vm->_sndRes->setVoiceBank(5);
- voiceLUTResourceID = 27;
- break;
- case 6:
- _vm->_sndRes->setVoiceBank(6);
- voiceLUTResourceID = 28;
- break;
- case 7:
+ if (chapter != 7) {
+ int voiceBank = (chapter == 8) ? 0 : chapter;
+ _vm->_sndRes->setVoiceBank(voiceBank);
+ voiceLUTResourceID = 22 + voiceBank;
+ } else {
// IHNM demo
_vm->_sndRes->setVoiceBank(0);
voiceLUTResourceID = 17;
- break;
- case 8:
- _vm->_sndRes->setVoiceBank(0);
- voiceLUTResourceID = 22;
- break;
}
if (voiceLUTResourceID) {
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index fafbd02cec..5ce5d6ab93 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -64,7 +64,6 @@ SagaEngine::SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc)
_leftMouseButtonPressed = _rightMouseButtonPressed = false;
_console = NULL;
- _quit = false;
_resource = NULL;
_sndRes = NULL;
@@ -93,20 +92,20 @@ SagaEngine::SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc)
// The Linux version of Inherit the Earth puts all data files in an
// 'itedata' sub-directory, except for voices.rsc
- Common::File::addDefaultDirectory(_gameDataPath + "itedata/");
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("itedata"));
// The Windows version of Inherit the Earth puts various data files in
// other subdirectories.
- Common::File::addDefaultDirectory(_gameDataPath + "graphics/");
- Common::File::addDefaultDirectory(_gameDataPath + "music/");
- Common::File::addDefaultDirectory(_gameDataPath + "sound/");
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("graphics"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("music"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("sound"));
// The Multi-OS version puts the voices file in the root directory of
// the CD. The rest of the data files are in game/itedata
- Common::File::addDefaultDirectory(_gameDataPath + "game/itedata/");
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("game").getChild("itedata"));
// Mac CD Wyrmkeep
- Common::File::addDefaultDirectory(_gameDataPath + "patch/");
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("patch"));
_displayClip.left = _displayClip.top = 0;
syst->getEventManager()->registerRandomSource(_rnd, "saga");
@@ -142,8 +141,7 @@ SagaEngine::~SagaEngine() {
}
int SagaEngine::init() {
- _soundVolume = ConfMan.getInt("sfx_volume") / 25;
- _musicVolume = ConfMan.getInt("music_volume") / 25;
+ _musicVolume = ConfMan.getInt("music_volume");
_subtitlesEnabled = ConfMan.getBool("subtitles");
_readingSpeed = getTalkspeed();
_copyProtection = ConfMan.getBool("copy_protection");
@@ -194,29 +192,21 @@ int SagaEngine::init() {
if (native_mt32)
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- _music = new Music(this, _mixer, _driver, _musicVolume);
+ _music = new Music(this, _mixer, _driver);
_music->setNativeMT32(native_mt32);
_music->setAdlib(adlib);
-
- if (!_musicVolume) {
- debug(1, "Music disabled.");
- }
-
_render = new Render(this, _system);
if (!_render->initialized()) {
return FAILURE;
}
// Initialize system specific sound
- _sound = new Sound(this, _mixer, _soundVolume);
- if (!_soundVolume) {
- debug(1, "Sound disabled.");
- }
-
+ _sound = new Sound(this, _mixer);
+
_interface->converseInit();
_script->setVerb(_script->getVerbType(kVerbWalkTo));
- _music->setVolume(-1, 1);
+ _music->setVolume(_musicVolume, 1);
_gfx->initPalette();
@@ -233,6 +223,8 @@ int SagaEngine::init() {
}
}
+ syncSoundSettings();
+
// FIXME: This is the ugly way of reducing redraw overhead. It works
// well for 320x200 but it's unclear how well it will work for
// 640x480.
@@ -255,14 +247,22 @@ int SagaEngine::go() {
_interface->addToInventory(_actor->objIndexToId(0)); // Magic hat
_scene->changeScene(ConfMan.getInt("boot_param"), 0, kTransitionNoFade);
} else if (ConfMan.hasKey("save_slot")) {
+ // Init the current chapter to 8 (character selection) for IHNM
+ if (getGameType() == GType_IHNM)
+ _scene->changeScene(-2, 0, kTransitionFade, 8);
+
// First scene sets up palette
_scene->changeScene(getStartSceneNumber(), 0, kTransitionNoFade);
_events->handleEvents(0); // Process immediate events
- _interface->setMode(kPanelMain);
- char *fileName;
- fileName = calcSaveFileName(ConfMan.getInt("save_slot"));
+ if (getGameType() != GType_IHNM)
+ _interface->setMode(kPanelMain);
+ else
+ _interface->setMode(kPanelChapterSelection);
+
+ char *fileName = calcSaveFileName(ConfMan.getInt("save_slot"));
load(fileName);
+ syncSoundSettings();
} else {
_framesEsc = 0;
_scene->startScene();
@@ -270,7 +270,7 @@ int SagaEngine::go() {
uint32 currentTicks;
- while (!_quit) {
+ while (!quit()) {
if (_console->isAttached())
_console->onFrame();
@@ -520,4 +520,16 @@ int SagaEngine::getTalkspeed() {
return (ConfMan.getInt("talkspeed") * 3 + 255 / 2) / 255;
}
+void SagaEngine::syncSoundSettings() {
+ _subtitlesEnabled = ConfMan.getBool("subtitles");
+ _readingSpeed = getTalkspeed();
+
+ if (_readingSpeed > 3)
+ _readingSpeed = 0;
+
+ _musicVolume = ConfMan.getInt("music_volume");
+ _music->setVolume(_musicVolume, 1);
+ _sound->setVolume();
+}
+
} // End of namespace Saga
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index eeb8f7a61b..0b6b3b1478 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -492,7 +492,6 @@ protected:
public:
SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc);
virtual ~SagaEngine();
- void shutDown() { _quit = true; }
void save(const char *fileName, const char *saveName);
void load(const char *fileName);
@@ -513,6 +512,8 @@ public:
return isSaveListFull() ? _saveFilesCount : _saveFilesCount + 1;
}
+ virtual void syncSoundSettings();
+
int16 _framesEsc;
uint32 _globalFlags;
@@ -521,6 +522,7 @@ public:
int _soundVolume;
int _musicVolume;
+ int _speechVolume;
bool _subtitlesEnabled;
bool _voicesEnabled;
bool _voiceFilesExist;
@@ -611,8 +613,6 @@ public:
bool _rightMouseButtonPressed;
int _mouseClickCount;
- bool _quit;
-
//current game description
int _gameNumber;
const SAGAGameDescription *_gameDescription;
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index c3c1587822..074b4c933a 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -315,7 +315,7 @@ void Scene::creditsScene() {
break;
}
- _vm->shutDown();
+ _vm->quitGame();
return;
}
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index ea61f5ce04..e19fd5ae02 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -276,31 +276,14 @@ void Script::sfTakeObject(SCRIPTFUNC_PARAMS) {
if (obj->_sceneNumber != ITE_SCENE_INV) {
obj->_sceneNumber = ITE_SCENE_INV;
- // WORKAROUND for a problematic object in IHNM
- // There are 3 different scenes in front of the zeppelin, in Gorrister's chapter. A scene where the
- // zeppelin is in the air (scene 17), a scene where it approaches Gorrister's (scene 16) and another one
- // where it has landed (scene 18).
- // In two of these scenes (the "on air" and "approaching" ones), when the player uses the knife with the
- // rope, the associated script picks up object id 16392. In the "zeppelin landed" scene (scene 18), the
- // associated script picks up object id 16390. This seems to be a script bug, as it should be id 16392,
- // like in the other two scenes, as it is the same object (the rope). Picking up object 16390 leads to an
- // assertion anyway, therefore we change the problematic object (16390) to the correct one (16392) here.
- // Fixes bug #1861126 - "IHNM: Crash when Gorrister cuts sheet in the mooring ring"
- if (_vm->getGameType() == GType_IHNM) {
- if (_vm->_scene->currentChapterNumber() == 1 && _vm->_scene->currentSceneNumber() == 18) {
- if (objectId == 16390)
- objectId = 16392;
- }
- }
-
- // WORKAROUND for two incorrect object sprites in the IHNM demo
- // (the mirror and the icon in Ted's part). Set them correctly here
- if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (objectId == 16408)
- obj->_spriteListResourceId = 24;
- if (objectId == 16409)
- obj->_spriteListResourceId = 25;
- }
+ // Normally, when objects are picked up, they should always have the same
+ // _spriteListResourceId as their _index value. Some don't in IHNM, so
+ // we fix their sprite here
+ // Fixes bugs #2057200 - "IHNM: Invisible inventory objects",
+ // #1861126 - "IHNM: Crash when Gorrister cuts sheet in the mooring ring"
+ // and some incorrect objects in the IHNM demo
+ if (_vm->getGameType() == GType_IHNM)
+ obj->_spriteListResourceId = obj->_index;
_vm->_interface->addToInventory(objectId);
}
@@ -356,7 +339,7 @@ void Script::sfMainMode(SCRIPTFUNC_PARAMS) {
// exit the game. Known non-interactive demos are GID_ITE_MACDEMO1 and
// GID_ITE_WINDEMO1
if (_vm->getFeatures() & GF_NON_INTERACTIVE)
- _vm->shutDown();
+ _vm->quitGame();
}
// Script function #6 (0x06) blocking
@@ -572,7 +555,7 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
}
if (_vm->getGameType() == GType_ITE && sceneNumber < 0) {
- _vm->shutDown();
+ _vm->quitGame();
return;
}
@@ -1482,7 +1465,7 @@ void Script::sfPlayMusic(SCRIPTFUNC_PARAMS) {
int16 param = thread->pop() + 9;
if (param >= 9 && param <= 34) {
- _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
+ _vm->_music->setVolume(_vm->_musicVolume, 1);
_vm->_music->play(param);
} else {
_vm->_music->stop();
@@ -1499,7 +1482,7 @@ void Script::sfPlayMusic(SCRIPTFUNC_PARAMS) {
if (param1 >= _vm->_music->_songTableLen) {
warning("sfPlayMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1);
} else {
- _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
+ _vm->_music->setVolume(_vm->_musicVolume, 1);
_vm->_music->play(_vm->_music->_songTable[param1], param2 ? MUSIC_LOOP : MUSIC_NORMAL);
if (!_vm->_scene->haveChapterPointsChanged()) {
_vm->_scene->setCurrentMusicTrack(param1);
@@ -1945,7 +1928,7 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
if (param1 >= _vm->_music->_songTableLen) {
warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1);
} else {
- _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
+ _vm->_music->setVolume(_vm->_musicVolume, 1);
event.type = kEvTOneshot;
event.code = kMusicEvent;
event.param = _vm->_music->_songTable[param1];
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index 8d269fb3e8..b990b8ddf7 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -169,7 +169,6 @@ void SndRes::playVoice(uint32 resourceId) {
}
bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader) {
- byte *soundResource;
Audio::AudioStream *voxStream;
size_t soundResourceLength;
bool result = false;
@@ -180,13 +179,13 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
byte flags;
size_t voxSize;
const GameSoundInfo *soundInfo;
+ Common::File* file;
if (resourceId == (uint32)-1) {
return false;
}
if (_vm->getGameType() == GType_IHNM && _vm->isMacResources()) {
- Common::File soundFile;
char soundFileName[40];
int dirIndex = resourceId / 64;
@@ -199,15 +198,23 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
} else {
sprintf(soundFileName, "SFX/SFX%d/SFX%03x", dirIndex, resourceId);
}
- soundFile.open(soundFileName);
- soundResourceLength = soundFile.size();
- soundResource = new byte[soundResourceLength];
- soundFile.read(soundResource, soundResourceLength);
- soundFile.close();
+
+ file = new Common::File();
+
+ file->open(soundFileName);
+ soundResourceLength = file->size();
} else {
- _vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength);
+
+ ResourceData* resourceData = _vm->_resource->getResourceData(context, resourceId);
+ file = context->getFile(resourceData);
+
+ file->seek(resourceData->offset);
+ soundResourceLength = resourceData->size;
+
}
+ Common::SeekableReadStream& readS = *file;
+
if ((context->fileType & GAME_VOICEFILE) != 0) {
soundInfo = _vm->getVoiceInfo();
} else {
@@ -220,16 +227,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
context->table[resourceId].fillSoundPatch(soundInfo);
}
- MemoryReadStream readS(soundResource, soundResourceLength);
resourceType = soundInfo->resourceType;
if (soundResourceLength >= 8) {
- if (!memcmp(soundResource, "Creative", 8)) {
+ byte header[8];
+
+ readS.read(&header, 8);
+ readS.seek(readS.pos() - 8);
+
+ if (!memcmp(header, "Creative", 8)) {
resourceType = kSoundVOC;
- } else if (!memcmp(soundResource, "RIFF", 4) != 0) {
+ } else if (!memcmp(header, "RIFF", 4) != 0) {
resourceType = kSoundWAV;
- } else if (!memcmp(soundResource, "FORM", 4) != 0) {
+ } else if (!memcmp(header, "FORM", 4) != 0) {
resourceType = kSoundAIFF;
}
@@ -244,11 +255,11 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
uncompressedSound = true;
if ((_vm->getFeatures() & GF_COMPRESSED_SOUNDS) && !uncompressedSound) {
- if (soundResource[0] == char(0)) {
+ if (header[0] == char(0)) {
resourceType = kSoundMP3;
- } else if (soundResource[0] == char(1)) {
+ } else if (header[0] == char(1)) {
resourceType = kSoundOGG;
- } else if (soundResource[0] == char(2)) {
+ } else if (header[0] == char(2)) {
resourceType = kSoundFLAC;
}
}
@@ -268,9 +279,9 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
buffer.stereo = false;
if (onlyHeader) {
buffer.buffer = NULL;
- free(soundResource);
} else {
- buffer.buffer = soundResource;
+ buffer.buffer = (byte *) malloc(soundResourceLength);
+ readS.read(buffer.buffer, soundResourceLength);
}
result = true;
break;
@@ -284,9 +295,10 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
buffer.buffer = NULL;
} else {
buffer.buffer = (byte *)malloc(buffer.size);
- memcpy(buffer.buffer, soundResource + 36, buffer.size);
+
+ readS.seek(readS.pos() + 36);
+ readS.read(buffer.buffer, buffer.size);
}
- free(soundResource);
result = true;
break;
case kSoundVOX:
@@ -297,7 +309,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
buffer.size = soundResourceLength * 4;
if (onlyHeader) {
buffer.buffer = NULL;
- free(soundResource);
} else {
voxStream = Audio::makeADPCMStream(&readS, false, soundResourceLength, Audio::kADPCMOki);
buffer.buffer = (byte *)malloc(buffer.size);
@@ -325,7 +336,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
result = true;
}
- free(soundResource);
break;
case kSoundWAV:
if (Audio::loadWAVFromStream(readS, size, rate, flags)) {
@@ -342,7 +352,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
result = true;
}
- free(soundResource);
break;
case kSoundAIFF:
if (Audio::loadAIFFFromStream(readS, size, rate, flags)) {
@@ -359,7 +368,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
result = true;
}
- free(soundResource);
break;
case kSoundMP3:
case kSoundOGG:
@@ -382,12 +390,17 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
buffer.buffer = NULL;
result = true;
- free(soundResource);
break;
default:
error("SndRes::load Unknown sound type");
}
+
+ if (_vm->getGameType() == GType_IHNM && _vm->isMacResources()) {
+ delete file;
+ }
+
+
// In ITE CD De some voices are absent and contain just 5 bytes header
// Round it to even number so soundmanager will not crash.
// See bug #1256701
diff --git a/engines/saga/sndres.h b/engines/saga/sndres.h
index e77c833076..d5507ebc55 100644
--- a/engines/saga/sndres.h
+++ b/engines/saga/sndres.h
@@ -39,7 +39,6 @@ public:
SndRes(SagaEngine *vm);
~SndRes();
- int loadSound(uint32 resourceId);
void playSound(uint32 resourceId, int volume, bool loop);
void playVoice(uint32 resourceId);
int getVoiceLength(uint32 resourceId);
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index 1d3263d302..1d41d39cf2 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -22,8 +22,10 @@
* $Id$
*
*/
-#include "saga/saga.h"
+#include "common/config-manager.h"
+
+#include "saga/saga.h"
#include "saga/sound.h"
#include "sound/audiostream.h"
@@ -32,13 +34,13 @@
namespace Saga {
-Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer, int volume) :
+Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer) :
_vm(vm), _mixer(mixer), _voxStream(0) {
for (int i = 0; i < SOUND_HANDLES; i++)
_handles[i].type = kFreeHandle;
- setVolume(volume == 10 ? 255 : volume * 25);
+ setVolume();
}
Sound::~Sound() {
@@ -61,7 +63,8 @@ SndHandle *Sound::getHandle() {
return NULL;
}
-void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume, bool loop) {
+void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume,
+ sndHandleType handleType, bool loop) {
byte flags;
flags = Audio::Mixer::FLAG_AUTOFREE;
@@ -81,7 +84,12 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int
flags |= Audio::Mixer::FLAG_UNSIGNED;
if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
+ if (handleType == kVoiceHandle)
+ _mixer->playRaw(Audio::Mixer::kSpeechSoundType, handle, buffer.buffer,
+ buffer.size, buffer.frequency, flags, -1, volume);
+ else
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer,
+ buffer.size, buffer.frequency, flags, -1, volume);
} else {
Audio::AudioStream *stream = NULL;
MemoryReadStream *tmp = NULL;
@@ -116,12 +124,23 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int
#endif
default:
// No compression, play it as raw sound
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
+ if (handleType == kVoiceHandle)
+ _mixer->playRaw(Audio::Mixer::kSpeechSoundType, handle, buffer.buffer,
+ buffer.size, buffer.frequency, flags, -1, volume);
+ else
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer,
+ buffer.size, buffer.frequency, flags, -1, volume);
break;
}
- if (stream != NULL)
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, stream, -1, volume, 0, true, false);
+ if (stream != NULL) {
+ if (handleType == kVoiceHandle)
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, handle, stream, -1,
+ volume, 0, true, false);
+ else
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, stream, -1,
+ volume, 0, true, false);
+ }
}
}
@@ -129,7 +148,7 @@ void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) {
SndHandle *handle = getHandle();
handle->type = kEffectHandle;
- playSoundBuffer(&handle->handle, buffer, 2 * volume, loop);
+ playSoundBuffer(&handle->handle, buffer, 2 * volume, handle->type, loop);
}
void Sound::pauseSound() {
@@ -156,7 +175,7 @@ void Sound::playVoice(SoundBuffer &buffer) {
SndHandle *handle = getHandle();
handle->type = kVoiceHandle;
- playSoundBuffer(&handle->handle, buffer, 255, false);
+ playSoundBuffer(&handle->handle, buffer, 255, handle->type, false);
}
void Sound::pauseVoice() {
@@ -184,9 +203,11 @@ void Sound::stopAll() {
stopSound();
}
-void Sound::setVolume(int volume) {
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume);
+void Sound::setVolume() {
+ _vm->_soundVolume = ConfMan.getInt("sound_volume");
+ _vm->_speechVolume = ConfMan.getInt("speech_volume");
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_soundVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_speechVolume);
}
} // End of namespace Saga
diff --git a/engines/saga/sound.h b/engines/saga/sound.h
index ce479c64d1..6d9e42a49d 100644
--- a/engines/saga/sound.h
+++ b/engines/saga/sound.h
@@ -71,7 +71,7 @@ struct SndHandle {
class Sound {
public:
- Sound(SagaEngine *vm, Audio::Mixer *mixer, int volume);
+ Sound(SagaEngine *vm, Audio::Mixer *mixer);
~Sound();
void playSound(SoundBuffer &buffer, int volume, bool loop);
@@ -86,11 +86,12 @@ public:
void stopAll();
- void setVolume(int volume);
+ void setVolume();
private:
- void playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume, bool loop);
+ void playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume,
+ sndHandleType handleType, bool loop);
SndHandle *getHandle();
diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp
index d9c7b446ba..a1f78e1b9f 100644
--- a/engines/saga/sprite.cpp
+++ b/engines/saga/sprite.cpp
@@ -412,6 +412,8 @@ void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t ou
while (!readS.eos() && (outPointer < outPointerEnd)) {
bg_runcount = readS.readByte();
+ if (readS.eos())
+ break;
fg_runcount = readS.readByte();
for (c = 0; c < bg_runcount && !readS.eos(); c++) {
@@ -424,6 +426,8 @@ void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t ou
for (c = 0; c < fg_runcount && !readS.eos(); c++) {
*outPointer = readS.readByte();
+ if (readS.eos())
+ break;
if (outPointer < outPointerEnd)
outPointer++;
else
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index ca5dba7865..d3397fe208 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -177,7 +177,7 @@ static Common::String generateFilenameForDetection(const char *pattern, Filename
}
struct DetectorDesc {
- FilesystemNode node;
+ Common::FilesystemNode node;
Common::String md5;
const MD5Table *md5Entry; // Entry of the md5 table corresponding to this file, if any.
};
@@ -191,8 +191,8 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com
// when performing the matching. The first match is returned, so if you
// search for "resource" and two nodes "RESOURE and "resource" are present,
// the first match is used.
-static bool searchFSNode(const FSList &fslist, const Common::String &name, FilesystemNode &result) {
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+static bool searchFSNode(const Common::FSList &fslist, const Common::String &name, Common::FilesystemNode &result) {
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!scumm_stricmp(file->getName().c_str(), name.c_str())) {
result = *file;
return true;
@@ -202,7 +202,7 @@ static bool searchFSNode(const FSList &fslist, const Common::String &name, Files
}
// The following function tries to detect the language for COMI and DIG
-static Common::Language detectLanguage(const FSList &fslist, byte id) {
+static Common::Language detectLanguage(const Common::FSList &fslist, byte id) {
assert(id == GID_CMI || id == GID_DIG);
// Check for LANGUAGE.BND (Dig) resp. LANGUAGE.TAB (CMI).
@@ -212,14 +212,14 @@ static Common::Language detectLanguage(const FSList &fslist, byte id) {
// switch to MD5 based detection).
const char *filename = (id == GID_CMI) ? "LANGUAGE.TAB" : "LANGUAGE.BND";
Common::File tmp;
- FilesystemNode langFile;
+ Common::FilesystemNode langFile;
if (!searchFSNode(fslist, filename, langFile) || !tmp.open(langFile)) {
// try loading in RESOURCE sub dir...
- FilesystemNode resDir;
- FSList tmpList;
+ Common::FilesystemNode resDir;
+ Common::FSList tmpList;
if (searchFSNode(fslist, "RESOURCE", resDir)
&& resDir.isDirectory()
- && resDir.getChildren(tmpList, FilesystemNode::kListFilesOnly)
+ && resDir.getChildren(tmpList, Common::FilesystemNode::kListFilesOnly)
&& searchFSNode(tmpList, filename, langFile)) {
tmp.open(langFile);
}
@@ -270,7 +270,7 @@ static Common::Language detectLanguage(const FSList &fslist, byte id) {
}
-static void computeGameSettingsFromMD5(const FSList &fslist, const GameFilenamePattern *gfp, const MD5Table *md5Entry, DetectorResult &dr) {
+static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameFilenamePattern *gfp, const MD5Table *md5Entry, DetectorResult &dr) {
dr.language = md5Entry->language;
dr.extra = md5Entry->extra;
@@ -315,12 +315,12 @@ static void computeGameSettingsFromMD5(const FSList &fslist, const GameFilenameP
}
}
-static void detectGames(const FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) {
+static void detectGames(const Common::FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) {
DescMap fileMD5Map;
DetectorResult dr;
char md5str[32+1];
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
DetectorDesc d;
d.node = *file;
@@ -674,15 +674,30 @@ public:
virtual const char *getName() const;
virtual const char *getCopyright() const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual GameList getSupportedGames() const;
virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const FSList &fslist) const;
-
+ virtual GameList detectGames(const Common::FSList &fslist) const;
+
virtual PluginError createInstance(OSystem *syst, Engine **engine) const;
virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
+ virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
+bool ScummMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSupportsMetaInfos) ||
+ (f == kSupportsThumbnails) ||
+ (f == kSupportsSaveDate) ||
+ (f == kSupportsSavePlayTime);
+}
+
GameList ScummMetaEngine::getSupportedGames() const {
return GameList(gameDescriptions);
}
@@ -691,8 +706,7 @@ GameDescriptor ScummMetaEngine::findGame(const char *gameid) const {
return Common::AdvancedDetector::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable);
}
-
-GameList ScummMetaEngine::detectGames(const FSList &fslist) const {
+GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const {
GameList detectedGames;
Common::List<DetectorResult> results;
@@ -769,9 +783,9 @@ PluginError ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
}
// Fetch the list of files in the current directory
- FSList fslist;
- FilesystemNode dir(ConfMan.get("path"));
- if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ Common::FSList fslist;
+ Common::FilesystemNode dir(ConfMan.get("path"));
+ if (!dir.getChildren(fslist, Common::FilesystemNode::kListFilesOnly)) {
return kInvalidPathError;
}
@@ -967,6 +981,53 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const {
return saveList;
}
+void ScummMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
+SaveStateDescriptor ScummMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
+
+ if (!in)
+ return SaveStateDescriptor();
+
+ Common::String saveDesc;
+ Scumm::getSavegameName(in, saveDesc, 0); // FIXME: heversion?!?
+ delete in;
+
+ // TODO: Cleanup
+ Graphics::Surface *thumbnail = ScummEngine::loadThumbnailFromSlot(target, slot);
+
+ SaveStateDescriptor desc(slot, saveDesc, filename);
+ desc.setDeletableFlag(true);
+ desc.setThumbnail(thumbnail);
+
+ InfoStuff infos;
+ memset(&infos, 0, sizeof(infos));
+ if (ScummEngine::loadInfosFromSlot(target, slot, &infos)) {
+ int day = (infos.date >> 24) & 0xFF;
+ int month = (infos.date >> 16) & 0xFF;
+ int year = infos.date & 0xFFFF;
+
+ desc.setSaveDate(year, month, day);
+
+ int hour = (infos.time >> 8) & 0xFF;
+ int minutes = infos.time & 0xFF;
+
+ desc.setSaveTime(hour, minutes);
+
+ minutes = infos.playtime / 60;
+ hour = minutes / 60;
+ minutes %= 60;
+
+ desc.setPlayTime(hour, minutes);
+ }
+
+ return desc;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(SCUMM)
REGISTER_PLUGIN_DYNAMIC(SCUMM, PLUGIN_TYPE_ENGINE, ScummMetaEngine);
#else
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 324cc91e78..d281364a77 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -472,12 +472,14 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "fbear", "fbdemo", kGenHEPC, UNK_LANG, UNK, 0 },
{ "fbear", "Fatty Bear Demo", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "fbear", "Fatty Bear", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 },
+ { "fbear", "jfbear", kGenHEPC, Common::JA_JPN, Common::kPlatform3DO, 0 },
{ "puttmoon", "puttmoon", kGenHEPC, UNK_LANG, UNK, 0 },
{ "puttmoon", "moondemo", kGenHEPC, UNK_LANG, UNK, 0 },
{ "puttmoon", "Putt-Putt Moon Demo", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "puttmoon", "Putt-Putt Moon", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 },
+ { "puttputt", "jputtputt", kGenHEPC, Common::JA_JPN, Common::kPlatform3DO, 0 },
{ "puttputt", "puttputt", kGenHEPC, UNK_LANG, UNK, 0 },
{ "puttputt", "puttdemo", kGenHEPC, UNK_LANG, UNK, 0 },
{ "puttputt", "Putt-Putt's Demo", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 },
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 8886214910..ee1c0abf1c 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -322,8 +322,6 @@ void SaveLoadChooser::reflowLayout() {
if (!g_gui.xmlEval()->getWidgetData("ScummSaveLoad.Thumbnail", x, y, w, h))
error("Error when loading position data for Save/Load Thumbnails.");
- _container->resize(x, y, w, h);
-
int thumbW = kThumbnailWidth;
int thumbH = ((g_system->getHeight() % 200 && g_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1);
int thumbX = x + (w >> 1) - (thumbW >> 1);
@@ -398,8 +396,7 @@ void SaveLoadChooser::updateInfos(bool redraw) {
int hours = minutes / 60;
minutes %= 60;
- snprintf(buffer, 32, "Playtime: %.2d:%.2d",
- hours & 0xFF, minutes & 0xFF);
+ snprintf(buffer, 32, "Playtime: %.2d:%.2d", hours, minutes);
_playtime->setLabel(buffer);
} else {
_date->setLabel("No date saved");
@@ -434,7 +431,7 @@ Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) {
return descriptions;
}
-MainMenuDialog::MainMenuDialog(ScummEngine *scumm)
+ScummMenuDialog::ScummMenuDialog(ScummEngine *scumm)
: ScummDialog("ScummMain"), _vm(scumm) {
new GUI::ButtonWidget(this, "ScummMain.Resume", "Resume", kPlayCmd, 'P');
@@ -462,7 +459,7 @@ MainMenuDialog::MainMenuDialog(ScummEngine *scumm)
_loadDialog = new SaveLoadChooser("Load game:", "Load", false, scumm);
}
-MainMenuDialog::~MainMenuDialog() {
+ScummMenuDialog::~ScummMenuDialog() {
delete _aboutDialog;
delete _optionsDialog;
#ifndef DISABLE_HELP
@@ -472,7 +469,7 @@ MainMenuDialog::~MainMenuDialog() {
delete _loadDialog;
}
-void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+void ScummMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kSaveCmd:
save();
@@ -495,7 +492,7 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
break;
#endif
case kQuitCmd:
- _vm->_quit = true;
+ _vm->quitGame();
close();
break;
default:
@@ -503,7 +500,7 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
}
}
-void MainMenuDialog::save() {
+void ScummMenuDialog::save() {
int idx;
_saveDialog->setList(generateSavegameList(_vm, true));
idx = _saveDialog->runModal();
@@ -522,7 +519,7 @@ void MainMenuDialog::save() {
}
}
-void MainMenuDialog::load() {
+void ScummMenuDialog::load() {
int idx;
_loadDialog->setList(generateSavegameList(_vm, false));
idx = _loadDialog->runModal();
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index 0d04d8faea..3837787a3b 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -82,10 +82,10 @@ public:
virtual void reflowLayout();
};
-class MainMenuDialog : public ScummDialog {
+class ScummMenuDialog : public ScummDialog {
public:
- MainMenuDialog(ScummEngine *scumm);
- ~MainMenuDialog();
+ ScummMenuDialog(ScummEngine *scumm);
+ ~ScummMenuDialog();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
protected:
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index bf13308a0c..f258ddd420 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -42,9 +42,9 @@ void ScummFile::setEnc(byte value) {
_encbyte = value;
}
-void ScummFile::setSubfileRange(uint32 start, uint32 len) {
+void ScummFile::setSubfileRange(int32 start, int32 len) {
// TODO: Add sanity checks
- const uint32 fileSize = File::size();
+ const int32 fileSize = File::size();
assert(start <= fileSize);
assert(start + len <= fileSize);
_subFileStart = start;
@@ -125,19 +125,19 @@ bool ScummFile::openSubFile(const Common::String &filename) {
}
-bool ScummFile::eof() {
- return _subFileLen ? (pos() >= _subFileLen) : File::eof();
+bool ScummFile::eos() {
+ return _subFileLen ? (pos() >= _subFileLen) : File::eos(); // FIXME
}
-uint32 ScummFile::pos() {
+int32 ScummFile::pos() {
return File::pos() - _subFileStart;
}
-uint32 ScummFile::size() {
+int32 ScummFile::size() {
return _subFileLen ? _subFileLen : File::size();
}
-void ScummFile::seek(int32 offs, int whence) {
+bool ScummFile::seek(int32 offs, int whence) {
if (_subFileLen) {
// Constrain the seek to the subfile
switch (whence) {
@@ -154,7 +154,7 @@ void ScummFile::seek(int32 offs, int whence) {
assert((int32)_subFileStart <= offs && offs <= (int32)(_subFileStart + _subFileLen));
whence = SEEK_SET;
}
- File::seek(offs, whence);
+ return File::seek(offs, whence);
}
uint32 ScummFile::read(void *dataPtr, uint32 dataSize) {
@@ -162,12 +162,12 @@ uint32 ScummFile::read(void *dataPtr, uint32 dataSize) {
if (_subFileLen) {
// Limit the amount we read by the subfile boundaries.
- const uint32 curPos = pos();
+ const int32 curPos = pos();
assert(_subFileLen >= curPos);
- uint32 newPos = curPos + dataSize;
+ int32 newPos = curPos + dataSize;
if (newPos > _subFileLen) {
dataSize = _subFileLen - curPos;
- _ioFailed = true;
+ _myIoFailed = true;
}
}
diff --git a/engines/scumm/file.h b/engines/scumm/file.h
index a2695cac59..336f3cde12 100644
--- a/engines/scumm/file.h
+++ b/engines/scumm/file.h
@@ -39,32 +39,37 @@ public:
virtual bool open(const Common::String &filename) = 0;
virtual bool openSubFile(const Common::String &filename) = 0;
- virtual bool eof() = 0;
- virtual uint32 pos() = 0;
- virtual uint32 size() = 0;
- virtual void seek(int32 offs, int whence = SEEK_SET) = 0;
+ virtual bool eos() = 0;
+ virtual int32 pos() = 0;
+ virtual int32 size() = 0;
+ virtual bool seek(int32 offs, int whence = SEEK_SET) = 0;
virtual uint32 read(void *dataPtr, uint32 dataSize) = 0;
};
class ScummFile : public BaseScummFile {
private:
byte _encbyte;
- uint32 _subFileStart;
- uint32 _subFileLen;
+ int32 _subFileStart;
+ int32 _subFileLen;
+ bool _myIoFailed;
+
+ void setSubfileRange(int32 start, int32 len);
+ void resetSubfile();
+
public:
ScummFile();
void setEnc(byte value);
- void setSubfileRange(uint32 start, uint32 len);
- void resetSubfile();
-
bool open(const Common::String &filename);
bool openSubFile(const Common::String &filename);
- bool eof();
- uint32 pos();
- uint32 size();
- void seek(int32 offs, int whence = SEEK_SET);
+ bool ioFailed() const { return _myIoFailed || BaseScummFile::ioFailed(); }
+ void clearIOFailed() { _myIoFailed = false; BaseScummFile::clearIOFailed(); }
+
+ bool eos();
+ int32 pos();
+ int32 size();
+ bool seek(int32 offs, int whence = SEEK_SET);
uint32 read(void *dataPtr, uint32 dataSize);
};
@@ -106,10 +111,10 @@ public:
bool openSubFile(const Common::String &filename);
void close();
- bool eof() { return _stream->eos(); }
- uint32 pos() { return _stream->pos(); }
- uint32 size() { return _stream->size(); }
- void seek(int32 offs, int whence = SEEK_SET) { _stream->seek(offs, whence); }
+ bool eos() { return _stream->eos(); }
+ int32 pos() { return _stream->pos(); }
+ int32 size() { return _stream->size(); }
+ bool seek(int32 offs, int whence = SEEK_SET) { return _stream->seek(offs, whence); }
uint32 read(void *dataPtr, uint32 dataSize) { return _stream->read(dataPtr, dataSize); }
};
diff --git a/engines/scumm/file_nes.cpp b/engines/scumm/file_nes.cpp
index 8325436f87..0ddbd0b3ee 100644
--- a/engines/scumm/file_nes.cpp
+++ b/engines/scumm/file_nes.cpp
@@ -1124,8 +1124,7 @@ bool ScummNESFile::generateResource(int res) {
write_byte(&out, 0xD1);
write_byte(&out, 0xF5);
- if (_stream)
- delete _stream;
+ delete _stream;
_stream = new Common::MemoryReadStream(_buf, bufsize);
@@ -1221,8 +1220,7 @@ bool ScummNESFile::generateIndex() {
for (i = 0; i < (int)sizeof(lfl_index); i++)
write_byte(&out, ((byte *)&lfl_index)[i]);
- if (_stream)
- delete _stream;
+ delete _stream;
_stream = new Common::MemoryReadStream(_buf, bufsize);
diff --git a/engines/scumm/file_nes.h b/engines/scumm/file_nes.h
index 4d2d6de275..f1a07f8085 100644
--- a/engines/scumm/file_nes.h
+++ b/engines/scumm/file_nes.h
@@ -68,10 +68,10 @@ public:
bool openSubFile(const Common::String &filename);
void close();
- bool eof() { return _stream->eos(); }
- uint32 pos() { return _stream->pos(); }
- uint32 size() { return _stream->size(); }
- void seek(int32 offs, int whence = SEEK_SET) { _stream->seek(offs, whence); }
+ bool eos() { return _stream->eos(); }
+ int32 pos() { return _stream->pos(); }
+ int32 size() { return _stream->size(); }
+ bool seek(int32 offs, int whence = SEEK_SET) { return _stream->seek(offs, whence); }
uint32 read(void *dataPtr, uint32 dataSize) { return _stream->read(dataPtr, dataSize); }
};
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index d09accafb0..45b078b6f9 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -46,7 +46,7 @@ namespace Scumm {
static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
static void fill(byte *dst, int dstPitch, byte color, int w, int h);
-#ifndef ARM_USE_GFX_ASM
+#ifndef USE_ARM_GFX_ASM
static void copy8Col(byte *dst, int dstPitch, const byte *src, int height);
#endif
static void clear8Col(byte *dst, int dstPitch, int height);
@@ -612,32 +612,37 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
assert(0 == (width & 3));
// Compose the text over the game graphics
-
- // TODO: Optimize this code. There are several things that come immediately to mind:
- // (1) Loop unrolling: We could read 4 or even 8 pixels at once, since everything is
- // a multiple of 8 here.
- // (2) More ASM versions (in particular, the ARM code for the NDS could be used on
- // all ARM systems, couldn't it?)
- // (3) Better encoding of the text surface data. This is the one with the biggest
- // potential.
- // (a) Keep an "isEmpty" marker for each pixel row in the _textSurface. The idea
- // is that most rows won't contain any text data, so we can just use memcpy.
- // (b) RLE encode the _textSurface row-wise. This is an improved variant of (a),
- // but also more complicated to implement, and incurs a bigger overhead when
- // writing to the text surface.
-#ifdef ARM_USE_GFX_ASM
+#ifdef USE_ARM_GFX_ASM
asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, width, _textSurface.pitch);
#else
- for (int h = 0; h < height * m; ++h) {
- for (int w = 0; w < width * m; ++w) {
- byte tmp = *text++;
- if (tmp == CHARSET_MASK_TRANSPARENCY)
- tmp = *src;
- *dst++ = tmp;
- src++;
+ // We blit four pixels at a time, for improved performance.
+ const uint32 *src32 = (const uint32 *)src;
+ const uint32 *text32 = (const uint32 *)text;
+ uint32 *dst32 = (uint32 *)dst;
+
+ vsPitch >>= 2;
+ const int textPitch = (_textSurface.pitch - width * m) >> 2;
+ for (int h = height * m; h > 0; --h) {
+ for (int w = width*m; w > 0; w-=4) {
+ uint32 temp = *text32++;
+
+ // Generate a byte mask for those text pixels (bytes) with
+ // value CHARSET_MASK_TRANSPARENCY. In the end, each byte
+ // in mask will be either equal to 0x00 or 0xFF.
+ // Doing it this way avoids branches and bytewise operations,
+ // at the cost of readability ;).
+ uint32 mask = temp ^ CHARSET_MASK_TRANSPARENCY_32;
+ mask = (((mask & 0x7f7f7f7f) + 0x7f7f7f7f) | mask) & 0x80808080;
+ mask = ((mask >> 7) + 0x7f7f7f7f) ^ 0x80808080;
+
+ // The following line is equivalent to this code:
+ // *dst32++ = (*src32++ & mask) | (temp & ~mask);
+ // However, some compilers can generate somewhat better
+ // machine code for this equivalent statement:
+ *dst32++ = ((temp ^ *src32++) & mask) ^ temp;
}
- src += vsPitch;
- text += _textSurface.pitch - width * m;
+ src32 += vsPitch;
+ text32 += textPitch;
}
#endif
src = _compositeBuf;
@@ -1078,7 +1083,7 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h) {
}
}
-#ifdef ARM_USE_GFX_ASM
+#ifdef USE_ARM_GFX_ASM
#define copy8Col(A,B,C,D) asmCopy8Col(A,B,C,D)
@@ -1098,7 +1103,7 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {
} while (--height);
}
-#endif /* ARM_USE_GFX_ASM */
+#endif /* USE_ARM_GFX_ASM */
static void clear8Col(byte *dst, int dstPitch, int height) {
do {
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index e03fdd1c53..e4c1054450 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -174,7 +174,8 @@ struct ColorCycle {
struct StripTable;
-#define CHARSET_MASK_TRANSPARENCY 253
+#define CHARSET_MASK_TRANSPARENCY 0xFD
+#define CHARSET_MASK_TRANSPARENCY_32 0xFDFDFDFD
class Gdi {
protected:
diff --git a/engines/scumm/gfxARM.s b/engines/scumm/gfxARM.s
index 83aaa78927..f3a1f20303 100644
--- a/engines/scumm/gfxARM.s
+++ b/engines/scumm/gfxARM.s
@@ -24,7 +24,7 @@
.global asmDrawStripToScreen
.global asmCopy8Col
-
+
@ ARM implementation of asmDrawStripToScreen.
@
@ C prototype would be:
@@ -47,7 +47,7 @@ asmDrawStripToScreen:
@ r2 = text
@ r3 = src
MOV r12,r13
- STMFD r13!,{r4-r7,r9-r11,R14}
+ STMFD r13!,{r4-r11,R14}
LDMIA r12,{r4,r5,r6,r7}
@ r4 = dst
@ r5 = vsPitch
@@ -69,57 +69,46 @@ asmDrawStripToScreen:
MOV r10,#253
ORR r10,r10,r10,LSL #8
ORR r10,r10,r10,LSL #16 @ r10 = mask
-yLoop:
- MOV r14,r1 @ r14 = width
+ MOV r8,#0x7F
+ ORR r8, r8, r8, LSL #8
+ ORR r8, r8, r8, LSL #16 @ r8 = 7f7f7f7f
+ STR r1,[r13,#-4]! @ Stack width
+ B xLoop
+
+notEntirelyTransparent:
+ AND r14,r9, r8 @ r14 = mask & 7f7f7f7f
+ ADD r14,r14,r8 @ r14 = (mask & 7f7f7f7f)+7f7f7f7f
+ ORR r14,r14,r9 @ r14 |= mask
+ BIC r14,r14,r8 @ r14 &= 80808080
+ ADD r14,r8, r14,LSR #7 @ r14 = (rx>>7) + 7f7f7f7f
+ EOR r14,r14,r8 @ r14 ^= 7f7f7f7f
+ @ So bytes of r14 are 00 where source was matching value,FF otherwise
+ BIC r11,r11,r14
+ AND r12,r12,r14
+ ORR r12,r11,r12
+ STR r12,[r4],#4
+ SUBS r1,r1,#4
+ BLE endXLoop
xLoop:
- LDR r12,[r2],#4 @ r12 = [text]
- LDR r11,[r3],#4 @ r11 = [src]
- CMP r12,r10
- BNE singleByteCompare
- SUBS r14,r14,#4
+ LDR r12,[r2],#4 @ r12 = temp = [text]
+ LDR r11,[r3],#4 @ r11 = [src]
+ @ Stall
+ EORS r9, r12,r10 @ r9 = mask = temp ^ TRANSPARENCY
+ BNE notEntirelyTransparent
+ SUBS r1, r1, #4
STR r11,[r4], #4 @ r4 = [dst]
BGT xLoop
-
+endXLoop:
ADD r2,r2,r7 @ text += textSurfacePitch
ADD r3,r3,r5 @ src += vsPitch
ADD r4,r4,r6 @ dst += vmScreenWidth
SUBS r0,r0,#1
- BGT yLoop
- LDMFD r13!,{r4-r7,r9-r11,PC}
-
-singleByteCompare:
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- STR r12,[r4],#4
- SUBS r14,r14,#4
+ LDRGT r1,[r13] @ r14 = width
BGT xLoop
-
- ADD r2,r2,r7 @ text += textSurfacePitch
- ADD r3,r3,r5 @ src += vsPitch
- ADD r4,r4,r6 @ dst += vmScreenWidth
- SUBS r0,r0,#1
- BGT yLoop
+ ADD r13,r13,#4
end:
- LDMFD r13!,{r4-r7,r9-r11,PC}
-
+ LDMFD r13!,{r4-r11,PC}
+
@ ARM implementation of asmCopy8Col
@
@ C prototype would be:
@@ -156,4 +145,4 @@ roll2:
STR r14,[r0],r1
BNE yLoop2
- LDMFD r13!,{PC}
+ LDMFD r13!,{PC}
diff --git a/engines/scumm/he/cup_player_he.cpp b/engines/scumm/he/cup_player_he.cpp
index e611c85e9d..685bd00065 100644
--- a/engines/scumm/he/cup_player_he.cpp
+++ b/engines/scumm/he/cup_player_he.cpp
@@ -99,7 +99,7 @@ void CUP_Player::play() {
debug(1, "rate %d width %d height %d", _playbackRate, _width, _height);
int ticks = _system->getMillis();
- while (_dataSize != 0 && !_vm->_quit) {
+ while (_dataSize != 0 && !_vm->quit()) {
while (parseNextBlockTag(_fileStream)) {
if (_fileStream.ioFailed()) {
return;
@@ -190,7 +190,7 @@ void CUP_Player::waitForSfxChannel(int channel) {
CUP_SfxChannel *sfxChannel = &_sfxChannels[channel];
debug(1, "waitForSfxChannel %d", channel);
if ((sfxChannel->flags & kSfxFlagLoop) == 0) {
- while (_mixer->isSoundHandleActive(sfxChannel->handle) && !_vm->_quit) {
+ while (_mixer->isSoundHandleActive(sfxChannel->handle) && !_vm->quit()) {
_vm->parseEvents();
_system->delayMillis(10);
}
@@ -496,7 +496,7 @@ void CUP_Player::handleTOIL(Common::SeekableReadStream &dataStream, uint32 dataS
for (int i = 0; i < kSfxChannels; ++i) {
waitForSfxChannel(i);
}
- _vm->_quit = true;
+ _vm->quitGame();
break;
case 7: {
int channelSync = dataStream.readUint32LE();
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index fff8502134..72ba7edb85 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -320,6 +320,8 @@ protected:
virtual bool handleNextCharsetCode(Actor *a, int *c);
virtual int convertMessageToString(const byte *msg, byte *dst, int dstSize);
+ void debugInput(byte *string);
+
/* HE version 72 script opcodes */
void o72_pushDWord();
void o72_getScriptString();
@@ -602,9 +604,12 @@ protected:
const OpcodeEntryV100he *_opcodesV100he;
+ byte _debugInputBuffer[256];
public:
ScummEngine_v100he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v99he(syst, dr) {}
+ virtual void resetScumm();
+
protected:
virtual void setupOpcodes();
virtual void executeOpcode(byte i);
@@ -643,6 +648,7 @@ protected:
void o100_videoOps();
void o100_wait();
void o100_writeFile();
+ void o100_debugInput();
void o100_isResourceLoaded();
void o100_getResourceSize();
void o100_getSpriteGroupInfo();
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index f72701c229..5717d77640 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -29,6 +29,7 @@
#include "scumm/actor.h"
#include "scumm/charset.h"
+#include "scumm/dialogs.h"
#include "scumm/he/animation_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
@@ -256,7 +257,7 @@ void ScummEngine_v100he::setupOpcodes() {
OPCODE(o90_cond),
OPCODE(o90_cos),
/* A8 */
- OPCODE(o6_invalid),
+ OPCODE(o100_debugInput),
OPCODE(o80_getFileSize),
OPCODE(o6_getActorFromXY),
OPCODE(o72_findAllObjects),
@@ -1116,6 +1117,10 @@ void ScummEngine_v100he::o100_resourceRoutines() {
_heResId = pop();
break;
case 128:
+ // TODO: Clear Heap
+ break;
+ case 129:
+ // Dummy case
break;
case 132:
if (_heResType == rtScript && _heResId >= _numGlobalScripts)
@@ -2136,31 +2141,30 @@ void ScummEngine_v100he::o100_systemOps() {
byte string[1024];
byte subOp = fetchScriptByte();
- subOp -= 61;
switch (subOp) {
- case 0:
+ case 61:
restart();
break;
- case 67:
+ case 128:
clearDrawObjectQueue();
break;
- case 71:
+ case 132:
// Confirm shutdown
- shutDown();
+ quitGame();
break;
- case 72:
- shutDown();
+ case 133:
+ quitGame();
break;
- case 73:
+ case 134:
copyScriptString(string, sizeof(string));
debug(0, "Start game (%s)", string);
break;
- case 74:
+ case 135:
copyScriptString(string, sizeof(string));
debug(0, "Start executable (%s)", string);
break;
- case 75:
+ case 136:
restoreBackgroundHE(Common::Rect(_screenWidth, _screenHeight));
updatePalette();
break;
@@ -2342,6 +2346,30 @@ void ScummEngine_v100he::o100_writeFile() {
}
}
+void ScummEngine_v100he::o100_debugInput() {
+ byte subOp = fetchScriptByte();
+
+ switch (subOp) {
+ case 0:
+ copyScriptString(_debugInputBuffer, sizeof(_debugInputBuffer));
+ break;
+ case 26:
+ pop();
+ break;
+ case 27:
+ copyScriptString(_debugInputBuffer, sizeof(_debugInputBuffer));
+ break;
+ case 80:
+ copyScriptString(_debugInputBuffer, sizeof(_debugInputBuffer));
+ break;
+ case 92:
+ debugInput(_debugInputBuffer);
+ break;
+ default:
+ error("o100_debugInput: default case %d", subOp);
+ }
+}
+
void ScummEngine_v100he::o100_isResourceLoaded() {
// Reports percentage of resource loaded by queue
int type;
@@ -2493,65 +2521,64 @@ void ScummEngine_v100he::o100_getWizData() {
int32 x, y;
byte subOp = fetchScriptByte();
- subOp -= 20;
switch (subOp) {
- case 0:
+ case 20:
y = pop();
x = pop();
state = pop();
resId = pop();
push(_wiz->getWizPixelColor(resId, state, x, y, 0));
break;
- case 6:
+ case 26:
resId = pop();
push(_wiz->getWizImageStates(resId));
break;
- case 13:
+ case 33:
y = pop();
x = pop();
state = pop();
resId = pop();
push(_wiz->isWizPixelNonTransparent(resId, state, x, y, 0));
break;
- case 19:
+ case 39:
state = pop();
resId = pop();
_wiz->getWizImageDim(resId, state, w, h);
push(h);
break;
- case 34:
+ case 54:
type = pop();
state = pop();
resId = pop();
push(_wiz->getWizImageData(resId, state, type));
break;
- case 64:
+ case 84:
state = pop();
resId = pop();
_wiz->getWizImageDim(resId, state, w, h);
push(w);
break;
- case 65:
+ case 85:
state = pop();
resId = pop();
_wiz->getWizImageSpot(resId, state, x, y);
push(x);
break;
- case 66:
+ case 86:
state = pop();
resId = pop();
_wiz->getWizImageSpot(resId, state, x, y);
push(y);
break;
- case 111:
+ case 131:
pop();
copyScriptString(filename, sizeof(filename));
pop();
push(0);
debug(0, "o100_getWizData() case 111 unhandled");
break;
- case 112:
+ case 132:
h = pop();
w = pop();
y = pop();
@@ -2896,30 +2923,29 @@ void ScummEngine_v100he::o100_getSpriteInfo() {
void ScummEngine_v100he::o100_getVideoData() {
// Uses Bink video
byte subOp = fetchScriptByte();
- subOp -= 26;
switch (subOp) {
- case 0:
+ case 26:
pop();
push(_moviePlay->getFrameCount());
break;
- case 13:
+ case 39:
pop();
push(_moviePlay->getHeight());
break;
- case 14:
+ case 40:
pop();
push(_moviePlay->getImageNum());
break;
- case 28:
+ case 54:
debug(0, "o100_getVideoData: subOp 28 stub (%d, %d)", pop(), pop());
push(0);
break;
- case 47:
+ case 73:
pop();
push(_moviePlay->getCurFrame());
break;
- case 58:
+ case 84:
pop();
push(_moviePlay->getWidth());
break;
diff --git a/engines/scumm/he/script_v70he.cpp b/engines/scumm/he/script_v70he.cpp
index 3f22c16648..8fcb8b6fe8 100644
--- a/engines/scumm/he/script_v70he.cpp
+++ b/engines/scumm/he/script_v70he.cpp
@@ -546,6 +546,7 @@ void ScummEngine_v70he::o70_resourceRoutines() {
_res->unlock(rtRoomImage, resid);
break;
case 116:
+ // TODO: Clear Heap
break;
case 117: // SO_LOAD_CHARSET
resid = pop();
@@ -634,10 +635,10 @@ void ScummEngine_v70he::o70_systemOps() {
break;
case 160:
// Confirm shutdown
- shutDown();
+ quitGame();
break;
case 244:
- shutDown();
+ quitGame();
break;
case 250:
id = pop();
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 6c3d0023d8..7e31383f4e 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -1485,10 +1485,10 @@ void ScummEngine_v72he::o72_systemOps() {
break;
case 160:
// Confirm shutdown
- shutDown();
+ quitGame();
break;
case 244:
- shutDown();
+ quitGame();
break;
case 251:
copyScriptString(string, sizeof(string));
@@ -1635,13 +1635,10 @@ void ScummEngine_v72he::o72_drawWizImage() {
_wiz->displayWizImage(&wi);
}
-void ScummEngine_v72he::o72_debugInput() {
- byte string[255];
+void ScummEngine_v72he::debugInput(byte* string) {
byte *debugInputString;
- copyScriptString(string, sizeof(string));
-
- DebugInputDialog dialog(this, (char*)string);
+ DebugInputDialog dialog(this, (char *)string);
runDialog(dialog);
while (!dialog.done) {
parseEvents();
@@ -1654,6 +1651,13 @@ void ScummEngine_v72he::o72_debugInput() {
push(readVar(0));
}
+void ScummEngine_v72he::o72_debugInput() {
+ byte string[255];
+
+ copyScriptString(string, sizeof(string));
+ debugInput(string);
+}
+
void ScummEngine_v72he::o72_jumpToScript() {
int args[25];
int script;
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index 37ce17c050..6d15303378 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -395,42 +395,41 @@ void ScummEngine_v90he::o90_wizImageOps() {
int a, b;
int subOp = fetchScriptByte();
- subOp -= 46;
switch (subOp) {
- case -14: // HE99+
+ case 32: // HE99+
_wizParams.processFlags |= kWPFUseDefImgWidth;
_wizParams.resDefImgW = pop();
break;
- case -13: // HE99+
+ case 33: // HE99+
_wizParams.processFlags |= kWPFUseDefImgHeight;
_wizParams.resDefImgH = pop();
break;
- case 0:
+ case 46:
// Dummy case
pop();
break;
- case 1:
+ case 47:
_wizParams.box.bottom = pop();
_wizParams.box.right = pop();
_wizParams.box.top = pop();
_wizParams.box.left = pop();
break;
- case 2:
+ case 48:
_wizParams.processMode = 1;
break;
- case 3:
+ case 49:
_wizParams.processFlags |= kWPFUseFile;
_wizParams.processMode = 3;
copyScriptString(_wizParams.filename, sizeof(_wizParams.filename));
break;
- case 4:
+ case 50:
_wizParams.processFlags |= kWPFUseFile;
_wizParams.processMode = 4;
copyScriptString(_wizParams.filename, sizeof(_wizParams.filename));
_wizParams.fileWriteMode = pop();
break;
- case 5:
+ case 51:
_wizParams.processFlags |= kWPFClipBox | 0x100;
_wizParams.processMode = 2;
_wizParams.box.bottom = pop();
@@ -440,19 +439,19 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.compType = pop();
adjustRect(_wizParams.box);
break;
- case 6:
+ case 52:
_wizParams.processFlags |= kWPFNewState;
_wizParams.img.state = pop();
break;
- case 7:
+ case 53:
_wizParams.processFlags |= kWPFRotate;
_wizParams.angle = pop();
break;
- case 8:
+ case 54:
_wizParams.processFlags |= kWPFNewFlags;
_wizParams.img.flags |= pop();
break;
- case 10:
+ case 56:
_wizParams.img.flags = pop();
_wizParams.img.state = pop();
_wizParams.img.y1 = pop();
@@ -460,7 +459,7 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.img.resNum = pop();
_wiz->displayWizImage(&_wizParams.img);
break;
- case 11:
+ case 57:
_wizParams.img.resNum = pop();
_wizParams.processMode = 0;
_wizParams.processFlags = 0;
@@ -471,18 +470,18 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.spriteId = 0;
_wizParams.spriteGroup = 0;
break;
- case 16: // HE99+
+ case 62: // HE99+
_wizParams.processFlags |= kWPFMaskImg;
_wizParams.sourceImage = pop();
break;
- case 19:
- case 108:
+ case 65:
+ case 154:
_wizParams.processFlags |= kWPFSetPos;
_wizParams.img.y1 = pop();
_wizParams.img.x1 = pop();
break;
- case 20:
- case 203: // HE98+
+ case 66:
+ case 249: // HE98+
b = pop();
a = pop();
_wizParams.processFlags |= kWPFRemapPalette;
@@ -495,7 +494,7 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.remapColor[a] = b;
_wizParams.remapNum++;
break;
- case 21:
+ case 67:
_wizParams.processFlags |= kWPFClipBox;
_wizParams.box.bottom = pop();
_wizParams.box.right = pop();
@@ -503,26 +502,26 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.box.left = pop();
adjustRect(_wizParams.box);
break;
- case 40: // HE99+
+ case 86: // HE99+
_wizParams.processFlags |= kWPFPaletteNum;
_wizParams.img.palette = pop();
break;
- case 46:
+ case 92:
_wizParams.processFlags |= kWPFScaled;
_wizParams.scale = pop();
break;
- case 52:
+ case 98:
_wizParams.processFlags |= kWPFShadow;
_wizParams.img.shadow = pop();
break;
- case 85: // HE99+
+ case 131: // HE99+
_wizParams.processFlags |= 0x1000 | 0x100 | 0x2;
_wizParams.processMode = 7;
_wizParams.polygonId2 = pop();
_wizParams.polygonId1 = pop();
_wizParams.compType = pop();
break;
- case 87: // HE99+
+ case 133: // HE99+
_wizParams.processFlags |= kWPFFillColor | kWPFClipBox2;
_wizParams.processMode = 9;
_wizParams.fillColor = pop();
@@ -531,7 +530,7 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.box2.top = pop();
_wizParams.box2.left = pop();
break;
- case 88: // HE99+
+ case 134: // HE99+
_wizParams.processFlags |= kWPFFillColor | kWPFClipBox2;
_wizParams.processMode = 10;
_wizParams.fillColor = pop();
@@ -540,33 +539,33 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.box2.top = pop();
_wizParams.box2.left = pop();
break;
- case 89: // HE99+
+ case 135: // HE99+
_wizParams.processFlags |= kWPFFillColor | kWPFClipBox2;
_wizParams.processMode = 11;
_wizParams.fillColor = pop();
_wizParams.box2.top = _wizParams.box2.bottom = pop();
_wizParams.box2.left = _wizParams.box2.right = pop();
break;
- case 90: // HE99+
+ case 136: // HE99+
_wizParams.processFlags |= kWPFFillColor | kWPFClipBox2;
_wizParams.processMode = 12;
_wizParams.fillColor = pop();
_wizParams.box2.top = _wizParams.box2.bottom = pop();
_wizParams.box2.left = _wizParams.box2.right = pop();
break;
- case 91: // HE99+
+ case 137: // HE99+
_wizParams.processFlags |= kWPFDstResNum;
_wizParams.dstResNum = pop();
break;
- case 93: // HE99+
+ case 139: // HE99+
_wizParams.processFlags |= kWPFThickLine;
_wizParams.lineUnk1 = pop();
_wizParams.lineUnk2 = pop();
break;
- case 95: // HE99+
+ case 141: // HE99+
_wizParams.processMode = 13;
break;
- case 96: // HE99+
+ case 142: // HE99+
_wizParams.field_239D = pop();
_wizParams.field_2399 = pop();
_wizParams.field_23A5 = pop();
@@ -574,13 +573,13 @@ void ScummEngine_v90he::o90_wizImageOps() {
copyScriptString(_wizParams.string2, sizeof(_wizParams.string2));
_wizParams.processMode = 15;
break;
- case 97: // HE99+
+ case 143: // HE99+
_wizParams.processMode = 16;
_wizParams.field_23AD = pop();
_wizParams.field_23A9 = pop();
copyScriptString(_wizParams.string1, sizeof(_wizParams.string1));
break;
- case 143: // HE99+
+ case 189: // HE99+
_wizParams.processMode = 17;
_wizParams.field_23CD = pop();
_wizParams.field_23C9 = pop();
@@ -591,18 +590,18 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.field_23B5 = pop();
_wizParams.field_23B1 = pop();
break;
- case 150: // HE99+
+ case 196: // HE99+
_wizParams.processMode = 14;
break;
- case 171: // HE99+
+ case 217: // HE99+
_wizParams.processMode = 8;
break;
- case 200:
+ case 246:
_wizParams.processFlags |= kWPFNewFlags | kWPFSetPos | 2;
_wizParams.img.flags |= kWIFIsPolygon;
_wizParams.polygonId1 = _wizParams.img.y1 = _wizParams.img.x1 = pop();
break;
- case 209:
+ case 255:
if (_wizParams.img.resNum)
_wiz->processWizImage(&_wizParams);
break;
@@ -724,10 +723,9 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
int32 x, y;
byte subOp = fetchScriptByte();
- subOp -= 30;
switch (subOp) {
- case 0:
+ case 30:
spriteId = pop();
if (spriteId) {
_sprite->getSpritePosition(spriteId, x, y);
@@ -736,7 +734,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 1:
+ case 31:
spriteId = pop();
if (spriteId) {
_sprite->getSpritePosition(spriteId, x, y);
@@ -745,7 +743,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 2:
+ case 32:
spriteId = pop();
if (spriteId) {
_sprite->getSpriteImageDim(spriteId, x, y);
@@ -754,7 +752,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 3:
+ case 33:
spriteId = pop();
if (spriteId) {
_sprite->getSpriteImageDim(spriteId, x, y);
@@ -763,7 +761,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 4:
+ case 34:
spriteId = pop();
if (spriteId) {
_sprite->getSpriteDist(spriteId, x, y);
@@ -772,7 +770,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 5:
+ case 35:
spriteId = pop();
if (spriteId) {
_sprite->getSpriteDist(spriteId, x, y);
@@ -781,35 +779,35 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 6:
+ case 36:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteImageStateCount(spriteId));
else
push(0);
break;
- case 7:
+ case 37:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteGroup(spriteId));
else
push(0);
break;
- case 8:
+ case 38:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteDisplayX(spriteId));
else
push(0);
break;
- case 9:
+ case 39:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteDisplayY(spriteId));
else
push(0);
break;
- case 12:
+ case 42:
flags = pop();
spriteId = pop();
if (spriteId) {
@@ -836,14 +834,14 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 13:
+ case 43:
spriteId = pop();
if (spriteId)
push(_sprite->getSpritePriority(spriteId));
else
push(0);
break;
- case 15:
+ case 45:
if (_game.heversion == 99) {
flags = getStackList(args, ARRAYSIZE(args));
type = pop();
@@ -864,77 +862,77 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(_sprite->findSpriteWithClassOf(x, y, groupId, 0, 0, 0));
}
break;
- case 22:
+ case 52:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteImageState(spriteId));
else
push(0);
break;
- case 32:
+ case 62:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteSourceImage(spriteId));
else
push(0);
break;
- case 33:
+ case 63:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteImage(spriteId));
else
push(0);
break;
- case 38:
+ case 68:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteFlagEraseType(spriteId));
else
push(1);
break;
- case 52:
+ case 82:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteFlagAutoAnim(spriteId));
else
push(0);
break;
- case 56:
+ case 86:
spriteId = pop();
if (spriteId)
push(_sprite->getSpritePalette(spriteId));
else
push(0);
break;
- case 62:
+ case 92:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteScale(spriteId));
else
push(0);
break;
- case 67:
+ case 97:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteAnimSpeed(spriteId));
else
push(1);
break;
- case 68:
+ case 98:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteShadow(spriteId));
else
push(0);
break;
- case 94:
+ case 124:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteFlagUpdateType(spriteId));
else
push(0);
break;
- case 95:
+ case 125:
flags = getStackList(args, ARRAYSIZE(args));
spriteId = pop();
if (spriteId) {
@@ -943,7 +941,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
push(0);
}
break;
- case 109:
+ case 139:
flags = pop();
spriteId = pop();
if (spriteId)
@@ -951,14 +949,14 @@ void ScummEngine_v90he::o90_getSpriteInfo() {
else
push(0);
break;
- case 110:
+ case 140:
spriteId = pop();
if (spriteId)
push(_sprite->getSpriteMaskImage(spriteId));
else
push(0);
break;
- case 168:
+ case 198:
pop();
spriteId = pop();
if (spriteId)
@@ -978,10 +976,9 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
int n;
byte subOp = fetchScriptByte();
- subOp -= 34;
switch (subOp) {
- case 0:
+ case 34:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -994,7 +991,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
_sprite->setSpriteDist(spriteId, args[0], tmp[1]);
}
break;
- case 1:
+ case 35:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1007,7 +1004,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
_sprite->setSpriteDist(spriteId, tmp[0], args[0]);
}
break;
- case 3:
+ case 37:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1018,7 +1015,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteGroup(spriteId, args[0]);
break;
- case 8:
+ case 42:
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1048,7 +1045,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
break;
}
break;
- case 9:
+ case 43:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1059,7 +1056,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpritePriority(spriteId, args[0]);
break;
- case 10:
+ case 44:
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1071,7 +1068,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->moveSprite(spriteId, args[0], args[1]);
break;
- case 18:
+ case 52:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1082,7 +1079,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteImageState(spriteId, args[0]);
break;
- case 19:
+ case 53:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1093,7 +1090,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteAngle(spriteId, args[0]);
break;
- case 23:
+ case 57:
if (_game.features & GF_HE_985 || _game.heversion >= 99) {
_curMaxSpriteId = pop();
_curSpriteId = pop();
@@ -1105,7 +1102,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
_curMaxSpriteId = _curSpriteId; // to make all functions happy
}
break;
- case 28: // HE99+
+ case 62: // HE99+
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1116,7 +1113,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteSourceImage(spriteId, args[0]);
break;
- case 29:
+ case 63:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1127,7 +1124,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteImage(spriteId, args[0]);
break;
- case 31:
+ case 65:
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1139,7 +1136,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpritePosition(spriteId, args[0], args[1]);
break;
- case 34:
+ case 68:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1150,7 +1147,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteFlagEraseType(spriteId, args[0]);
break;
- case 43:
+ case 77:
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1162,7 +1159,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteDist(spriteId, args[0], args[1]);
break;
- case 48:
+ case 82:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1173,7 +1170,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteFlagAutoAnim(spriteId, args[0]);
break;
- case 52: // HE 98+
+ case 86: // HE 98+
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1184,7 +1181,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpritePalette(spriteId, args[0]);
break;
- case 58: // HE 99+
+ case 92: // HE 99+
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1195,7 +1192,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteScale(spriteId, args[0]);
break;
- case 63: // HE 98+
+ case 97: // HE 98+
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1206,7 +1203,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteAnimSpeed(spriteId, args[0]);
break;
- case 64:
+ case 98:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1217,7 +1214,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteShadow(spriteId, args[0]);
break;
- case 90:
+ case 124:
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1228,7 +1225,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteFlagUpdateType(spriteId, args[0]);
break;
- case 91:
+ case 125:
n = getStackList(args, ARRAYSIZE(args));
if (_curSpriteId != 0 && _curMaxSpriteId != 0 && n != 0) {
int *p = &args[n - 1];
@@ -1251,7 +1248,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
} while (--n);
}
break;
- case 105: // HE 99+
+ case 139: // HE 99+
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1263,7 +1260,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteGeneralProperty(spriteId, args[0], args[1]);
break;
- case 106: // HE 99+
+ case 140: // HE 99+
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1274,10 +1271,10 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteMaskImage(spriteId, args[0]);
break;
- case 124:
+ case 158:
_sprite->resetTables(true);
break;
- case 164:
+ case 198:
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1289,7 +1286,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteUserValue(spriteId, args[0], args[1]);
break;
- case 183:
+ case 217:
if (_curSpriteId > _curMaxSpriteId)
break;
spriteId = _curSpriteId;
@@ -1389,10 +1386,9 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
int type, value1, value2, value3, value4;
byte subOp = fetchScriptByte();
- subOp -= 37;
switch (subOp) {
- case 0:
+ case 37:
type = pop() - 1;
switch (type) {
case 0:
@@ -1455,7 +1451,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
error("o90_setSpriteGroupInfo subOp 0: Unknown case %d", subOp);
}
break;
- case 5:
+ case 42:
type = pop();
value1 = pop();
if (!_curSpriteGroupId)
@@ -1478,14 +1474,14 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
error("o90_setSpriteGroupInfo subOp 5: Unknown case %d", subOp);
}
break;
- case 6:
+ case 43:
value1 = pop();
if (!_curSpriteGroupId)
break;
_sprite->setGroupPriority(_curSpriteGroupId, value1);
break;
- case 7:
+ case 44:
value2 = pop();
value1 = pop();
if (!_curSpriteGroupId)
@@ -1493,17 +1489,17 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
_sprite->moveGroup(_curSpriteGroupId, value1, value2);
break;
- case 20:
+ case 57:
_curSpriteGroupId = pop();
break;
- case 26:
+ case 63:
value1 = pop();
if (!_curSpriteGroupId)
break;
_sprite->setGroupImage(_curSpriteGroupId, value1);
break;
- case 28:
+ case 65:
value2 = pop();
value1 = pop();
if (!_curSpriteGroupId)
@@ -1511,7 +1507,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
_sprite->setGroupPosition(_curSpriteGroupId, value1, value2);
break;
- case 30:
+ case 67:
value4 = pop();
value3 = pop();
value2 = pop();
@@ -1521,13 +1517,13 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
_sprite->setGroupBounds(_curSpriteGroupId, value1, value2, value3, value4);
break;
- case 56:
+ case 93:
if (!_curSpriteGroupId)
break;
_sprite->resetGroupBounds(_curSpriteGroupId);
break;
- case 180:
+ case 217:
if (!_curSpriteGroupId)
break;
@@ -1545,52 +1541,51 @@ void ScummEngine_v90he::o90_getWizData() {
int32 x, y;
byte subOp = fetchScriptByte();
- subOp -= 30;
switch (subOp) {
- case 0:
+ case 30:
state = pop();
resId = pop();
_wiz->getWizImageSpot(resId, state, x, y);
push(x);
break;
- case 1:
+ case 31:
state = pop();
resId = pop();
_wiz->getWizImageSpot(resId, state, x, y);
push(y);
break;
- case 2:
+ case 32:
state = pop();
resId = pop();
_wiz->getWizImageDim(resId, state, w, h);
push(w);
break;
- case 3:
+ case 33:
state = pop();
resId = pop();
_wiz->getWizImageDim(resId, state, w, h);
push(h);
break;
- case 6:
+ case 36:
resId = pop();
push(_wiz->getWizImageStates(resId));
break;
- case 15:
+ case 45:
y = pop();
x = pop();
state = pop();
resId = pop();
push(_wiz->isWizPixelNonTransparent(resId, state, x, y, 0));
break;
- case 36:
+ case 66:
y = pop();
x = pop();
state = pop();
resId = pop();
push(_wiz->getWizPixelColor(resId, state, x, y, 0));
break;
- case 100:
+ case 130:
h = pop();
w = pop();
y = pop();
@@ -1604,12 +1599,12 @@ void ScummEngine_v90he::o90_getWizData() {
}
push(computeWizHistogram(resId, state, x, y, w, h));
break;
- case 109:
+ case 139:
pop();
pop();
push(0);
break;
- case 111:
+ case 141:
pop();
copyScriptString(filename, sizeof(filename));
pop();
@@ -1730,30 +1725,29 @@ void ScummEngine_v90he::o90_videoOps() {
void ScummEngine_v90he::o90_getVideoData() {
// Uses Smacker video
byte subOp = fetchScriptByte();
- subOp -= 32;
switch (subOp) {
- case 0: // Get width
+ case 32: // Get width
pop();
push(_moviePlay->getWidth());
break;
- case 1: // Get height
+ case 33: // Get height
pop();
push(_moviePlay->getHeight());
break;
- case 4: // Get frame count
+ case 36: // Get frame count
pop();
push(_moviePlay->getFrameCount());
break;
- case 20: // Get current frame
+ case 52: // Get current frame
pop();
push(_moviePlay->getCurFrame());
break;
- case 31: // Get image number
+ case 63: // Get image number
pop();
push(_moviePlay->getImageNum());
break;
- case 107: // Get statistics
+ case 139: // Get statistics
debug(0, "o90_getVideoData: subOp 107 stub (%d, %d)", pop(), pop());
push(0);
break;
@@ -1764,33 +1758,32 @@ void ScummEngine_v90he::o90_getVideoData() {
void ScummEngine_v90he::o90_floodFill() {
byte subOp = fetchScriptByte();
- subOp -= 54;
switch (subOp) {
- case 0:
+ case 54:
pop();
break;
- case 3:
+ case 57:
memset(&_floodFillParams, 0, sizeof(_floodFillParams));
_floodFillParams.box.left = 0;
_floodFillParams.box.top = 0;
_floodFillParams.box.right = 639;
_floodFillParams.box.bottom = 479;
break;
- case 11:
+ case 65:
_floodFillParams.y = pop();
_floodFillParams.x = pop();
break;
- case 12:
+ case 66:
_floodFillParams.flags = pop();
break;
- case 13:
+ case 67:
_floodFillParams.box.bottom = pop();
_floodFillParams.box.right = pop();
_floodFillParams.box.top = pop();
_floodFillParams.box.left = pop();
break;
- case 201:
+ case 255:
floodFill(&_floodFillParams, this);
break;
default:
@@ -2336,47 +2329,46 @@ void ScummEngine_v90he::o90_sortArray() {
void ScummEngine_v90he::o90_getObjectData() {
byte subOp = fetchScriptByte();
- subOp -= 32;
switch (subOp) {
- case 0:
+ case 32:
if (_heObjectNum == -1)
push(0);
else
push(_objs[_heObjectNum].width);
break;
- case 1:
+ case 33:
if (_heObjectNum == -1)
push(0);
else
push(_objs[_heObjectNum].height);
break;
- case 4:
+ case 36:
if (_heObjectNum == -1)
push(0);
else
push(getObjectImageCount(_heObject));
break;
- case 6:
+ case 38:
if (_heObjectNum == -1)
push(0);
else
push(_objs[_heObjectNum].x_pos);
break;
- case 7:
+ case 39:
if (_heObjectNum == -1)
push(0);
else
push(_objs[_heObjectNum].y_pos);
break;
- case 20:
+ case 52:
push(getState(_heObject));
break;
- case 25:
+ case 57:
_heObject = pop();
_heObjectNum = getObjectIndex(_heObject);
break;
- case 107:
+ case 139:
// Dummy case
pop();
push(0);
@@ -2391,10 +2383,9 @@ void ScummEngine_v90he::o90_getPaletteData() {
int palSlot, color;
byte subOp = fetchScriptByte();
- subOp -= 45;
switch (subOp) {
- case 0:
+ case 45:
e = pop();
d = pop();
palSlot = pop();
@@ -2403,23 +2394,23 @@ void ScummEngine_v90he::o90_getPaletteData() {
b = pop();
push(getHEPaletteSimilarColor(palSlot, b, c, d, e));
break;
- case 7:
+ case 52:
c = pop();
b = pop();
palSlot = pop();
push(getHEPaletteColorComponent(palSlot, b, c));
break;
- case 21:
+ case 66:
color = pop();
palSlot = pop();
push(getHEPaletteColor(palSlot, color));
break;
- case 87:
+ case 132:
c = pop();
b = pop();
push(getHEPaletteColorComponent(1, b, c));
break;
- case 172:
+ case 217:
pop();
c = pop();
c = MAX(0, c);
@@ -2438,20 +2429,19 @@ void ScummEngine_v90he::o90_paletteOps() {
int a, b, c, d, e;
byte subOp = fetchScriptByte();
- subOp -= 57;
switch (subOp) {
- case 0:
+ case 57:
_hePaletteNum = pop();
break;
- case 6:
+ case 63:
b = pop();
a = pop();
if (_hePaletteNum != 0) {
setHEPaletteFromImage(_hePaletteNum, a, b);
}
break;
- case 9:
+ case 66:
e = pop();
d = pop();
c = pop();
@@ -2463,7 +2453,7 @@ void ScummEngine_v90he::o90_paletteOps() {
}
}
break;
- case 13:
+ case 70:
c = pop();
b = pop();
a = pop();
@@ -2473,31 +2463,31 @@ void ScummEngine_v90he::o90_paletteOps() {
}
}
break;
- case 19: //HE99+
+ case 76: //HE99+
a = pop();
if (_hePaletteNum != 0) {
setHEPaletteFromCostume(_hePaletteNum, a);
}
break;
- case 29:
+ case 86:
a = pop();
if (_hePaletteNum != 0) {
copyHEPalette(_hePaletteNum, a);
}
break;
- case 118:
+ case 175:
b = pop();
a = pop();
if (_hePaletteNum != 0) {
setHEPaletteFromRoom(_hePaletteNum, a, b);
}
break;
- case 160:
+ case 217:
if (_hePaletteNum != 0) {
restoreHEPalette(_hePaletteNum);
}
break;
- case 198:
+ case 255:
_hePaletteNum = 0;
break;
default:
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 35028c7e1c..bb67f2b31d 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -192,10 +192,6 @@ void ScummEngine::parseEvents() {
_keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6'
break;
- case Common::EVENT_QUIT:
- _quit = true;
- break;
-
default:
break;
}
@@ -475,7 +471,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0);
- mainMenuDialog(); // Display NewGui
+ scummMenuDialog(); // Display NewGui
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0);
@@ -514,7 +510,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
vol = Audio::Mixer::kMaxMixerVolume;
ConfMan.setInt("music_volume", vol);
- updateSoundSettings();
+ syncSoundSettings();
} else if (lastKeyHit.ascii == '-' || lastKeyHit.ascii == '+') { // Change text speed
if (lastKeyHit.ascii == '+' && _defaultTalkDelay > 0)
@@ -527,7 +523,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
_defaultTalkDelay = 9 - runDialog(dlg);
// Save the new talkspeed value to ConfMan
- setTalkspeed(_defaultTalkDelay);
+ setTalkDelay(_defaultTalkDelay);
if (VAR_CHARINC != 0xFF)
VAR(VAR_CHARINC) = _defaultTalkDelay;
diff --git a/engines/scumm/insane/insane.cpp b/engines/scumm/insane/insane.cpp
index 1771618822..77a01d54d0 100644
--- a/engines/scumm/insane/insane.cpp
+++ b/engines/scumm/insane/insane.cpp
@@ -39,7 +39,6 @@
#include "scumm/smush/smush_player.h"
#include "scumm/smush/smush_font.h"
-#include "scumm/smush/chunk.h"
#include "scumm/insane/insane.h"
@@ -1310,33 +1309,25 @@ void Insane::smlayer_showStatusMsg(int32 arg_0, byte *renderBitmap, int32 codecp
free (string);
}
-void Insane::procSKIP(Chunk &b) {
+void Insane::procSKIP(int32 subSize, Common::SeekableReadStream &b) {
int16 par1, par2;
_player->_skipNext = false;
if ((_vm->_game.features & GF_DEMO) && (_vm->_game.platform == Common::kPlatformPC)) {
- _player->checkBlock(b, MKID_BE('SKIP'), 2);
+ assert(subSize >= 2);
par1 = b.readUint16LE();
- if (isBitSet(par1))
- _player->_skipNext = true;
- return;
+ par2 = 0;
+ } else {
+ assert(subSize >= 4);
+ par1 = b.readUint16LE();
+ par2 = b.readUint16LE();
}
- _player->checkBlock(b, MKID_BE('SKIP'), 4);
-
- par1 = b.readUint16LE();
- par2 = b.readUint16LE();
-
-
if (!par2) {
if (isBitSet(par1))
_player->_skipNext = true;
- return;
- }
-
- if (isBitSet(par1) != isBitSet(par2)) {
+ } else if (isBitSet(par1) != isBitSet(par2)) {
_player->_skipNext = true;
- return;
}
}
diff --git a/engines/scumm/insane/insane.h b/engines/scumm/insane/insane.h
index 28eafb6f73..50d8d057cf 100644
--- a/engines/scumm/insane/insane.h
+++ b/engines/scumm/insane/insane.h
@@ -31,7 +31,6 @@
#include "scumm/nut_renderer.h"
#include "scumm/smush/smush_player.h"
-#include "scumm/smush/chunk.h"
namespace Scumm {
@@ -67,9 +66,9 @@ class Insane {
void procPostRendering(byte *renderBitmap, int32 codecparam, int32 setupsan12,
int32 setupsan13, int32 curFrame, int32 maxFrame);
void procIACT(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags, int16 par1,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags, int16 par1,
int16 par2, int16 par3, int16 par4);
- void procSKIP(Chunk &b);
+ void procSKIP(int32 subSize, Common::SeekableReadStream &b);
void escapeKeyHandler(void);
private:
@@ -434,22 +433,22 @@ class Insane {
void ouchSoundEnemy(void);
bool weaponEnemyIsEffective(void);
void iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4);
void iactScene3(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 command, int16 par1, int16, int16);
void iactScene4(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4);
void iactScene6(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4);
void iactScene17(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4);
void iactScene21(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4);
bool isBitSet(int n);
void setBit(int n);
diff --git a/engines/scumm/insane/insane_iact.cpp b/engines/scumm/insane/insane_iact.cpp
index c7f0c7220b..b6ce1091e8 100644
--- a/engines/scumm/insane/insane_iact.cpp
+++ b/engines/scumm/insane/insane_iact.cpp
@@ -30,14 +30,13 @@
#include "scumm/scumm.h"
#include "scumm/smush/smush_player.h"
-#include "scumm/smush/chunk.h"
#include "scumm/insane/insane.h"
namespace Scumm {
void Insane::procIACT(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
if (_keyboardDisable)
return;
@@ -67,7 +66,7 @@ void Insane::procIACT(byte *renderBitmap, int32 codecparam, int32 setupsan12,
}
void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ 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;
@@ -294,7 +293,7 @@ void Insane::removeEnemyFromMetList(int32 enemy1) {
}
void Insane::iactScene3(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 command, int16 par1, int16, int16) {
int par2, par3;
if (command == 6) {
@@ -317,7 +316,7 @@ void Insane::iactScene3(byte *renderBitmap, int32 codecparam, int32 setupsan12,
}
void Insane::iactScene4(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
int16 par5;
@@ -393,7 +392,7 @@ void Insane::iactScene4(byte *renderBitmap, int32 codecparam, int32 setupsan12,
}
void Insane::iactScene6(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
int16 par5;
@@ -478,7 +477,7 @@ void Insane::iactScene6(byte *renderBitmap, int32 codecparam, int32 setupsan12,
}
void Insane::iactScene17(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
switch (par1) {
case 2:
@@ -524,7 +523,7 @@ void Insane::iactScene17(byte *renderBitmap, int32 codecparam, int32 setupsan12,
}
void Insane::iactScene21(byte *renderBitmap, int32 codecparam, int32 setupsan12,
- int32 setupsan13, Chunk &b, int32 size, int32 flags,
+ int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
// void implementation
}
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 7d52a02116..8d6a5453df 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -53,7 +53,6 @@ MODULE_OBJS := \
scumm.o \
sound.o \
string.o \
- thumbnail.o \
usage_bits.o \
util.o \
vars.o \
@@ -82,7 +81,6 @@ MODULE_OBJS += \
insane/insane_scenes.o \
insane/insane_iact.o \
smush/channel.o \
- smush/chunk.o \
smush/codec1.o \
smush/codec37.o \
smush/codec47.o \
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 6bd62c1761..50e0d221ca 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -226,7 +226,7 @@ void ScummEngine::askForDisk(const char *filename, int disknum) {
#ifdef MACOSX
sprintf(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nPress OK to retry, Quit to exit", filename, disknum);
#else
- sprintf(buf, "Cannot find file: '%s'\nInsert disc %d into drive %s\nPress OK to retry, Quit to exit", filename, disknum, _gameDataPath.c_str());
+ sprintf(buf, "Cannot find file: '%s'\nInsert disc %d into drive %s\nPress OK to retry, Quit to exit", filename, disknum, _gameDataDir.getPath().c_str());
#endif
result = displayMessage("Quit", buf);
@@ -253,7 +253,7 @@ void ScummEngine::readIndexFile() {
if (_game.version <= 5) {
// Figure out the sizes of various resources
- while (!_fileHandle->eof()) {
+ while (!_fileHandle->eos()) {
blocktype = _fileHandle->readUint32BE();
itemsize = _fileHandle->readUint32BE();
if (_fileHandle->ioFailed())
@@ -291,7 +291,7 @@ void ScummEngine::readIndexFile() {
if (checkTryMedia(_fileHandle)) {
displayMessage(NULL, "You're trying to run game encrypted by ActiveMark. This is not supported.");
- _quit = true;
+ quitGame();
return;
}
@@ -809,7 +809,7 @@ byte *ResourceManager::createResource(int type, int idx, uint32 size) {
ptr = (byte *)calloc(size + sizeof(MemBlkHeader) + SAFETY_AREA, 1);
if (ptr == NULL) {
- error("Out of memory while allocating %d", size);
+ error("createResource(%s,%d): Out of memory while allocating %d", resTypeFromId(type), idx, size);
}
_allocatedSize += size;
diff --git a/engines/scumm/resource_v4.cpp b/engines/scumm/resource_v4.cpp
index 0ced00e254..29d7c5d25d 100644
--- a/engines/scumm/resource_v4.cpp
+++ b/engines/scumm/resource_v4.cpp
@@ -62,7 +62,7 @@ void ScummEngine_v4::readIndexFile() {
closeRoom();
openRoom(0);
- while (!_fileHandle->eof()) {
+ while (!_fileHandle->eos()) {
// Figure out the sizes of various resources
itemsize = _fileHandle->readUint32LE();
blocktype = _fileHandle->readUint16LE();
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 54dfca9eea..267e06dafd 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -46,6 +46,8 @@
#include "sound/audiocd.h"
#include "sound/mixer.h"
+#include "graphics/thumbnail.h"
+
namespace Scumm {
struct SaveGameHeader {
@@ -71,6 +73,8 @@ struct SaveInfoSection {
#define INFOSECTION_VERSION 2
+#pragma mark -
+
void ScummEngine::requestSave(int slot, const char *name, bool temporary) {
_saveLoadSlot = slot;
_saveTemporaryState = temporary;
@@ -99,34 +103,36 @@ static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) {
}
bool ScummEngine::saveState(int slot, bool compat) {
- char filename[256];
+ Common::String filename;
Common::OutSaveFile *out;
SaveGameHeader hdr;
if (_saveLoadSlot == 255) {
// Allow custom filenames for save game system in HE Games
- memcpy(filename, _saveLoadFileName, sizeof(_saveLoadFileName));
+ filename = _saveLoadFileName;
} else {
- makeSavegameName(filename, slot, compat);
+ filename = makeSavegameName(slot, compat);
}
- if (!(out = _saveFileMan->openForSaving(filename)))
+ if (!(out = _saveFileMan->openForSaving(filename.c_str())))
return false;
memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
saveSaveGameHeader(out, hdr);
- saveThumbnail(out);
+#if !defined(__DS__)
+ Graphics::saveThumbnail(*out);
+#endif
saveInfos(out);
Serializer ser(0, out, CURRENT_VER);
saveOrLoad(&ser);
out->finalize();
- if (out->ioFailed()) {
+ if (out->err()) {
delete out;
- debug(1, "State save as '%s' FAILED", filename);
+ debug(1, "State save as '%s' FAILED", filename.c_str());
return false;
}
delete out;
- debug(1, "State saved as '%s'", filename);
+ debug(1, "State saved as '%s'", filename.c_str());
return true;
}
@@ -135,11 +141,11 @@ 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->ioFailed() && hdr.type == MKID_BE('SCVM');
+ return !in->err() && hdr.type == MKID_BE('SCVM');
}
bool ScummEngine::loadState(int slot, bool compat) {
- char filename[256];
+ Common::String filename;
Common::SeekableReadStream *in;
int i, j;
SaveGameHeader hdr;
@@ -147,15 +153,15 @@ bool ScummEngine::loadState(int slot, bool compat) {
if (_saveLoadSlot == 255) {
// Allow custom filenames for save game system in HE Games
- memcpy(filename, _saveLoadFileName, sizeof(_saveLoadFileName));
+ filename = _saveLoadFileName;
} else {
- makeSavegameName(filename, slot, compat);
+ filename = makeSavegameName(slot, compat);
}
- if (!(in = _saveFileMan->openForLoading(filename)))
+ if (!(in = _saveFileMan->openForLoading(filename.c_str())))
return false;
if (!loadSaveGameHeader(in, hdr)) {
- warning("Invalid savegame '%s'", filename);
+ warning("Invalid savegame '%s'", filename.c_str());
delete in;
return false;
}
@@ -171,30 +177,30 @@ bool ScummEngine::loadState(int slot, bool compat) {
// to work around a bug from the stone age (see below for more
// information).
if (hdr.ver < VER(7) || hdr.ver > CURRENT_VER) {
- warning("Invalid version of '%s'", filename);
+ warning("Invalid version of '%s'", filename.c_str());
delete in;
return false;
}
// We (deliberately) broke HE savegame compatibility at some point.
if (hdr.ver < VER(50) && _game.heversion >= 71) {
- warning("Unsupported version of '%s'", filename);
+ warning("Unsupported version of '%s'", filename.c_str());
delete in;
return false;
}
// Since version 52 a thumbnail is saved directly after the header.
if (hdr.ver >= VER(52)) {
- uint32 type = in->readUint32BE();
- // Check for the THMB header. Also, work around a bug which caused
- // the chunk type (incorrectly) to be written in LE on LE machines.
- if (! (type == MKID_BE('THMB') || (hdr.ver < VER(55) && type == MKID_BE('BMHT')))){
- warning("Can not load thumbnail");
- delete in;
- return false;
+ // Prior to version 75 we always required an thumbnail to be present
+ if (hdr.ver <= VER(74)) {
+ if (!Graphics::checkThumbnailHeader(*in)) {
+ warning("Can not load thumbnail");
+ delete in;
+ return false;
+ }
}
- uint32 size = in->readUint32BE();
- in->skip(size - 8);
+
+ Graphics::skipThumbnailHeader(*in);
}
// Since version 56 we save additional information about the creation of
@@ -275,7 +281,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
delete in;
// Update volume settings
- updateSoundSettings();
+ syncSoundSettings();
// Init NES costume data
if (_game.platform == Common::kPlatformNES) {
@@ -385,7 +391,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
if (VAR_VOICE_MODE != 0xFF)
VAR(VAR_VOICE_MODE) = ConfMan.getBool("subtitles");
- debug(1, "State loaded from '%s'", filename);
+ debug(1, "State loaded from '%s'", filename.c_str());
_sound->pauseSounds(false);
@@ -401,23 +407,24 @@ bool ScummEngine::loadState(int slot, bool compat) {
return true;
}
-void ScummEngine::makeSavegameName(char *out, int slot, bool temporary) {
- sprintf(out, "%s.%c%.2d", _targetName.c_str(), temporary ? 'c' : 's', slot);
+Common::String ScummEngine::makeSavegameName(const Common::String &target, int slot, bool temporary) {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".%c%02d", temporary ? 'c' : 's', slot);
+ return (target + extension);
}
void ScummEngine::listSavegames(bool *marks, int num) {
assert(marks);
- char prefix[256];
char slot[3];
int slotNum;
Common::StringList files;
- makeSavegameName(prefix, 99, false);
- prefix[strlen(prefix)-2] = '*';
- prefix[strlen(prefix)-1] = 0;
+ Common::String prefix = makeSavegameName(99, false);
+ prefix.setChar('*', prefix.size()-2);
+ prefix.setChar(0, prefix.size()-1);
memset(marks, false, num * sizeof(bool)); //assume no savegames for this title
- files = _saveFileMan->listSavefiles(prefix);
+ files = _saveFileMan->listSavefiles(prefix.c_str());
for (Common::StringList::const_iterator file = files.begin(); file != files.end(); ++file) {
//Obtain the last 2 digits of the filename, since they correspond to the save slot
@@ -436,11 +443,10 @@ bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion
bool ScummEngine::getSavegameName(int slot, Common::String &desc) {
Common::InSaveFile *in = 0;
bool result = false;
- char filename[256];
desc.clear();
- makeSavegameName(filename, slot, false);
- in = _saveFileMan->openForLoading(filename);
+ Common::String filename = makeSavegameName(slot, false);
+ in = _saveFileMan->openForLoading(filename.c_str());
if (in) {
result = Scumm::getSavegameName(in, desc, _game.heversion);
delete in;
@@ -474,16 +480,15 @@ bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion
return true;
}
-Graphics::Surface *ScummEngine::loadThumbnailFromSlot(int slot) {
- char filename[256];
+Graphics::Surface *ScummEngine::loadThumbnailFromSlot(const char *target, int slot) {
Common::SeekableReadStream *in;
SaveGameHeader hdr;
if (slot < 0)
return 0;
- makeSavegameName(filename, slot, false);
- if (!(in = _saveFileMan->openForLoading(filename))) {
+ Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
+ if (!(in = g_system->getSavefileManager()->openForLoading(filename.c_str()))) {
return 0;
}
@@ -499,22 +504,29 @@ Graphics::Surface *ScummEngine::loadThumbnailFromSlot(int slot) {
return 0;
}
- Graphics::Surface *thumb = loadThumbnail(in);
+ Graphics::Surface *thumb = 0;
+ if (Graphics::checkThumbnailHeader(*in)) {
+ thumb = new Graphics::Surface();
+ assert(thumb);
+ if (!Graphics::loadThumbnail(*in, *thumb)) {
+ delete thumb;
+ thumb = 0;
+ }
+ }
delete in;
return thumb;
}
-bool ScummEngine::loadInfosFromSlot(int slot, InfoStuff *stuff) {
- char filename[256];
+bool ScummEngine::loadInfosFromSlot(const char *target, int slot, InfoStuff *stuff) {
Common::SeekableReadStream *in;
SaveGameHeader hdr;
if (slot < 0)
return 0;
- makeSavegameName(filename, slot, false);
- if (!(in = _saveFileMan->openForLoading(filename))) {
+ Common::String filename = makeSavegameName(target, slot, false);
+ if (!(in = g_system->getSavefileManager()->openForLoading(filename.c_str()))) {
return false;
}
@@ -530,16 +542,8 @@ bool ScummEngine::loadInfosFromSlot(int slot, InfoStuff *stuff) {
return false;
}
- uint32 type = in->readUint32BE();
-
- // Check for the THMB header. Also, work around a bug which caused
- // the chunk type (incorrectly) to be written in LE on LE machines.
- if (! (type == MKID_BE('THMB') || (hdr.ver < VER(55) && type == MKID_BE('BMHT')))){
- delete in;
+ if (!Graphics::skipThumbnailHeader(*in))
return false;
- }
- uint32 size = in->readUint32BE();
- in->skip(size - 8);
if (!loadInfos(in, stuff)) {
delete in;
@@ -594,9 +598,8 @@ bool ScummEngine::loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff)
stuff->playtime = section.playtime;
// Skip over the remaining (unsupported) data
- if (section.size > SaveInfoSectionSize) {
+ if (section.size > SaveInfoSectionSize)
file->skip(section.size - SaveInfoSectionSize);
- }
return true;
}
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 2d7ee64680..4f9899f961 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -50,7 +50,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 74
+#define CURRENT_VER 75
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index c727b59c64..642627d649 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -625,10 +625,10 @@ void ScummEngine::writeVar(uint var, int value) {
if (var == VAR_CHARINC) {
if (ConfMan.hasKey("talkspeed")) {
- value = getTalkspeed();
+ value = getTalkDelay();
} else {
// Save the new talkspeed value to ConfMan
- setTalkspeed(value);
+ setTalkDelay(value);
}
}
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 3cbb2b8266..c5c055249e 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -1769,7 +1769,7 @@ void ScummEngine_v5::o5_systemOps() {
pauseGame();
break;
case 3: // SO_QUIT
- shutDown();
+ quitGame();
break;
default:
error("o5_systemOps: unknown subopcode %d", subOp);
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index b9a00e6d38..c8534396db 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -2310,7 +2310,7 @@ void ScummEngine_v6::o6_systemOps() {
pauseGame();
break;
case 160: // SO_QUIT
- shutDown();
+ quitGame();
break;
default:
error("o6_systemOps invalid case %d", subOp);
@@ -2374,7 +2374,7 @@ void ScummEngine_v6::o6_printEgo() {
void ScummEngine_v6::o6_talkActor() {
int offset = _scriptPointer - _scriptOrgPointer;
- // WORKAROUNDfor bug #896489: see below for detailed description
+ // WORKAROUND for bug #896489: see below for detailed description
if (_forcedWaitForMessage) {
if (VAR(VAR_HAVE_MSG)) {
_scriptPointer--;
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index 08629afb07..8859435dc9 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -424,10 +424,10 @@ void ScummEngine_v8::writeVar(uint var, int value) {
if (var == VAR_CHARINC) {
if (ConfMan.hasKey("talkspeed")) {
- value = getTalkspeed();
+ value = getTalkDelay();
} else {
// Save the new talkspeed value to ConfMan
- setTalkspeed(value);
+ setTalkDelay(value);
}
}
@@ -1170,7 +1170,7 @@ void ScummEngine_v8::o8_systemOps() {
restart();
break;
case 0x29: // SO_SYSTEM_QUIT Quit game
- shutDown();
+ quitGame();
break;
default:
error("o8_systemOps: invalid case 0x%x", subOp);
@@ -1289,7 +1289,7 @@ void ScummEngine_v8::o8_kernelSetFunctions() {
if (ConfMan.getBool("confirm_exit"))
confirmExitDialog();
else
- _quit = true;
+ quitGame();
break;
case 108: // buildPaletteShadow
setShadowPalette(args[1], args[2], args[3], args[4], args[5], args[6]);
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index ce8f0a4d9a..9c076ddfc8 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Mon Jul 28 00:13:01 2008
+ This file was generated by the md5table tool on Sat Sep 06 07:02:46 2008
DO NOT EDIT MANUALLY!
*/
@@ -54,6 +54,7 @@ static const MD5Table md5table[] = {
{ "0f5935bd5e88ba6f09e558d64459746d", "thinker1", "", "Demo", 30919, Common::EN_USA, Common::kPlatformWindows },
{ "0f6f2e716ba896a44e5059bba1de7ca9", "samnmax", "", "CD", -1, Common::IT_ITA, Common::kPlatformUnknown },
{ "0f9c7a76657f0840b8f7ccb5bffeb9f4", "indy3", "No Adlib", "EGA", -1, Common::FR_FRA, Common::kPlatformAtariST },
+ { "0f9d3317910ac7a9f449243118884ada", "puttzoo", "", "", 42070, Common::DE_DEU, Common::kPlatformWindows },
{ "0fb73eddfcf584c02ba097984df131ba", "samnmax", "", "CD", 9080, Common::DE_DEU, Common::kPlatformUnknown },
{ "1005456bfe351c1b679e1ff2dc2849e9", "puttzoo", "", "", -1, Common::UNK_LANG, Common::kPlatformWindows },
{ "100b4c8403ad6a83d4bf7dbf83e44dc4", "spyfox", "", "", -1, Common::FR_FRA, Common::kPlatformWindows },
@@ -63,6 +64,7 @@ static const MD5Table md5table[] = {
{ "11e6e244078ff09b0f3832e35420e0a7", "catalog", "", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "132bff65e6367c09cc69318ce1b59333", "monkey2", "", "", 11155, Common::EN_ANY, Common::kPlatformAmiga },
{ "1387d16aa620dc1c2d1fd87f8a9e7a09", "puttcircus", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
+ { "13d2a86a7290813a1c386490447d72db", "fbear", "HE 61", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "145bd3373574feb668cc2eea2ec6cf86", "balloon", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "14d48c95b43ddeb983254cf6c43851f1", "freddi4", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "151071053a1d0021198216713939521d", "freddi2", "HE 80", "", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -98,6 +100,7 @@ static const MD5Table md5table[] = {
{ "1ff5997c78fbd0a841a75ef15a05d9d5", "BluesBirthday", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "2012f854d83d9cc6f73b2b544cd8bbf8", "water", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "20176076d708bf14407bcc9bdcd7a418", "pajama3", "", "", -1, Common::RU_RUS, Common::kPlatformWindows },
+ { "204453e33456c4faa26e276229fe5b76", "spyfox2", "", "Demo", 14689, Common::DE_DEU, Common::kPlatformWindows },
{ "20da6fce37805423966aaa8f3c2426aa", "atlantis", "", "Floppy", -1, Common::FR_FRA, Common::kPlatformAmiga },
{ "2108d83dcf09f8adb4bc524669c8cf51", "PuttTime", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "21a6592322f92550f144f68a8a4e685e", "dig", "", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
@@ -106,6 +109,7 @@ static const MD5Table md5table[] = {
{ "225e18566e810c634bf7de63e7568e3e", "mustard", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "22c9eb04455440131ffc157aeb8d40a8", "fbear", "HE 70", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "22d07d6c386c9c25aca5dac2a0c0d94b", "maniac", "NES", "", 262144, Common::SE_SWE, Common::kPlatformNES },
+ { "22de86b2f7ec6e5db745ed1123310b44", "spyfox2", "", "Demo", 15832, Common::FR_FRA, Common::kPlatformWindows },
{ "22f4ea88a09da12df9308ba30bcb7d0f", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformPC },
{ "23394c8d29cc63c61313959431a12476", "spyfox", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "257f8c14d8c584f7ddd601bcb00920c7", "maniac", "NES", "", 262144, Common::DE_DEU, Common::kPlatformNES },
@@ -144,6 +148,7 @@ static const MD5Table md5table[] = {
{ "362c1d281fb9899254cda66ad246c66a", "dig", "Demo", "Demo", 3472, Common::EN_ANY, Common::kPlatformUnknown },
{ "3686cf8f89e102ececf4366e1d2c8126", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformPC },
{ "36a6750e03fb505fc19fc2bf3e4dbe91", "pajama2", "", "Demo", 58749, Common::EN_ANY, Common::kPlatformUnknown },
+ { "3769b56c9a22f5521d74525ee459f88d", "puttrace", "HE 99", "Demo", 13108, Common::DE_DEU, Common::kPlatformWindows },
{ "37aed3f91c1ef959e0bd265f9b13781f", "pajama", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "37f56ceb13e401a7ac7d9e6b37fecaf7", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformPC },
{ "37ff1b308999c4cca7319edfcc1280a0", "puttputt", "HE 70", "Demo", 8269, Common::EN_ANY, Common::kPlatformWindows },
@@ -201,6 +206,7 @@ static const MD5Table md5table[] = {
{ "4edbf9d03550f7ba01e7f34d69b678dd", "spyfox", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "4f04b321a95d4315ce6d65f8e1dd0368", "maze", "HE 80", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "4f138ac6f9b2ac5a41bc68b2c3296064", "freddi4", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows },
+ { "4f1d6f8b38343dba405472538b5037ed", "fbear", "HE 61", "", 7717, Common::EN_ANY, Common::kPlatformPC },
{ "4f267a901719623de7dde83e47d5b474", "atlantis", "", "Floppy", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "4f580a021eee026f3b4589e17d130d78", "freddi4", "", "", -1, Common::UNK_LANG, Common::kPlatformUnknown },
{ "4fa6870d9bc8c313b65d54b1da5a1891", "pajama", "", "", -1, Common::NL_NLD, Common::kPlatformWindows },
@@ -208,6 +214,7 @@ static const MD5Table md5table[] = {
{ "4fe6a2e8df3c4536b278fdd2fbcb181e", "pajama3", "", "Mini Game", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "5057fb0e99e5aa29df1836329232f101", "freddi2", "HE 80", "", -1, Common::UNK_LANG, Common::kPlatformWindows },
{ "507bb360688dc4180fdf0d7597352a69", "freddi", "HE 73", "", 26402, Common::SE_SWE, Common::kPlatformWindows },
+ { "50b831f11b8c4b83784cf81f4dcc69ea", "spyfox", "HE 100", "", -1, Common::EN_ANY, Common::kPlatformWii },
{ "50fcdc982a25063b78ad46bf389b8e8d", "tentacle", "", "Floppy", -1, Common::IT_ITA, Common::kPlatformPC },
{ "51305e929e330e24a75a0351c8f9975e", "freddi2", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "513f91a9dbe8d5490b39e56a3ac5bbdf", "pajama2", "HE 98.5", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
@@ -221,6 +228,7 @@ static const MD5Table md5table[] = {
{ "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows },
{ "5798972220cd458be2626d54c80f71d7", "atlantis", "", "Floppy", -1, Common::IT_ITA, Common::kPlatformAmiga },
{ "57a17febe2183f521250e55d55b83e60", "PuttTime", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows },
+ { "57a5cfec9ef231a007043cc1917e8988", "freddi", "HE 100", "", -1, Common::EN_ANY, Common::kPlatformWii },
{ "57b0d89af79befe1cabce3bece869e7f", "tentacle", "", "Floppy", -1, Common::DE_DEU, Common::kPlatformPC },
{ "58436e634f4fae1d9973591c2ffa1fcb", "spyfox", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "589601b676c98b1c0c987bc031ab68b3", "chase", "HE 95", "", -1, Common::EN_USA, Common::kPlatformUnknown },
@@ -244,6 +252,7 @@ static const MD5Table md5table[] = {
{ "6269b8fbf51a353e5b501e4ad98cdc67", "arttime", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "6271130f440066830eca9056c1d7926f", "water", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "62b8c16b6db226ba95aaa8be73f9885c", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformAmiga },
+ { "632d2fddb8ba97723fa15334763ae857", "thinker1", "", "", 33270, Common::EN_ANY, Common::kPlatformWindows },
{ "63fdcdc95cdeea00060883aed38e5504", "PuttTime", "HE 85", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "6508fd55530e6915507e1cc37f7f045d", "indy3", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformPC },
{ "65563295c3a06493351870f20a1630cf", "spyozon", "HE CUP", "Preview", 5235008, Common::UNK_LANG, Common::kPlatformUnknown },
@@ -272,6 +281,7 @@ static const MD5Table md5table[] = {
{ "6b27dbcd8d5697d5c918eeca0f68ef6a", "puttrace", "HE CUP", "Preview", 3901484, Common::UNK_LANG, Common::kPlatformUnknown },
{ "6b3ec67da214f558dc5ceaa2acd47453", "indy3", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformPC },
{ "6b5a3fef241e90d4b2e77f1e222773ee", "maniac", "NES", "extracted", -1, Common::SE_SWE, Common::kPlatformNES },
+ { "6bca7a1a96d16e52b8f3c42b50dbdca3", "fbear", "HE 61", "", -1, Common::JA_JPN, Common::kPlatform3DO },
{ "6bf70eee5de3d24d2403e0dd3d267e8a", "spyfox", "", "", 49221, Common::UNK_LANG, Common::kPlatformWindows },
{ "6c2bff0e327f2962e809c2e1a82d7309", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformAmiga },
{ "6d1baa1065ac5f7b210be8ebe4235e49", "freddi", "HE 73", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
@@ -296,14 +306,17 @@ static const MD5Table md5table[] = {
{ "73e5ab7dbb9a8061cc6d25df02dbd1e7", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformPC },
{ "7410a8ba9795020cd42f171c4320659e", "pajama3", "", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "746e88c172a5b7a1ae89ac0ee3ee681a", "freddi", "HE 90", "Updated", -1, Common::RU_RUS, Common::kPlatformWindows },
+ { "74da3494fbe1a7d20213b0afe0954755", "catalog", "HE CUP", "Preview", 10841544, Common::FR_FRA, Common::kPlatformUnknown },
{ "754feb59d3bf86b8a00840df74fd7b26", "freddi3", "", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "75ba23fff4fd63fa446c02864f2a5a4b", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC },
{ "75bff95816b84672b877d22a911ab811", "freddi3", "HE 99", "Updated", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "76b66b43e593ad4d2f1dfb5cc8f19700", "spyfox", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "771bc18ec6f93837b839c992b211904b", "monkey", "Demo", "EGA Demo", -1, Common::DE_DEU, Common::kPlatformPC },
+ { "7766c9487f9d53a8cb0edabda5119c3d", "puttputt", "HE 60", "", 8022, Common::EN_ANY, Common::kPlatformPC },
{ "77f5c9cc0986eb729c1a6b4c8823bbae", "zak", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns },
{ "780e4a0ae2ff17dc296f4a79543b44f8", "puttmoon", "", "", -1, Common::UNK_LANG, Common::kPlatformPC },
{ "782393c5934ecd0b536eaf5fd541bd26", "pajama", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "784b499c98d07260a30952685758636b", "pajama3", "", "Demo", 13911, Common::DE_DEU, Common::kPlatformWindows },
{ "78bd5f036ea35a878b74e4f47941f784", "freddi4", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "78c07ca088526d8d4446a4c2cb501203", "freddi3", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "7974365d3dc0f43a2748c975f91ff042", "monkey2", "", "", -1, Common::ES_ESP, Common::kPlatformPC },
@@ -322,6 +335,7 @@ static const MD5Table md5table[] = {
{ "81bbfa181184cb494e7a81dcfa94fbd9", "maniac", "NES", "", 262144, Common::FR_FRA, Common::kPlatformNES },
{ "8299d9b8a1b0e7b881bae7a9971dc5e2", "zak", "V2", "Demo", 1916, Common::EN_ANY, Common::kPlatformAtariST },
{ "8368f552b1e3eba559f8d559bcc4cadb", "freddi3", "", "", -1, Common::UNK_LANG, Common::kPlatformUnknown },
+ { "839a658f7d22de00787ebc945348cdb6", "dog", "", "", 19681, Common::DE_DEU, Common::kPlatformWindows },
{ "83cedbe26aa8b58988e984e3d34cac8e", "freddi3", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "84e3c23a49ded8a6f9197735c8eb3de7", "PuttTime", "HE 85", "", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "8539c0ff89868e55a08e652ac44daaae", "water", "HE 98.5", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
@@ -330,6 +344,7 @@ static const MD5Table md5table[] = {
{ "86c9902b7bec1a17926d4dae85beaa45", "airport", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "870d1e3c86bc50846d808d14a36b4e08", "monkey", "VGA", "VGA", -1, Common::ES_ESP, Common::kPlatformAmiga },
{ "8776caed014c321272af407c1502a2df", "monkey", "CD", "", 8955, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "87df3e0074624040407764b7c5e710b9", "pajama", "", "Demo", 18354, Common::NL_NLD, Common::kPlatformWindows },
{ "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC },
{ "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown },
@@ -394,12 +409,14 @@ static const MD5Table md5table[] = {
{ "a0a7dea72003933b8b3f8b99b9f7ddeb", "loom", "No Adlib", "EGA", -1, Common::EN_ANY, Common::kPlatformAtariST },
{ "a194f15f51ee62badab74b9e7da97693", "baseball2001", "", "Demo", 20507, Common::EN_ANY, Common::kPlatformUnknown },
{ "a197a87ae77f3b3333f09a7a2c448fe2", "freddi", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "a2386da005672cbd5136f4f27a626c5f", "farm", "", "", 87061, Common::NL_NLD, Common::kPlatformWindows },
{ "a28135a7ade38cc0208b04507c46efd1", "spyfox", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "a2bb6aa0537402c1b3c2ea899ccef64b", "lost", "HE 99", "Demo", 15540, Common::EN_ANY, Common::kPlatformWindows },
{ "a3036878840720fbefa41e6965fa4a0a", "samnmax", "", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC },
{ "a525c1753c1db5011c00417da37887ef", "PuttTime", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "a561d2e2413cc1c71d5a1bf87bf493ea", "lost", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "a570381b028972d891052ee1e51dc011", "maniac", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAtariST },
+ { "a5c5388da9bf0e6662fdca8813a79d13", "farm", "", "", 86962, Common::EN_ANY, Common::kPlatformWindows },
{ "a654fb60c3b67d6317a7894ffd9f25c5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "a7cacad9c40c4dc9e1812abf6c8af9d5", "puttcircus", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "a85856675429fe88051744f755b72f93", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -429,10 +446,13 @@ static const MD5Table md5table[] = {
{ "b886b0a5d909c7158a914e1d7c1c6c65", "loom", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformPC },
{ "b8955d7d23b4972229060d1592489fef", "freddicove", "HE 100", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "b9ba19ce376efc69be78ef3baef8d2b9", "monkey", "CD", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "b9bb68c5d2c9b6e2d9c513a29a754a57", "puttmoon", "", "", 7828, Common::EN_ANY, Common::kPlatformPC },
{ "ba888e6831517597859e91aa173f945c", "spyfox", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown },
+ { "bab0fb81dcb12b8930c5d850b8f2a7de", "balloon", "HE 80", "", 12800, Common::DE_DEU, Common::kPlatformWindows },
{ "bbadf7309c4a2c2763e4bbba3c3be634", "freddi3", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "bc4700bc0e12879f6d25d14d6be6cfdd", "spyfox2", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "bd126753de619a495f9f22adc951c8d5", "monkey2", "", "", -1, Common::IT_ITA, Common::kPlatformPC },
+ { "bd5fd7835335dfce03064d5f77b7f0ae", "dog", "", "", 19681, Common::NL_NLD, Common::kPlatformWindows },
{ "be2abe172f58db170de3a037daa1dd27", "puttputt", "HE 61", "", -1, Common::JA_JPN, Common::kPlatform3DO },
{ "be39a5d4db60e8aa736b9086778cb45c", "spyozon", "", "", -1, Common::EN_GRB, Common::kPlatformWindows },
{ "be83e882b44f2767bc08d4f766ebc347", "maniac", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformAtariST },
@@ -441,6 +461,7 @@ static const MD5Table md5table[] = {
{ "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "c0d5c89550381ac433624fedad5e1100", "loom", "PC-Engine", "", -1, Common::JA_JPN, Common::kPlatformPCEngine },
{ "c13225cb1bbd3bc9fe578301696d8021", "monkey", "SEGA", "", -1, Common::EN_ANY, Common::kPlatformSegaCD },
+ { "c225bec1b6c0798a2b8c89ac226dc793", "pajama", "HE 100", "", -1, Common::EN_ANY, Common::kPlatformWii },
{ "c24c490373aeb48fbd54caa8e7ae376d", "loom", "No Adlib", "EGA", -1, Common::DE_DEU, Common::kPlatformAtariST },
{ "c25755b08a8d0d47695e05f1e2111bfc", "freddi4", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "c30ef068add4277104243c31ce46c12b", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformAmiga },
@@ -546,6 +567,7 @@ static const MD5Table md5table[] = {
{ "ed361270102e355afe5236954216aba2", "lost", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "ede149fda3edfc1dbd7347e0737cb583", "tentacle", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "edfdb24a499d92c59f824c52987c0eec", "atlantis", "", "Floppy", -1, Common::FR_FRA, Common::kPlatformPC },
+ { "ee41f6afbc5b26fa475754b56fe92048", "puttputt", "HE 61", "", 8032, Common::JA_JPN, Common::kPlatform3DO },
{ "ee785fe2569bc9965526e774f7ab86f1", "spyfox", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "ef347474f3c7be3b29584eaa133cca05", "samnmax", "", "Floppy", -1, Common::FR_FRA, Common::kPlatformPC },
{ "ef74d9071d4e564b037cb44bd6774de7", "fbear", "HE 61", "", -1, Common::HB_ISR, Common::kPlatformPC },
@@ -566,6 +588,7 @@ static const MD5Table md5table[] = {
{ "f8be685007a8b425ba2a455da732f59f", "pajama2", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "fa127d7c4bb47d05bb1c33ddcaa9f767", "loom", "EGA", "EGA", 5748, Common::DE_DEU, Common::kPlatformPC },
{ "fa30c4a7a806629626269b6dcab59a15", "BluesBirthday", "HE CUP", "Preview", 7819264, Common::UNK_LANG, Common::kPlatformUnknown },
+ { "fa84cb1018103a4ee4e5fa8041c1d0d1", "freddi4", "", "Demo", 13609, Common::DE_DEU, Common::kPlatformWindows },
{ "fb66aa42de21675116346213f176a366", "monkey", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformAmiga },
{ "fbb697d89d2beca87360a145f467bdae", "PuttTime", "HE 90", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "fbbbb38a81fc9d6a61d509278390a290", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2f0593dca8..f87adfd9ac 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -109,7 +109,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_language(dr.language),
_debugger(0),
_currentScript(0xFF), // Let debug() work on init stage
- _pauseDialog(0), _mainMenuDialog(0), _versionDialog(0) {
+ _pauseDialog(0), _scummMenuDialog(0), _versionDialog(0) {
if (_game.platform == Common::kPlatformNES) {
_gdi = new GdiNES(this);
@@ -143,9 +143,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_objs = NULL;
_sound = NULL;
memset(&vm, 0, sizeof(vm));
- _quit = false;
_pauseDialog = NULL;
- _mainMenuDialog = NULL;
+ _scummMenuDialog = NULL;
_versionDialog = NULL;
_fastMode = 0;
_actors = NULL;
@@ -561,7 +560,7 @@ ScummEngine::~ScummEngine() {
delete _2byteFontPtr;
delete _charset;
delete _pauseDialog;
- delete _mainMenuDialog;
+ delete _scummMenuDialog;
delete _versionDialog;
delete _fileHandle;
@@ -815,7 +814,6 @@ ScummEngine_vCUPhe::ScummEngine_vCUPhe(OSystem *syst, const DetectorResult &dr)
_syst = syst;
_game = dr.game;
_filenamePattern = dr.fp,
- _quit = false;
_cupPlayer = new CUP_Player(syst, this, _mixer);
}
@@ -845,14 +843,13 @@ void ScummEngine_vCUPhe::parseEvents() {
Common::Event event;
while (_eventMan->pollEvent(event)) {
+#if 0
switch (event.type) {
- case Common::EVENT_QUIT:
- _quit = true;
- break;
default:
break;
}
+#endif
}
}
@@ -916,20 +913,20 @@ int ScummEngine::init() {
// Add default file directories.
if (((_game.platform == Common::kPlatformAmiga) || (_game.platform == Common::kPlatformAtariST)) && (_game.version <= 4)) {
// This is for the Amiga version of Indy3/Loom/Maniac/Zak
- File::addDefaultDirectory(_gameDataPath + "ROOMS/");
- File::addDefaultDirectory(_gameDataPath + "rooms/");
+ File::addDefaultDirectory(_gameDataDir.getChild("ROOMS"));
+ File::addDefaultDirectory(_gameDataDir.getChild("rooms"));
}
if ((_game.platform == Common::kPlatformMacintosh) && (_game.version == 3)) {
// This is for the Mac version of Indy3/Loom
- File::addDefaultDirectory(_gameDataPath + "Rooms 1/");
- File::addDefaultDirectory(_gameDataPath + "Rooms 2/");
- File::addDefaultDirectory(_gameDataPath + "Rooms 3/");
+ File::addDefaultDirectory(_gameDataDir.getChild("Rooms 1"));
+ File::addDefaultDirectory(_gameDataDir.getChild("Rooms 2"));
+ File::addDefaultDirectory(_gameDataDir.getChild("Rooms 3"));
}
#ifdef ENABLE_SCUMM_7_8
#ifdef MACOSX
- if (_game.version == 8 && !memcmp(_gameDataPath.c_str(), "/Volumes/MONKEY3_", 17)) {
+ if (_game.version == 8 && !memcmp(_gameDataDir.getPath().c_str(), "/Volumes/MONKEY3_", 17)) {
// Special case for COMI on Mac OS X. The mount points on OS X depend
// on the volume name. Hence if playing from CD, we'd get a problem.
// So if loading of a resource file fails, we fall back to the (fixed)
@@ -946,16 +943,16 @@ int ScummEngine::init() {
#endif
if (_game.version == 8) {
// This is for COMI
- File::addDefaultDirectory(_gameDataPath + "RESOURCE/");
- File::addDefaultDirectory(_gameDataPath + "resource/");
+ File::addDefaultDirectory(_gameDataDir.getChild("RESOURCE"));
+ File::addDefaultDirectory(_gameDataDir.getChild("resource"));
}
if (_game.version == 7) {
// This is for Full Throttle & The Dig
- File::addDefaultDirectory(_gameDataPath + "VIDEO/");
- File::addDefaultDirectory(_gameDataPath + "video/");
- File::addDefaultDirectory(_gameDataPath + "DATA/");
- File::addDefaultDirectory(_gameDataPath + "data/");
+ File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
+ File::addDefaultDirectory(_gameDataDir.getChild("video"));
+ File::addDefaultDirectory(_gameDataDir.getChild("DATA"));
+ File::addDefaultDirectory(_gameDataDir.getChild("data"));
}
#endif
@@ -1108,7 +1105,7 @@ int ScummEngine::init() {
if (_game.version >= 5 && _game.version <= 7)
_sound->setupSound();
- updateSoundSettings();
+ syncSoundSettings();
return 0;
}
@@ -1533,6 +1530,12 @@ void ScummEngine_v99he::resetScumm() {
byte *data = defineArray(129, kStringArray, 0, 0, 0, len);
memcpy(data, _filenamePattern.pattern, len);
}
+
+void ScummEngine_v100he::resetScumm() {
+ ScummEngine_v99he::resetScumm();
+
+ memset(_debugInputBuffer, 0, sizeof(_debugInputBuffer));
+}
#endif
void ScummEngine::setupMusic(int midi) {
@@ -1667,7 +1670,7 @@ void ScummEngine::setupMusic(int midi) {
}
}
-void ScummEngine::updateSoundSettings() {
+void ScummEngine::syncSoundSettings() {
// Sync the engine with the config manager
int soundVolumeMusic = ConfMan.getInt("music_volume");
@@ -1690,17 +1693,17 @@ void ScummEngine::updateSoundSettings() {
if (VAR_VOICE_MODE != 0xFF)
VAR(VAR_VOICE_MODE) = _voiceMode;
- _defaultTalkDelay = getTalkspeed();
+ _defaultTalkDelay = getTalkDelay();
if (VAR_CHARINC != 0xFF)
VAR(VAR_CHARINC) = _defaultTalkDelay;
}
-void ScummEngine::setTalkspeed(int talkspeed) {
- ConfMan.setInt("talkspeed", (talkspeed * 255 + 9 / 2) / 9);
+void ScummEngine::setTalkDelay(int talkdelay) {
+ ConfMan.setInt("talkspeed", ((9 - talkdelay) * 255 + 9 / 2) / 9);
}
-int ScummEngine::getTalkspeed() {
- return (ConfMan.getInt("talkspeed") * 9 + 255 / 2) / 255;
+int ScummEngine::getTalkDelay() {
+ return 9 - (ConfMan.getInt("talkspeed") * 9 + 255 / 2) / 255;
}
@@ -1721,7 +1724,7 @@ int ScummEngine::go() {
int diff = 0; // Duration of one loop iteration
- while (!_quit) {
+ while (!quit()) {
if (_debugger->isAttached())
_debugger->onFrame();
@@ -1754,7 +1757,7 @@ int ScummEngine::go() {
diff = _system->getMillis() - diff;
- if (_quit) {
+ if (quit()) {
// TODO: Maybe perform an autosave on exit?
}
}
@@ -1772,7 +1775,7 @@ void ScummEngine::waitForTimer(int msec_delay) {
start_time = _system->getMillis();
- while (!_quit) {
+ while (!quit()) {
_sound->updateCD(); // Loop CD Audio if needed
parseEvents();
_system->updateScreen();
@@ -1895,7 +1898,7 @@ load_game:
checkExecVerbs();
checkAndRunSentenceScript();
- if (_quit)
+ if (quit())
return;
// HACK: If a load was requested, immediately perform it. This avoids
@@ -2011,7 +2014,6 @@ void ScummEngine::scummLoop_handleSaveLoad() {
if (_saveLoadFlag) {
bool success;
const char *errMsg = 0;
- char filename[256];
if (_game.version == 8 && _saveTemporaryState)
VAR(VAR_GAME_LOADED) = 0;
@@ -2032,13 +2034,13 @@ void ScummEngine::scummLoop_handleSaveLoad() {
VAR(VAR_GAME_LOADED) = (_game.version == 8) ? 1 : 203;
}
- makeSavegameName(filename, _saveLoadSlot, _saveTemporaryState);
+ Common::String filename = makeSavegameName(_saveLoadSlot, _saveTemporaryState);
if (!success) {
- displayMessage(0, errMsg, filename);
+ displayMessage(0, errMsg, filename.c_str());
} else if (_saveLoadFlag == 1 && _saveLoadSlot != 0 && !_saveTemporaryState) {
// Display "Save successful" message, except for auto saves
char buf[256];
- snprintf(buf, sizeof(buf), "Successfully saved game state in file:\n\n%s", filename);
+ snprintf(buf, sizeof(buf), "Successfully saved game state in file:\n\n%s", filename.c_str());
GUI::TimedMessageDialog dialog(buf, 1500);
runDialog(dialog);
@@ -2160,10 +2162,6 @@ void ScummEngine::pauseGame() {
pauseDialog();
}
-void ScummEngine::shutDown() {
- _quit = true;
-}
-
void ScummEngine::restart() {
// TODO: Check this function - we should probably be reinitting a lot more stuff, and I suspect
// this leaks memory like a sieve
@@ -2305,18 +2303,18 @@ void ScummEngine::versionDialog() {
runDialog(*_versionDialog);
}
-void ScummEngine::mainMenuDialog() {
- if (!_mainMenuDialog)
- _mainMenuDialog = new MainMenuDialog(this);
- runDialog(*_mainMenuDialog);
- updateSoundSettings();
+void ScummEngine::scummMenuDialog() {
+ if (!_scummMenuDialog)
+ _scummMenuDialog = new ScummMenuDialog(this);
+ runDialog(*_scummMenuDialog);
+ syncSoundSettings();
}
void ScummEngine::confirmExitDialog() {
ConfirmDialog d(this, 6);
if (runDialog(d)) {
- _quit = true;
+ quitGame();
}
}
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 2763331420..27c8943fee 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -462,9 +462,9 @@ protected:
virtual void loadLanguageBundle() {}
void loadCJKFont();
void setupMusic(int midi);
- void updateSoundSettings();
- void setTalkspeed(int talkspeed);
- int getTalkspeed();
+ virtual void syncSoundSettings();
+ void setTalkDelay(int talkdelay);
+ int getTalkDelay();
// Scumm main loop & helper functions.
virtual void scummLoop(int delta);
@@ -496,22 +496,18 @@ protected:
public:
void pauseGame();
void restart();
- void shutDown();
-
- /** We keep running until this is set to true. */
- bool _quit;
protected:
Dialog *_pauseDialog;
Dialog *_versionDialog;
- Dialog *_mainMenuDialog;
+ Dialog *_scummMenuDialog;
virtual int runDialog(Dialog &dialog);
void confirmExitDialog();
void confirmRestartDialog();
void pauseDialog();
void versionDialog();
- void mainMenuDialog();
+ void scummMenuDialog();
char displayMessage(const char *altButton, const char *message, ...);
@@ -618,11 +614,16 @@ protected:
void saveLoadResource(Serializer *ser, int type, int index); // "Obsolete"
void saveResource(Serializer *ser, int type, int index);
void loadResource(Serializer *ser, int type, int index);
- void makeSavegameName(char *out, int slot, bool temporary);
+
+ Common::String makeSavegameName(int slot, bool temporary) const {
+ return makeSavegameName(_targetName, slot, temporary);
+ }
int getKeyState(int key);
public:
+ static Common::String makeSavegameName(const Common::String &target, int slot, bool temporary);
+
bool getSavegameName(int slot, Common::String &desc);
void listSavegames(bool *marks, int num);
@@ -631,14 +632,19 @@ public:
// thumbnail + info stuff
public:
- Graphics::Surface *loadThumbnailFromSlot(int slot);
- bool loadInfosFromSlot(int slot, InfoStuff *stuff);
+ Graphics::Surface *loadThumbnailFromSlot(int slot) {
+ return loadThumbnailFromSlot(_targetName.c_str(), slot);
+ }
+ static Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot);
+
+ bool loadInfosFromSlot(int slot, InfoStuff *stuff) {
+ return loadInfosFromSlot(_targetName.c_str(), slot, stuff);
+ }
+ static bool loadInfosFromSlot(const char *target, int slot, InfoStuff *stuff);
protected:
- Graphics::Surface *loadThumbnail(Common::SeekableReadStream *file);
- bool loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff);
- void saveThumbnail(Common::WriteStream *file);
void saveInfos(Common::WriteStream* file);
+ static bool loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff);
int32 _engineStartTime;
int32 _pauseStartTime;
diff --git a/engines/scumm/smush/channel.h b/engines/scumm/smush/channel.h
index 52fec22e0e..1e023e08ff 100644
--- a/engines/scumm/smush/channel.h
+++ b/engines/scumm/smush/channel.h
@@ -28,10 +28,11 @@
#include "common/util.h"
-namespace Scumm {
+namespace Common {
+ class SeekableReadStream;
+}
-class Chunk;
-class ContChunk;
+namespace Scumm {
class SmushChannel {
protected:
@@ -55,7 +56,7 @@ protected:
public:
SmushChannel(int32 track);
virtual ~SmushChannel();
- virtual bool appendData(Chunk &b, int32 size) = 0;
+ virtual bool appendData(Common::SeekableReadStream &b, int32 size) = 0;
virtual bool setParameters(int32, int32, int32, int32, int32) = 0;
virtual bool checkParameters(int32, int32, int32, int32, int32) = 0;
virtual bool isTerminated() const = 0;
@@ -83,7 +84,7 @@ public:
bool isTerminated() const;
bool setParameters(int32 duration, int32 flags, int32 vol1, int32 vol2, int32 index);
bool checkParameters(int32 index, int32 duration, int32 flags, int32 vol1, int32 vol2);
- bool appendData(Chunk &b, int32 size);
+ bool appendData(Common::SeekableReadStream &b, int32 size);
byte *getSoundData();
int32 getRate() { return 22050; }
bool getParameters(bool &stereo, bool &is_16bit, int32 &vol, int32 &pan) {
@@ -105,7 +106,7 @@ private:
protected:
void decode();
- bool handleMap(Chunk &c);
+ bool handleMap(byte *data);
bool handleSubTags(int32 &offset);
public:
@@ -113,7 +114,7 @@ public:
bool isTerminated() const;
bool setParameters(int32 nbframes, int32 size, int32 track_flags, int32 unk1, int32);
bool checkParameters(int32 index, int32 nbframes, int32 size, int32 track_flags, int32 unk1);
- bool appendData(Chunk &b, int32 size);
+ bool appendData(Common::SeekableReadStream &b, int32 size);
byte *getSoundData();
int32 getRate() { return _rate; }
bool getParameters(bool &stereo, bool &is_16bit, int32 &vol, int32 &pan) {
diff --git a/engines/scumm/smush/chunk.cpp b/engines/scumm/smush/chunk.cpp
deleted file mode 100644
index 5e6f05b3e4..0000000000
--- a/engines/scumm/smush/chunk.cpp
+++ /dev/null
@@ -1,168 +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 "scumm/smush/chunk.h"
-#include "scumm/scumm.h"
-#include "scumm/file.h"
-
-#include "common/file.h"
-#include "common/str.h"
-#include "common/util.h"
-
-namespace Scumm {
-
-BaseChunk::BaseChunk() :
- _type(0),
- _size(0),
- _curPos(0),
- _name("") {
-}
-
-bool BaseChunk::eos() const {
- return _curPos >= _size;
-}
-
-uint32 BaseChunk::pos() const {
- return _curPos;
-}
-
-Chunk::type BaseChunk::getType() const {
- return _type;
-}
-
-uint32 BaseChunk::size() const {
- return _size;
-}
-
-void BaseChunk::seek(int32 delta, int dir) {
- switch (dir) {
- case SEEK_CUR:
- _curPos += delta;
- break;
- case SEEK_SET:
- if (delta < 0)
- error("invalid seek request");
- _curPos = (uint32)delta;
- break;
- case SEEK_END:
- if (delta > 0 || _size < (uint32)-delta)
- error("invalid seek request");
- _curPos = (uint32)(_size + delta);
- break;
- default:
- break;
- }
-
- if (_curPos > _size) {
- // It may happen that user misused our SAN compression tool
- // and ignored FLU index for videos which are used by INSANE.
- // This will lead to incorrect seek requests
- //
- // In fact it may happen only within INSANE, so do not even check for it
- warning("Looks like you compressed file %s in wrong way. It has FLU index which was not updated", _name.c_str());
- error("invalid seek request : %d > %d (delta == %d)", _curPos, _size, delta);
- }
-}
-
-FileChunk::FileChunk(BaseScummFile *data, int offset) {
- _data = data;
- _deleteData = false;
-
- _data->seek(offset, SEEK_SET);
- _type = _data->readUint32BE();
- _size = _data->readUint32BE();
- _offset = _data->pos();
- _curPos = 0;
-}
-
-FileChunk::FileChunk(const Common::String &name, int offset) {
- _data = new ScummFile();
- _deleteData = true;
- if (!g_scumm->openFile(*_data, name))
- error("FileChunk: Unable to open file %s", name.c_str());
-
- _data->seek(offset, SEEK_SET);
- _type = _data->readUint32BE();
- _size = _data->readUint32BE();
- _offset = _data->pos();
- _curPos = 0;
- _name = name;
-}
-
-FileChunk::~FileChunk() {
- if (_deleteData)
- delete _data;
-}
-
-Chunk *FileChunk::subBlock() {
- FileChunk *ptr = new FileChunk(_data, _offset + _curPos);
- skip(sizeof(Chunk::type) + sizeof(uint32) + ptr->size());
- return ptr;
-}
-
-void FileChunk::reseek() {
- _data->seek(_offset + _curPos, SEEK_SET);
-}
-
-uint32 FileChunk::read(void *buffer, uint32 dataSize) {
- if (dataSize <= 0 || (_curPos + dataSize) > _size)
- error("invalid buffer read request");
-
- dataSize = _data->read(buffer, dataSize);
- _curPos += dataSize;
-
- return dataSize;
-}
-
-MemoryChunk::MemoryChunk(byte *data) {
- if (data == 0)
- error("Chunk() called with NULL pointer");
-
- _type = (Chunk::type)READ_BE_UINT32(data);
- _size = READ_BE_UINT32(data + 4);
- _data = data + sizeof(Chunk::type) + sizeof(uint32);
- _curPos = 0;
-}
-
-Chunk *MemoryChunk::subBlock() {
- MemoryChunk *ptr = new MemoryChunk(_data + _curPos);
- skip(sizeof(Chunk::type) + sizeof(uint32) + ptr->size());
- return ptr;
-}
-
-void MemoryChunk::reseek() {
-}
-
-uint32 MemoryChunk::read(void *buffer, uint32 dataSize) {
- if (dataSize <= 0 || (_curPos + dataSize) > _size)
- error("invalid buffer read request");
-
- memcpy(buffer, _data + _curPos, dataSize);
- _curPos += dataSize;
- return dataSize;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp
index 822f32a896..fd34a8f60d 100644
--- a/engines/scumm/smush/imuse_channel.cpp
+++ b/engines/scumm/smush/imuse_channel.cpp
@@ -29,7 +29,6 @@
#include "scumm/scumm.h" // For DEBUG_SMUSH
#include "scumm/util.h"
#include "scumm/smush/channel.h"
-#include "scumm/smush/chunk.h"
namespace Scumm {
@@ -60,10 +59,10 @@ bool ImuseChannel::checkParameters(int32 index, int32 nbframes, int32 size, int3
return true;
}
-bool ImuseChannel::appendData(Chunk &b, int32 size) {
+bool ImuseChannel::appendData(Common::SeekableReadStream &b, int32 size) {
if (_dataSize == -1) {
assert(size > 8);
- Chunk::type imus_type = b.readUint32BE();
+ uint32 imus_type = b.readUint32BE();
/*uint32 imus_size =*/ b.readUint32BE();
if (imus_type != MKID_BE('iMUS'))
error("Invalid Chunk for imuse_channel");
@@ -104,35 +103,45 @@ bool ImuseChannel::appendData(Chunk &b, int32 size) {
return true;
}
-bool ImuseChannel::handleMap(Chunk &map) {
- while (!map.eos()) {
- Chunk *sub = map.subBlock();
- switch (sub->getType()) {
+bool ImuseChannel::handleMap(byte *data) {
+ // Read the chunk size & skip over the chunk header
+ int32 size = READ_BE_UINT32(data + 4);
+ data += 8;
+
+ while (size > 0) {
+ uint32 subType = READ_BE_UINT32(data);
+ int32 subSize = READ_BE_UINT32(data + 4);
+ data += 8;
+ size -= 8;
+
+ switch (subType) {
case MKID_BE('FRMT'):
- if (sub->size() != 20)
+ if (subSize != 20)
error("invalid size for FRMT Chunk");
- /*uint32 imuse_start =*/ sub->readUint32BE();
- sub->skip(4);
- _bitsize = sub->readUint32BE();
- _rate = sub->readUint32BE();
- _channels = sub->readUint32BE();
+ //uint32 imuse_start = READ_BE_UINT32(data);
+ //uint32 unk = READ_BE_UINT32(data+4);
+ _bitsize = READ_BE_UINT32(data+8);
+ _rate = READ_BE_UINT32(data+12);
+ _channels = READ_BE_UINT32(data+16);
assert(_channels == 1 || _channels == 2);
break;
case MKID_BE('TEXT'):
// Ignore this
break;
case MKID_BE('REGN'):
- if (sub->size() != 8)
+ if (subSize != 8)
error("invalid size for REGN Chunk");
break;
case MKID_BE('STOP'):
- if (sub->size() != 4)
+ if (subSize != 4)
error("invalid size for STOP Chunk");
break;
default:
- error("Unknown iMUS subChunk found : %s, %d", tag2str(sub->getType()), sub->size());
+ error("Unknown iMUS subChunk found : %s, %d", tag2str(subType), subSize);
}
- delete sub;
+
+ data += subSize;
+ size -= subSize;
}
return true;
}
@@ -187,15 +196,14 @@ void ImuseChannel::decode() {
bool ImuseChannel::handleSubTags(int32 &offset) {
if (_tbufferSize - offset >= 8) {
- Chunk::type type = READ_BE_UINT32(_tbuffer + offset);
+ uint32 type = READ_BE_UINT32(_tbuffer + offset);
uint32 size = READ_BE_UINT32(_tbuffer + offset + 4);
uint32 available_size = _tbufferSize - offset;
switch (type) {
case MKID_BE('MAP '):
_inData = false;
if (available_size >= (size + 8)) {
- MemoryChunk c((byte *)_tbuffer + offset);
- handleMap(c);
+ handleMap((byte *)_tbuffer + offset);
}
break;
case MKID_BE('DATA'):
diff --git a/engines/scumm/smush/saud_channel.cpp b/engines/scumm/smush/saud_channel.cpp
index 2fe34efe29..a56afa8f44 100644
--- a/engines/scumm/smush/saud_channel.cpp
+++ b/engines/scumm/smush/saud_channel.cpp
@@ -25,10 +25,10 @@
#include "common/endian.h"
+#include "common/stream.h"
#include "scumm/util.h"
#include "scumm/smush/channel.h"
-#include "scumm/smush/chunk.h"
namespace Scumm {
@@ -45,7 +45,7 @@ bool SaudChannel::isTerminated() const {
bool SaudChannel::handleSubTags(int32 &offset) {
if (_tbufferSize - offset >= 8) {
- Chunk::type type = READ_BE_UINT32(_tbuffer + offset);
+ uint32 type = READ_BE_UINT32(_tbuffer + offset);
uint32 size = READ_BE_UINT32(_tbuffer + offset + 4);
uint32 available_size = _tbufferSize - offset;
@@ -53,9 +53,9 @@ bool SaudChannel::handleSubTags(int32 &offset) {
case MKID_BE('STRK'):
_inData = false;
if (available_size >= (size + 8)) {
- MemoryChunk c((byte *)_tbuffer + offset);
- if (c.size() != 14 && c.size() != 10) {
- error("STRK has an invalid size : %d", c.size());
+ int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
+ if (subSize != 14 && subSize != 10) {
+ error("STRK has an invalid size : %d", subSize);
}
} else
return false;
@@ -63,7 +63,9 @@ bool SaudChannel::handleSubTags(int32 &offset) {
case MKID_BE('SMRK'):
_inData = false;
if (available_size >= (size + 8)) {
- MemoryChunk c((byte *)_tbuffer + offset);
+ int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
+ if (subSize != 0)
+ error("SMRK has an invalid size : %d", subSize);
_markReached = true;
} else
return false;
@@ -71,9 +73,9 @@ bool SaudChannel::handleSubTags(int32 &offset) {
case MKID_BE('SHDR'):
_inData = false;
if (available_size >= (size + 8)) {
- MemoryChunk c((byte *)_tbuffer + offset);
- if (c.size() != 4)
- error("SHDR has an invalid size : %d", c.size());
+ int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
+ if (subSize != 4)
+ error("SHDR has an invalid size : %d", subSize);
} else
return false;
break;
@@ -119,10 +121,10 @@ bool SaudChannel::checkParameters(int32 index, int32 nb, int32 flags, int32 volu
return true;
}
-bool SaudChannel::appendData(Chunk &b, int32 size) {
+bool SaudChannel::appendData(Common::SeekableReadStream &b, int32 size) {
if (_dataSize == -1) {
assert(size > 8);
- Chunk::type saud_type = b.readUint32BE();
+ uint32 saud_type = b.readUint32BE();
/*uint32 saud_size =*/ b.readUint32BE();
if (saud_type != MKID_BE('SAUD'))
error("Invalid Chunk for SaudChannel : %X", saud_type);
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index 494357a90c..6b79b7e2c4 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -23,8 +23,6 @@
*
*/
-
-
#include "engines/engine.h"
#include "common/config-manager.h"
@@ -42,7 +40,6 @@
#include "scumm/sound.h"
#include "scumm/util.h"
#include "scumm/smush/channel.h"
-#include "scumm/smush/chunk.h"
#include "scumm/smush/codec37.h"
#include "scumm/smush/codec47.h"
#include "scumm/smush/smush_font.h"
@@ -55,10 +52,6 @@
#include "sound/vorbis.h"
#include "sound/mp3.h"
-#ifdef DUMP_SMUSH_FRAMES
-#include <png.h>
-#endif
-
#include "common/zlib.h"
namespace Scumm {
@@ -212,10 +205,6 @@ static StringResource *getStrings(ScummEngine *vm, const char *file, bool is_enc
void SmushPlayer::timerCallback() {
parseNextFrame();
-#ifdef _WIN32_WCE
- _inTimer = true;
- _inTimerCount++;
-#endif
}
SmushPlayer::SmushPlayer(ScummEngine_v7 *scumm) {
@@ -252,11 +241,6 @@ SmushPlayer::SmushPlayer(ScummEngine_v7 *scumm) {
_paused = false;
_pauseStartTime = 0;
_pauseTime = 0;
-#ifdef _WIN32_WCE
- _inTimer = false;
- _inTimerCount = 0;
- _inTimerCountRedraw = ConfMan.getInt("Smush_force_redraw");
-#endif
}
SmushPlayer::~SmushPlayer() {
@@ -328,16 +312,7 @@ void SmushPlayer::release() {
_codec47 = 0;
}
-void SmushPlayer::checkBlock(const Chunk &b, Chunk::type type_expected, uint32 min_size) {
- if (type_expected != b.getType()) {
- error("Chunk type is different from expected : %x != %x", b.getType(), type_expected);
- }
- if (min_size > b.size()) {
- error("Chunk size is inferior than minimum required size : %d < %d", b.size(), min_size);
- }
-}
-
-void SmushPlayer::handleSoundBuffer(int32 track_id, int32 index, int32 max_frames, int32 flags, int32 vol, int32 pan, Chunk &b, int32 size) {
+void SmushPlayer::handleSoundBuffer(int32 track_id, int32 index, int32 max_frames, int32 flags, int32 vol, int32 pan, Common::SeekableReadStream &b, int32 size) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleSoundBuffer(%d, %d)", track_id, index);
// if ((flags & 128) == 128) {
// return;
@@ -360,8 +335,7 @@ void SmushPlayer::handleSoundBuffer(int32 track_id, int32 index, int32 max_frame
c->appendData(b, size);
}
-void SmushPlayer::handleSoundFrame(Chunk &b) {
- checkBlock(b, MKID_BE('PSAD'));
+void SmushPlayer::handleSoundFrame(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleSoundFrame()");
int32 track_id = b.readUint16LE();
@@ -373,28 +347,28 @@ void SmushPlayer::handleSoundFrame(Chunk &b) {
if (index == 0) {
debugC(DEBUG_SMUSH, "track_id:%d, max_frames:%d, flags:%d, vol:%d, pan:%d", track_id, max_frames, flags, vol, pan);
}
- int32 size = b.size() - 10;
+ int32 size = subSize - 10;
handleSoundBuffer(track_id, index, max_frames, flags, vol, pan, b, size);
}
-void SmushPlayer::handleStore(Chunk &b) {
+void SmushPlayer::handleStore(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleStore()");
- checkBlock(b, MKID_BE('STOR'), 4);
+ assert(subSize >= 4);
_storeFrame = true;
}
-void SmushPlayer::handleFetch(Chunk &b) {
+void SmushPlayer::handleFetch(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleFetch()");
- checkBlock(b, MKID_BE('FTCH'), 6);
+ assert(subSize >= 6);
if (_frameBuffer != NULL) {
memcpy(_dst, _frameBuffer, _width * _height);
}
}
-void SmushPlayer::handleIACT(Chunk &b) {
- checkBlock(b, MKID_BE('IACT'), 8);
+void SmushPlayer::handleIACT(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::IACT()");
+ assert(subSize >= 8);
int code = b.readUint16LE();
int flags = b.readUint16LE();
@@ -415,7 +389,7 @@ void SmushPlayer::handleIACT(Chunk &b) {
int index = b.readUint16LE();
int nbframes = b.readUint16LE();
int32 size = b.readUint32LE();
- int32 bsize = b.size() - 18;
+ int32 bsize = subSize - 18;
if (_vm->_game.id != GID_CMI) {
int32 track = track_id;
@@ -519,7 +493,7 @@ void SmushPlayer::handleIACT(Chunk &b) {
}
}
-void SmushPlayer::handleTextResource(Chunk &b) {
+void SmushPlayer::handleTextResource(uint32 subType, int32 subSize, Common::SeekableReadStream &b) {
int pos_x = b.readSint16LE();
int pos_y = b.readSint16LE();
int flags = b.readSint16LE();
@@ -531,10 +505,10 @@ void SmushPlayer::handleTextResource(Chunk &b) {
const char *str;
char *string = NULL, *string2 = NULL;
- if (b.getType() == MKID_BE('TEXT')) {
- string = (char *)malloc(b.size() - 16);
+ if (subType == MKID_BE('TEXT')) {
+ string = (char *)malloc(subSize - 16);
str = string;
- b.read(string, b.size() - 16);
+ b.read(string, subSize - 16);
} else {
int string_id = b.readUint16LE();
if (!_strings)
@@ -702,7 +676,7 @@ bool SmushPlayer::readString(const char *file) {
return false;
}
-void SmushPlayer::readPalette(byte *out, Chunk &in) {
+void SmushPlayer::readPalette(byte *out, Common::SeekableReadStream &in) {
in.read(out, 0x300);
}
@@ -711,11 +685,10 @@ static byte delta_color(byte org_color, int16 delta_color) {
return CLIP(t, 0, 255);
}
-void SmushPlayer::handleDeltaPalette(Chunk &b) {
- checkBlock(b, MKID_BE('XPAL'));
+void SmushPlayer::handleDeltaPalette(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleDeltaPalette()");
- if (b.size() == 0x300 * 3 + 4) {
+ if (subSize == 0x300 * 3 + 4) {
b.readUint16LE();
b.readUint16LE();
@@ -725,7 +698,7 @@ void SmushPlayer::handleDeltaPalette(Chunk &b) {
}
readPalette(_pal, b);
setDirtyColors(0, 255);
- } else if (b.size() == 6) {
+ } else if (subSize == 6) {
b.readUint16LE();
b.readUint16LE();
@@ -740,9 +713,9 @@ void SmushPlayer::handleDeltaPalette(Chunk &b) {
}
}
-void SmushPlayer::handleNewPalette(Chunk &b) {
- checkBlock(b, MKID_BE('NPAL'), 0x300);
+void SmushPlayer::handleNewPalette(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleNewPalette()");
+ assert(subSize >= 0x300);
if (_skipPalette)
return;
@@ -805,21 +778,20 @@ void SmushPlayer::decodeFrameObject(int codec, const uint8 *src, int left, int t
}
#ifdef USE_ZLIB
-void SmushPlayer::handleZlibFrameObject(Chunk &b) {
+void SmushPlayer::handleZlibFrameObject(int32 subSize, Common::SeekableReadStream &b) {
if (_skipNext) {
_skipNext = false;
return;
}
- int32 chunkSize = b.size();
+ int32 chunkSize = subSize;
byte *chunkBuffer = (byte *)malloc(chunkSize);
assert(chunkBuffer);
b.read(chunkBuffer, chunkSize);
unsigned long decompressedSize = READ_BE_UINT32(chunkBuffer);
byte *fobjBuffer = (byte *)malloc(decompressedSize);
- int result = Common::uncompress(fobjBuffer, &decompressedSize, chunkBuffer + 4, chunkSize - 4);
- if (result != Common::ZLIB_OK)
+ if (!Common::uncompress(fobjBuffer, &decompressedSize, chunkBuffer + 4, chunkSize - 4))
error("SmushPlayer::handleZlibFrameObject() Zlib uncompress error");
free(chunkBuffer);
@@ -836,8 +808,8 @@ void SmushPlayer::handleZlibFrameObject(Chunk &b) {
}
#endif
-void SmushPlayer::handleFrameObject(Chunk &b) {
- checkBlock(b, MKID_BE('FOBJ'), 14);
+void SmushPlayer::handleFrameObject(int32 subSize, Common::SeekableReadStream &b) {
+ assert(subSize >= 14);
if (_skipNext) {
_skipNext = false;
return;
@@ -852,7 +824,7 @@ void SmushPlayer::handleFrameObject(Chunk &b) {
b.readUint16LE();
b.readUint16LE();
- int32 chunk_size = b.size() - 14;
+ int32 chunk_size = subSize - 14;
byte *chunk_buffer = (byte *)malloc(chunk_size);
assert(chunk_buffer);
b.read(chunk_buffer, chunk_size);
@@ -862,8 +834,7 @@ void SmushPlayer::handleFrameObject(Chunk &b) {
free(chunk_buffer);
}
-void SmushPlayer::handleFrame(Chunk &b) {
- checkBlock(b, MKID_BE('FRME'));
+void SmushPlayer::handleFrame(int32 frameSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleFrame(%d)", _frame);
_skipNext = false;
@@ -871,54 +842,57 @@ void SmushPlayer::handleFrame(Chunk &b) {
_vm->_insane->procPreRendering();
}
- while (!b.eos()) {
- Chunk *sub = b.subBlock();
- switch (sub->getType()) {
+ while (frameSize > 0) {
+ const uint32 subType = b.readUint32BE();
+ const int32 subSize = b.readUint32BE();
+ const int32 subOffset = b.pos();
+ switch (subType) {
case MKID_BE('NPAL'):
- handleNewPalette(*sub);
+ handleNewPalette(subSize, b);
break;
case MKID_BE('FOBJ'):
- handleFrameObject(*sub);
+ handleFrameObject(subSize, b);
break;
#ifdef USE_ZLIB
case MKID_BE('ZFOB'):
- handleZlibFrameObject(*sub);
+ handleZlibFrameObject(subSize, b);
break;
#endif
case MKID_BE('PSAD'):
if (!_compressedFileMode)
- handleSoundFrame(*sub);
+ handleSoundFrame(subSize, b);
break;
case MKID_BE('TRES'):
- handleTextResource(*sub);
+ handleTextResource(subType, subSize, b);
break;
case MKID_BE('XPAL'):
- handleDeltaPalette(*sub);
+ handleDeltaPalette(subSize, b);
break;
case MKID_BE('IACT'):
- handleIACT(*sub);
+ handleIACT(subSize, b);
break;
case MKID_BE('STOR'):
- handleStore(*sub);
+ handleStore(subSize, b);
break;
case MKID_BE('FTCH'):
- handleFetch(*sub);
+ handleFetch(subSize, b);
break;
case MKID_BE('SKIP'):
- _vm->_insane->procSKIP(*sub);
+ _vm->_insane->procSKIP(subSize, b);
break;
case MKID_BE('TEXT'):
- handleTextResource(*sub);
+ handleTextResource(subType, subSize, b);
break;
default:
- error("Unknown frame subChunk found : %s, %d", tag2str(sub->getType()), sub->size());
+ error("Unknown frame subChunk found : %s, %d", tag2str(subType), subSize);
}
- b.reseek();
- if (sub->size() & 1)
+ frameSize -= subSize + 8;
+ b.seek(subOffset + subSize, SEEK_SET);
+ if (subSize & 1) {
b.skip(1);
-
- delete sub;
+ frameSize--;
+ }
}
if (_insanity) {
@@ -926,23 +900,16 @@ void SmushPlayer::handleFrame(Chunk &b) {
}
if (_width != 0 && _height != 0) {
-#ifdef _WIN32_WCE
- if (!_inTimer || _inTimerCount == _inTimerCountRedraw) {
- updateScreen();
- _inTimerCount = 0;
- }
-#else
updateScreen();
-#endif
}
_smixer->handleFrame();
_frame++;
}
-void SmushPlayer::handleAnimHeader(Chunk &b) {
- checkBlock(b, MKID_BE('AHDR'), 0x300 + 6);
+void SmushPlayer::handleAnimHeader(int32 subSize, Common::SeekableReadStream &b) {
debugC(DEBUG_SMUSH, "SmushPlayer::handleAnimHeader()");
+ assert(subSize >= 0x300 + 6);
/* _version = */ b.readUint16LE();
_nbframes = b.readUint16LE();
@@ -1004,7 +971,6 @@ SmushFont *SmushPlayer::getFont(int font) {
}
void SmushPlayer::parseNextFrame() {
- Chunk *sub;
if (_seekPos >= 0) {
if (_smixer)
@@ -1012,15 +978,23 @@ void SmushPlayer::parseNextFrame() {
if (_seekFile.size() > 0) {
delete _base;
- _base = new FileChunk(_seekFile);
+
+ ScummFile *tmp = new ScummFile();
+ if (!g_scumm->openFile(*tmp, _seekFile))
+ error("SmushPlayer: Unable to open file %s", _seekFile.c_str());
+ _base = tmp;
+ _base->readUint32BE();
+ _base->readUint32BE();
if (_seekPos > 0) {
assert(_seekPos > 8);
// In this case we need to get palette and number of frames
- sub = _base->subBlock();
- checkBlock(*sub, MKID_BE('AHDR'));
- handleAnimHeader(*sub);
- delete sub;
+ const uint32 subType = _base->readUint32BE();
+ const int32 subSize = _base->readUint32BE();
+ const int32 subOffset = _base->pos();
+ assert(subType == MKID_BE('AHDR'));
+ handleAnimHeader(subSize, *_base);
+ _base->seek(subOffset + subSize, SEEK_SET);
_middleAudio = true;
_seekPos -= 8;
@@ -1034,7 +1008,7 @@ void SmushPlayer::parseNextFrame() {
_skipPalette = true;
}
- _base->seek(_seekPos, SEEK_SET);
+ _base->seek(_seekPos + 8, SEEK_SET);
_frame = _seekFrame;
_startFrame = _frame;
_startTime = _vm->_system->getMillis();
@@ -1049,21 +1023,22 @@ void SmushPlayer::parseNextFrame() {
return;
}
- sub = _base->subBlock();
+ const uint32 subType = _base->readUint32BE();
+ const int32 subSize = _base->readUint32BE();
+ const int32 subOffset = _base->pos();
- switch (sub->getType()) {
+ switch (subType) {
case MKID_BE('AHDR'): // FT INSANE may seek file to the beginning
- handleAnimHeader(*sub);
+ handleAnimHeader(subSize, *_base);
break;
case MKID_BE('FRME'):
- handleFrame(*sub);
+ handleFrame(subSize, *_base);
break;
default:
- error("Unknown Chunk found at %x: %x, %d", _base->pos(), sub->getType(), sub->size());
+ error("Unknown Chunk found at %x: %x, %d", subOffset, subType, subSize);
}
- delete sub;
- _base->reseek();
+ _base->seek(subOffset + subSize, SEEK_SET);
if (_insanity)
_vm->_sound->processSound();
@@ -1098,57 +1073,6 @@ void SmushPlayer::warpMouse(int x, int y, int buttons) {
}
void SmushPlayer::updateScreen() {
-#ifdef DUMP_SMUSH_FRAMES
- char fileName[100];
- // change path below for dump png files
- sprintf(fileName, "/path/to/somethere/%s%04d.png", _vm->getBaseName(), _frame);
- FILE *file = fopen(fileName, "wb");
- if (file == NULL)
- error("can't open file for writing png");
-
- png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- if (png_ptr == NULL) {
- fclose(file);
- error("can't write png header");
- }
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (info_ptr == NULL) {
- fclose(file);
- error("can't create png info struct");
- }
- if (setjmp(png_ptr->jmpbuf)) {
- fclose(file);
- error("png jmpbuf error");
- }
-
- png_init_io(png_ptr, file);
-
- png_set_IHDR(png_ptr, info_ptr, _width, _height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-
- png_colorp palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
- for (int i = 0; i != 256; ++i) {
- (palette + i)->red = _pal[i * 3 + 0];
- (palette + i)->green = _pal[i * 3 + 1];
- (palette + i)->blue = _pal[i * 3 + 2];
- }
-
- png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
-
- png_write_info(png_ptr, info_ptr);
- png_set_flush(png_ptr, 10);
-
- png_bytep row_pointers[480];
- for (int y = 0 ; y < _height ; y++)
- row_pointers[y] = (png_byte *) (_dst + y * _width);
- png_write_image(png_ptr, row_pointers);
- png_write_end(png_ptr, info_ptr);
- png_free(png_ptr, palette);
-
- fclose(file);
- png_destroy_write_struct(&png_ptr, &info_ptr);
-#endif
-
uint32 end_time, start_time = _vm->_system->getMillis();
_updateNeeded = true;
end_time = _vm->_system->getMillis();
@@ -1326,14 +1250,10 @@ void SmushPlayer::play(const char *filename, int32 speed, int32 offset, int32 st
_vm->_system->updateScreen();
_updateNeeded = false;
}
-#ifdef _WIN32_WCE
- _inTimer = false;
- _inTimerCount = 0;
-#endif
}
if (_endOfFile)
break;
- if (_vm->_quit || _vm->_saveLoadFlag || _vm->_smushVideoShouldFinish) {
+ if (_vm->quit() || _vm->_saveLoadFlag || _vm->_smushVideoShouldFinish) {
_smixer->stop();
_vm->_mixer->stopHandle(_compressedFileSoundHandle);
_vm->_mixer->stopHandle(_IACTchannel);
diff --git a/engines/scumm/smush/smush_player.h b/engines/scumm/smush/smush_player.h
index 413a5895d3..2e2996009c 100644
--- a/engines/scumm/smush/smush_player.h
+++ b/engines/scumm/smush/smush_player.h
@@ -27,7 +27,6 @@
#define SCUMM_SMUSH_PLAYER_H
#include "common/util.h"
-#include "scumm/smush/chunk.h"
#include "scumm/sound.h"
namespace Scumm {
@@ -51,7 +50,7 @@ private:
StringResource *_strings;
Codec37Decoder *_codec37;
Codec47Decoder *_codec47;
- FileChunk *_base;
+ Common::SeekableReadStream *_base;
byte *_frameBuffer;
byte *_specialBuffer;
@@ -84,11 +83,6 @@ private:
bool _insanity;
bool _middleAudio;
bool _skipPalette;
-#ifdef _WIN32_WCE
- bool _inTimer;
- int16 _inTimerCount;
- int16 _inTimerCountRedraw;
-#endif
public:
SmushPlayer(ScummEngine_v7 *scumm);
@@ -126,22 +120,21 @@ private:
bool readString(const char *file);
void decodeFrameObject(int codec, const uint8 *src, int left, int top, int width, int height);
- void checkBlock(const Chunk &, Chunk::type, uint32 = 0);
- void handleAnimHeader(Chunk &);
- void handleFrame(Chunk &);
- void handleNewPalette(Chunk &);
+ void handleAnimHeader(int32 subSize, Common::SeekableReadStream &);
+ void handleFrame(int32 frameSize, Common::SeekableReadStream &);
+ void handleNewPalette(int32 subSize, Common::SeekableReadStream &);
#ifdef USE_ZLIB
- void handleZlibFrameObject(Chunk &b);
+ void handleZlibFrameObject(int32 subSize, Common::SeekableReadStream &b);
#endif
- void handleFrameObject(Chunk &);
- void handleSoundBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32);
- void handleSoundFrame(Chunk &);
- void handleStore(Chunk &);
- void handleFetch(Chunk &);
- void handleIACT(Chunk &);
- void handleTextResource(Chunk &);
- void handleDeltaPalette(Chunk &);
- void readPalette(byte *, Chunk &);
+ void handleFrameObject(int32 subSize, Common::SeekableReadStream &);
+ void handleSoundBuffer(int32, int32, int32, int32, int32, int32, Common::SeekableReadStream &, int32);
+ void handleSoundFrame(int32 subSize, Common::SeekableReadStream &);
+ void handleStore(int32 subSize, Common::SeekableReadStream &);
+ void handleFetch(int32 subSize, Common::SeekableReadStream &);
+ void handleIACT(int32 subSize, Common::SeekableReadStream &);
+ void handleTextResource(uint32 subType, int32 subSize, Common::SeekableReadStream &);
+ void handleDeltaPalette(int32 subSize, Common::SeekableReadStream &);
+ void readPalette(byte *, Common::SeekableReadStream &);
void timerCallback();
};
diff --git a/engines/scumm/thumbnail.cpp b/engines/scumm/thumbnail.cpp
deleted file mode 100644
index 40f1ee48e5..0000000000
--- a/engines/scumm/thumbnail.cpp
+++ /dev/null
@@ -1,130 +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 file the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/system.h"
-#include "common/savefile.h"
-#include "graphics/scaler.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-#define THMB_VERSION 1
-
-struct ThumbnailHeader {
- uint32 type;
- uint32 size;
- byte version;
- uint16 width, height;
- byte bpp;
-};
-
-#define ThumbnailHeaderSize (4+4+1+2+2+1)
-
-inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {
- r = (((color >> 11) & 0x1F) << 3);
- g = (((color >> 5) & 0x3F) << 2);
- b = ((color&0x1F) << 3);
-}
-
-Graphics::Surface *ScummEngine::loadThumbnail(Common::SeekableReadStream *file) {
- ThumbnailHeader header;
-
- header.type = file->readUint32BE();
- // 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'))
- return 0;
-
- header.size = file->readUint32BE();
- header.version = file->readByte();
-
- if (header.version > THMB_VERSION) {
- file->skip(header.size - 9);
- warning("Loading a newer thumbnail version");
- return 0;
- }
-
- header.width = file->readUint16BE();
- header.height = file->readUint16BE();
- header.bpp = file->readByte();
-
- // TODO: support other bpp values than 2
- if (header.bpp != 2) {
- file->skip(header.size - 14);
- return 0;
- }
-
- Graphics::Surface *thumb = new Graphics::Surface();
- thumb->create(header.width, header.height, sizeof(OverlayColor));
-
- OverlayColor* pixels = (OverlayColor *)thumb->pixels;
-
- for (int y = 0; y < thumb->h; ++y) {
- for (int x = 0; x < thumb->w; ++x) {
- uint8 r, g, b;
- colorToRGB(file->readUint16BE(), r, g, b);
-
- // converting to current OSystem Color
- *pixels++ = _system->RGBToColor(r, g, b);
- }
- }
-
- return thumb;
-}
-
-void ScummEngine::saveThumbnail(Common::OutSaveFile *file) {
- Graphics::Surface thumb;
-
-#if !defined(__DS__)
- if (!createThumbnailFromScreen(&thumb))
-#endif
- thumb.create(kThumbnailWidth, kThumbnailHeight2, sizeof(uint16));
-
- ThumbnailHeader header;
- header.type = MKID_BE('THMB');
- header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel;
- header.version = THMB_VERSION;
- header.width = thumb.w;
- header.height = thumb.h;
- header.bpp = thumb.bytesPerPixel;
-
- file->writeUint32BE(header.type);
- file->writeUint32BE(header.size);
- file->writeByte(header.version);
- file->writeUint16BE(header.width);
- file->writeUint16BE(header.height);
- file->writeByte(header.bpp);
-
- // TODO: for later this shouldn't be casted to uint16...
- uint16* pixels = (uint16 *)thumb.pixels;
- for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels)
- file->writeUint16BE(*pixels);
-
- thumb.free();
-}
-
-} // end of namespace Scumm
diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp
index 9d6b58704d..8699c893e4 100644
--- a/engines/sky/control.cpp
+++ b/engines/sky/control.cpp
@@ -238,13 +238,17 @@ void Control::removePanel(void) {
free(_sprites.slide2); free(_sprites.slode);
free(_sprites.slode2); free(_sprites.musicBodge);
delete _controlPanel; delete _exitButton;
- delete _slide; delete _slide2;
- delete _slode; delete _restorePanButton;
+ delete _slide; delete _slide2;
+ delete _slode; delete _restorePanButton;
+ delete _savePanel; delete _saveButton;
+ delete _downFastButton; delete _downSlowButton;
+ delete _upFastButton; delete _upSlowButton;
+ delete _quitButton; delete _autoSaveButton;
delete _savePanButton; delete _dosPanButton;
delete _restartPanButton; delete _fxPanButton;
delete _musicPanButton; delete _bodge;
- delete _yesNo; delete _text;
- delete _statusBar; delete _restoreButton;
+ delete _yesNo; delete _text;
+ delete _statusBar; delete _restoreButton;
if (_textSprite) {
free(_textSprite);
@@ -492,7 +496,7 @@ void Control::doControlPanel(void) {
_curButtonText = 0;
uint16 clickRes = 0;
- while (!quitPanel && !SkyEngine::_systemVars.quitGame) {
+ while (!quitPanel && !g_engine->quit()) {
_text->drawToScreen(WITH_MASK);
_system->updateScreen();
_mouseClicked = false;
@@ -524,7 +528,7 @@ void Control::doControlPanel(void) {
}
memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT);
_system->copyRectToScreen(_screenBuf, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, FULL_SCREEN_HEIGHT);
- if (!SkyEngine::_systemVars.quitGame)
+ if (!g_engine->quit())
_system->updateScreen();
_skyScreen->forceRefresh();
_skyScreen->setPaletteEndian((uint8 *)_skyCompact->fetchCpt(SkyEngine::_systemVars.currentPalette));
@@ -603,7 +607,7 @@ uint16 Control::handleClick(ConResource *pButton) {
case QUIT_TO_DOS:
animClick(pButton);
if (getYesNo(quitDos))
- SkyEngine::_systemVars.quitGame = true;
+ g_engine->quitGame();
return 0;
default:
error("Control::handleClick: unknown routine: %X",pButton->_onClick);
@@ -875,7 +879,7 @@ uint16 Control::saveRestorePanel(bool allowSave) {
bool refreshNames = true;
bool refreshAll = true;
uint16 clickRes = 0;
- while (!quitPanel && !SkyEngine::_systemVars.quitGame) {
+ while (!quitPanel && !g_engine->quit()) {
clickRes = 0;
if (refreshNames || refreshAll) {
if (refreshAll) {
@@ -1546,9 +1550,6 @@ void Control::delay(unsigned int amount) {
case Common::EVENT_WHEELDOWN:
_mouseWheel = 1;
break;
- case Common::EVENT_QUIT:
- SkyEngine::_systemVars.quitGame = true;
- break;
default:
break;
}
diff --git a/engines/sky/intro.cpp b/engines/sky/intro.cpp
index 024360561c..86e26309c9 100644
--- a/engines/sky/intro.cpp
+++ b/engines/sky/intro.cpp
@@ -636,14 +636,10 @@ Intro::Intro(Disk *disk, Screen *screen, MusicBase *music, Sound *sound, Text *t
_textBuf = (uint8*)malloc(10000);
_saveBuf = (uint8*)malloc(10000);
_bgBuf = NULL;
- _quitProg = false;
_relDelay = 0;
}
Intro::~Intro(void) {
-
- _mixer->stopAll();
- _skyScreen->stopSequence();
if (_textBuf)
free(_textBuf);
if (_saveBuf)
@@ -912,8 +908,7 @@ bool Intro::escDelay(uint32 msecs) {
if (event.type == Common::EVENT_KEYDOWN) {
if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
return false;
- } else if (event.type == Common::EVENT_QUIT) {
- _quitProg = true;
+ } else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL) {
return false;
}
}
diff --git a/engines/sky/intro.h b/engines/sky/intro.h
index 4a54fb8dd3..796bcf7e36 100644
--- a/engines/sky/intro.h
+++ b/engines/sky/intro.h
@@ -43,7 +43,6 @@ public:
Intro(Disk *disk, Screen *screen, MusicBase *music, Sound *sound, Text *text, Audio::Mixer *mixer, OSystem *system);
~Intro(void);
bool doIntro(bool floppyIntro);
- bool _quitProg;
private:
static uint16 _mainIntroSeq[];
static uint16 _floppyIntroSeq[];
diff --git a/engines/sky/logic.cpp b/engines/sky/logic.cpp
index c6c6c34c4d..9f13bf9bee 100644
--- a/engines/sky/logic.cpp
+++ b/engines/sky/logic.cpp
@@ -2490,7 +2490,7 @@ bool Logic::fnFadeUp(uint32 a, uint32 b, uint32 c) {
}
bool Logic::fnQuitToDos(uint32 a, uint32 b, uint32 c) {
- SkyEngine::_systemVars.quitGame = true;
+ g_engine->quitGame();
return false;
}
diff --git a/engines/sky/mouse.cpp b/engines/sky/mouse.cpp
index b3be8b4f36..1fc9e47539 100644
--- a/engines/sky/mouse.cpp
+++ b/engines/sky/mouse.cpp
@@ -180,7 +180,6 @@ void Mouse::waitMouseNotPressed(int minDelay) {
while (mousePressed || _system->getMillis() < now + minDelay) {
if (eventMan->shouldQuit()) {
- SkyEngine::_systemVars.quitGame = true;
minDelay = 0;
mousePressed = false;
}
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index d87ed06fef..0900ba5617 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -110,9 +110,10 @@ public:
virtual const char *getName() const;
virtual const char *getCopyright() const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual GameList getSupportedGames() const;
virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const FSList &fslist) const;
+ virtual GameList detectGames(const Common::FSList &fslist) const;
virtual PluginError createInstance(OSystem *syst, Engine **engine) const;
@@ -127,6 +128,13 @@ const char *SkyMetaEngine::getCopyright() const {
return "Beneath a Steel Sky (C) Revolution";
}
+bool SkyMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad);
+}
+
GameList SkyMetaEngine::getSupportedGames() const {
GameList games;
games.push_back(skySetting);
@@ -139,7 +147,7 @@ GameDescriptor SkyMetaEngine::findGame(const char *gameid) const {
return GameDescriptor();
}
-GameList SkyMetaEngine::detectGames(const FSList &fslist) const {
+GameList SkyMetaEngine::detectGames(const Common::FSList &fslist) const {
GameList detectedGames;
bool hasSkyDsk = false;
bool hasSkyDnr = false;
@@ -147,7 +155,7 @@ GameList SkyMetaEngine::detectGames(const FSList &fslist) const {
int dataDiskSize = -1;
// Iterate over all files in the given directory
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
const char *fileName = file->getName().c_str();
@@ -257,7 +265,7 @@ namespace Sky {
void *SkyEngine::_itemList[300];
-SystemVars SkyEngine::_systemVars = {0, 0, 0, 0, 4316, 0, 0, false, false, false };
+SystemVars SkyEngine::_systemVars = {0, 0, 0, 0, 4316, 0, 0, false, false };
SkyEngine::SkyEngine(OSystem *syst)
: Engine(syst), _fastMode(0), _debugger(0) {
@@ -277,6 +285,8 @@ SkyEngine::~SkyEngine() {
delete _skyDisk;
delete _skyControl;
delete _skyCompact;
+ if (_skyIntro)
+ delete _skyIntro;
for (int i = 0; i < 300; i++)
if (_itemList[i])
@@ -288,7 +298,6 @@ GUI::Debugger *SkyEngine::getDebugger() {
}
void SkyEngine::initVirgin() {
-
_skyScreen->setPalette(60111);
_skyScreen->showScreen(60110);
}
@@ -340,25 +349,23 @@ void SkyEngine::handleKey(void) {
int SkyEngine::go() {
- _systemVars.quitGame = false;
-
_keyPressed.reset();
uint16 result = 0;
- if (ConfMan.hasKey("save_slot") && ConfMan.getInt("save_slot") >= 0)
- result = _skyControl->quickXRestore(ConfMan.getInt("save_slot"));
+ if (ConfMan.hasKey("save_slot")) {
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0 && saveSlot <= 999)
+ result = _skyControl->quickXRestore(ConfMan.getInt("save_slot"));
+ }
if (result != GAME_RESTORED) {
bool introSkipped = false;
if (_systemVars.gameVersion > 267) { // don't do intro for floppydemos
_skyIntro = new Intro(_skyDisk, _skyScreen, _skyMusic, _skySound, _skyText, _mixer, _system);
introSkipped = !_skyIntro->doIntro(_floppyIntro);
- _systemVars.quitGame = _skyIntro->_quitProg;
-
- delete _skyIntro;
}
- if (!_systemVars.quitGame) {
+ if (!quit()) {
_skyLogic->initScreen0();
if (introSkipped)
_skyControl->restartGame();
@@ -368,7 +375,7 @@ int SkyEngine::go() {
_lastSaveTime = _system->getMillis();
uint32 delayCount = _system->getMillis();
- while (!_systemVars.quitGame) {
+ while (!quit()) {
if (_debugger->isAttached())
_debugger->onFrame();
@@ -440,7 +447,7 @@ int SkyEngine::init() {
_floppyIntro = ConfMan.getBool("alt_intro");
_skyDisk = new Disk();
- _skySound = new Sound(_mixer, _skyDisk, ConfMan.getInt("sfx_volume"));
+ _skySound = new Sound(_mixer, _skyDisk, Audio::Mixer::kMaxChannelVolume);
_systemVars.gameVersion = _skyDisk->determineGameVersion();
@@ -475,6 +482,7 @@ int SkyEngine::init() {
_systemVars.systemFlags |= SF_PLAY_VOCS;
_systemVars.gameSpeed = 50;
+ _skyIntro = 0;
_skyCompact = new SkyCompact();
_skyText = new Text(_skyDisk, _skyCompact);
_skyMouse = new Mouse(_system, _skyDisk, _skyCompact);
@@ -615,9 +623,6 @@ void SkyEngine::delay(int32 amount) {
_skyMouse->mouseMoved(event.mouse.x, event.mouse.y);
_skyMouse->buttonPressed(1);
break;
- case Common::EVENT_QUIT:
- _systemVars.quitGame = true;
- break;
default:
break;
}
diff --git a/engines/sky/sky.h b/engines/sky/sky.h
index b5d1701930..47aebaba77 100644
--- a/engines/sky/sky.h
+++ b/engines/sky/sky.h
@@ -41,7 +41,6 @@ struct SystemVars {
uint16 gameSpeed;
uint16 currentMusic;
bool pastIntro;
- bool quitGame;
bool paused;
};
diff --git a/engines/sky/skydefs.h b/engines/sky/skydefs.h
index f4be91b3d1..f68c0f826b 100644
--- a/engines/sky/skydefs.h
+++ b/engines/sky/skydefs.h
@@ -2023,14 +2023,14 @@ namespace Sky {
#define DISQ_13 26624
#define DISQ_14 28672
#define DISQ_15 30720
-#define T0 0
-#define T1 4096
-#define T2 8192
-#define T3 12288
-#define T4 16384
-#define T5 20480
-#define T6 24576
-#define T7 28672
+//#define T0 0
+//#define T1 4096
+//#define T2 8192
+//#define T3 12288
+//#define T4 16384
+//#define T5 20480
+//#define T6 24576
+//#define T7 28672
#define UP 0
#define DOWN 1
#define LEFT 2
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 2bb027ddb4..3e15429e44 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -189,7 +189,7 @@ bool MoviePlayer::load(uint32 id) {
int lastEnd = -1;
_movieTexts.clear();
- while (f.readLine(line, sizeof(line))) {
+ while (f.readLine_OLD(line, sizeof(line))) {
lineNo++;
if (line[0] == '#' || line[0] == 0) {
continue;
@@ -300,9 +300,6 @@ void MoviePlayer::play(void) {
terminated = true;
}
break;
- case Common::EVENT_QUIT:
- _system->quit();
- break;
default:
break;
}
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 980e0b4f9f..d0808d3ece 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -215,7 +215,7 @@ void Control::askForCd(void) {
notAccepted = false;
}
}
- } while (notAccepted && (!SwordEngine::_systemVars.engineQuit));
+ } while (notAccepted && (!g_engine->quit()));
_resMan->resClose(fontId);
free(_screenBuf);
@@ -317,7 +317,7 @@ uint8 Control::runPanel(void) {
}
delay(1000 / 12);
newMode = getClicks(mode, &retVal);
- } while ((newMode != BUTTON_DONE) && (retVal == 0) && (!SwordEngine::_systemVars.engineQuit));
+ } while ((newMode != BUTTON_DONE) && (retVal == 0) && (!g_engine->quit()));
if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
uint8 volL, volR;
@@ -425,7 +425,7 @@ uint8 Control::handleButtonClick(uint8 id, uint8 mode, uint8 *retVal) {
_buttons[5]->setSelected(SwordEngine::_systemVars.showText);
} else if (id == BUTTON_QUIT) {
if (getConfirm(_lStrings[STR_QUIT]))
- SwordEngine::_systemVars.engineQuit = true;
+ g_engine->quitGame();
return mode;
}
break;
@@ -703,7 +703,7 @@ void Control::handleSaveKey(Common::KeyState kbd) {
bool Control::saveToFile(void) {
if ((_selectedSavegame == 255) || !strlen((char*)_saveNames[_selectedSavegame]))
return false; // no saveslot selected or no name entered
- saveGameToFile(_selectedSavegame);
+ saveGameToFile(_numSaves);
writeSavegameDescriptions();
return true;
}
@@ -741,6 +741,7 @@ void Control::readSavegameDescriptions(void) {
curFileNum++;
} while ((ch != 255) && (!inf->eos()));
_saveFiles = curFileNum;
+ _numSaves = _saveFiles;
}
delete inf;
}
@@ -1091,9 +1092,6 @@ void Control::delay(uint32 msecs) {
_mouseDown = false;
_mouseState |= BS1_WHEEL_DOWN;
break;
- case Common::EVENT_QUIT:
- SwordEngine::_systemVars.engineQuit = true;
- break;
default:
break;
}
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 7d9af2f199..926db757b9 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -98,6 +98,7 @@ private:
void deselectSaveslots(void);
uint8 *_restoreBuf;
uint8 _saveFiles;
+ uint8 _numSaves;
uint8 _saveScrollPos;
uint8 _selectedSavegame;
uint8 _saveNames[64][32];
diff --git a/engines/sword1/credits.cpp b/engines/sword1/credits.cpp
index 14dd0ecd2b..258784ab53 100644
--- a/engines/sword1/credits.cpp
+++ b/engines/sword1/credits.cpp
@@ -125,7 +125,7 @@ void CreditsPlayer::play(void) {
uint16 renderY = BUFSIZE_Y / 2;
uint16 clearY = 0xFFFF;
bool clearLine = false;
- while (((*textData != FNT_EOB) || (scrollY != renderY)) && !SwordEngine::_systemVars.engineQuit) {
+ while (((*textData != FNT_EOB) || (scrollY != renderY)) && !g_engine->quit()) {
if ((int32)_mixer->getSoundElapsedTime(bgSound) - relDelay < (SCROLL_TIMING * 2)) { // sync to audio
if (scrollY < BUFSIZE_Y - CREDITS_Y)
_system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, CREDITS_Y);
@@ -175,7 +175,7 @@ void CreditsPlayer::play(void) {
uint8 *revoBuf = credFile.decompressFile(REVO_LOGO);
uint8 *revoPal = credFile.fetchFile(REVO_PAL, &_palLen);
_palLen /= 3;
- while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEUP_TIME) && !SwordEngine::_systemVars.engineQuit) {
+ while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEUP_TIME) && !g_engine->quit()) {
delay(100);
}
memset(_palette, 0, 256 * 4);
@@ -184,13 +184,13 @@ void CreditsPlayer::play(void) {
_system->updateScreen();
fadePalette(revoPal, true, _palLen);
- while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEDOWN_TIME) && !SwordEngine::_systemVars.engineQuit) {
+ while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEDOWN_TIME) && !g_engine->quit()) {
delay(100);
}
fadePalette(revoPal, false, _palLen);
delay(3000);
- if (SwordEngine::_systemVars.engineQuit)
+ if (g_engine->quit())
_mixer->stopAll();
free(revoBuf);
}
@@ -200,7 +200,7 @@ void CreditsPlayer::fadePalette(uint8 *srcPal, bool fadeup, uint16 len) {
int fadeStart = fadeup ? 0 : 12;
int relDelay = _system->getMillis();
- for (int fadeStep = fadeStart; (fadeStep >= 0) && (fadeStep <= 12) && !SwordEngine::_systemVars.engineQuit; fadeStep += fadeDir) {
+ for (int fadeStep = fadeStart; (fadeStep >= 0) && (fadeStep <= 12) && !g_engine->quit(); fadeStep += fadeDir) {
for (uint16 cnt = 0; cnt < len * 3; cnt++)
_palette[(cnt / 3) * 4 + (cnt % 3)] = (srcPal[cnt] * fadeStep) / 12;
_system->setPalette(_palette, 0, 256);
@@ -280,13 +280,12 @@ void CreditsPlayer::delay(int msecs) {
do {
Common::EventManager *eventMan = _system->getEventManager();
while (eventMan->pollEvent(event)) {
+#if 0
switch (event.type) {
- case Common::EVENT_QUIT:
- SwordEngine::_systemVars.engineQuit = true;
- break;
default:
break;
}
+#endif
}
_system->updateScreen();
@@ -294,7 +293,7 @@ void CreditsPlayer::delay(int msecs) {
if (msecs > 0)
_system->delayMillis(10);
- } while ((_system->getMillis() < start + msecs) && !SwordEngine::_systemVars.engineQuit);
+ } while ((_system->getMillis() < start + msecs) && !g_engine->quit());
}
ArcFile::ArcFile(void) {
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index e7e1fb39a4..2fa108ebdd 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -1636,7 +1636,7 @@ int Logic::fnQuitGame(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d,
if (SwordEngine::_systemVars.isDemo) {
GUI::MessageDialog dialog("This is the end of the Broken Sword 1 Demo", "OK", NULL);
dialog.runModal();
- SwordEngine::_systemVars.engineQuit = true;
+ g_engine->quitGame();
} else
error("fnQuitGame() called");
return fnQuit(cpt, id, 0, 0, 0, 0, 0, 0);
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index 6cb82bc0b0..27e7568fcc 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -80,7 +80,7 @@ BaseAudioStream::~BaseAudioStream() {
void BaseAudioStream::reinit(int size, int rate, byte flags) {
_isStereo = (flags & Audio::Mixer::FLAG_STEREO) != 0;
_rate = rate;
- assert((uint)size <= (_sourceStream->size() - _sourceStream->pos()));
+ assert(size <= (_sourceStream->size() - _sourceStream->pos()));
_bitsPerSample = ((flags & Audio::Mixer::FLAG_16BITS) != 0) ? 16 : 8;
_samplesLeft = (size * 8) / _bitsPerSample;
if ((_bitsPerSample != 16) && (_bitsPerSample != 8))
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 7372779199..9b79f59a32 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -32,6 +32,7 @@
#include "common/fs.h"
#include "common/timer.h"
#include "common/events.h"
+#include "common/savefile.h"
#include "common/system.h"
#include "engines/metaengine.h"
@@ -94,13 +95,22 @@ public:
return "Broken Sword Games (C) Revolution";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual GameList getSupportedGames() const;
virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const FSList &fslist) const;
+ virtual GameList detectGames(const Common::FSList &fslist) const;
+ virtual SaveStateList listSaves(const char *target) const;
virtual PluginError createInstance(OSystem *syst, Engine **engine) const;
};
+bool SwordMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad);
+}
+
GameList SwordMetaEngine::getSupportedGames() const {
GameList games;
games.push_back(sword1FullSettings);
@@ -122,8 +132,8 @@ GameDescriptor SwordMetaEngine::findGame(const char *gameid) const {
return GameDescriptor();
}
-void Sword1CheckDirectory(const FSList &fslist, bool *filesFound) {
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound) {
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
const char *fileName = file->getName().c_str();
for (int cnt = 0; cnt < NUM_FILES_TO_CHECK; cnt++)
@@ -132,15 +142,15 @@ void Sword1CheckDirectory(const FSList &fslist, bool *filesFound) {
} else {
for (int cnt = 0; cnt < ARRAYSIZE(g_dirNames); cnt++)
if (scumm_stricmp(file->getName().c_str(), g_dirNames[cnt]) == 0) {
- FSList fslist2;
- if (file->getChildren(fslist2, FilesystemNode::kListFilesOnly))
+ Common::FSList fslist2;
+ if (file->getChildren(fslist2, Common::FilesystemNode::kListFilesOnly))
Sword1CheckDirectory(fslist2, filesFound);
}
}
}
}
-GameList SwordMetaEngine::detectGames(const FSList &fslist) const {
+GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const {
int i, j;
GameList detectedGames;
bool filesFound[NUM_FILES_TO_CHECK];
@@ -187,6 +197,47 @@ PluginError SwordMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
return kNoError;
}
+SaveStateList SwordMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ SaveStateList saveList;
+
+ Common::String pattern = "SAVEGAME.???";
+ Common::StringList filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end());
+ Common::StringList::const_iterator file = filenames.begin();
+
+ Common::InSaveFile *in = saveFileMan->openForLoading("SAVEGAME.INF");
+ if (in) {
+ uint8 stop;
+ char saveDesc[32];
+ do {
+ // Obtain the last digit of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 1);
+
+ uint pos = 0;
+ do {
+ stop = in->readByte();
+ if (pos < (sizeof(saveDesc) - 1)) {
+ if ((stop == 10) || (stop == 255) || (in->eos())) {
+ saveDesc[pos++] = '\0';
+ }
+ else if (stop >= 32) {
+ saveDesc[pos++] = stop;
+ }
+ }
+ } while ((stop != 10) && (stop != 255) && (!in->eos()));
+ if (saveDesc[0] != 0) {
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file));
+ file++;
+ }
+ } while ((stop != 255) && (!in->eos()));
+ }
+
+ delete in;
+
+ return saveList;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(SWORD1)
REGISTER_PLUGIN_DYNAMIC(SWORD1, PLUGIN_TYPE_ENGINE, SwordMetaEngine);
#else
@@ -206,14 +257,14 @@ SwordEngine::SwordEngine(OSystem *syst)
_features = 0;
// Add default file directories
- Common::File::addDefaultDirectory(_gameDataPath + "CLUSTERS/");
- Common::File::addDefaultDirectory(_gameDataPath + "MUSIC/");
- Common::File::addDefaultDirectory(_gameDataPath + "SPEECH/");
- Common::File::addDefaultDirectory(_gameDataPath + "VIDEO/");
- Common::File::addDefaultDirectory(_gameDataPath + "clusters/");
- Common::File::addDefaultDirectory(_gameDataPath + "music/");
- Common::File::addDefaultDirectory(_gameDataPath + "speech/");
- Common::File::addDefaultDirectory(_gameDataPath + "video/");
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("CLUSTERS"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("MUSIC"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("SPEECH"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("music"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("speech"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("video"));
}
SwordEngine::~SwordEngine() {
@@ -247,8 +298,6 @@ int SwordEngine::init() {
_resMan = new ResMan("swordres.rif", _systemVars.isMac);
debug(5, "Starting object manager");
_objectMan = new ObjectMan(_resMan);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, Audio::Mixer::kMaxMixerVolume);
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
_mouse = new Mouse(_system, _resMan, _objectMan);
_screen = new Screen(_system, _resMan, _objectMan);
_music = new Music(_mixer);
@@ -257,60 +306,13 @@ int SwordEngine::init() {
_logic = new Logic(_objectMan, _resMan, _screen, _mouse, _sound, _music, _menu, _system, _mixer);
_mouse->useLogicAndMenu(_logic, _menu);
- uint musicVol = ConfMan.getInt("music_volume");
- uint speechVol = ConfMan.getInt("speech_volume");
- uint sfxVol = ConfMan.getInt("sfx_volume");
- uint musicBal = 50;
- if (ConfMan.hasKey("music_balance")) {
- musicBal = CLIP(ConfMan.getInt("music_balance"), 0, 100);
- }
- uint speechBal = 50;
- if (ConfMan.hasKey("speech_balance")) {
- speechBal = CLIP(ConfMan.getInt("speech_balance"), 0, 100);
- }
- uint sfxBal = 50;
- if (ConfMan.hasKey("sfx_balance")) {
- sfxBal = CLIP(ConfMan.getInt("sfx_balance"), 0, 100);
- }
-
- uint musicVolL = 2 * musicVol * musicBal / 100;
- uint musicVolR = 2 * musicVol - musicVolL;
-
- uint speechVolL = 2 * speechVol * speechBal / 100;
- uint speechVolR = 2 * speechVol - speechVolL;
-
- uint sfxVolL = 2 * sfxVol * sfxBal / 100;
- uint sfxVolR = 2 * sfxVol - sfxVolL;
-
- if (musicVolR > 255) {
- musicVolR = 255;
- }
- if (musicVolL > 255) {
- musicVolL = 255;
- }
- if (speechVolR > 255) {
- speechVolR = 255;
- }
- if (speechVolL > 255) {
- speechVolL = 255;
- }
- if (sfxVolR > 255) {
- sfxVolR = 255;
- }
- if (sfxVolL > 255) {
- sfxVolL = 255;
- }
-
- _music->setVolume(musicVolL, musicVolR);
- _sound->setSpeechVol(speechVolL, speechVolR);
- _sound->setSfxVol(sfxVolL, sfxVolR);
+ syncSoundSettings();
_systemVars.justRestoredGame = 0;
_systemVars.currentCD = 0;
_systemVars.controlPanelMode = CP_NEWGAME;
_systemVars.forceRestart = false;
_systemVars.wantFade = true;
- _systemVars.engineQuit = false;
switch (Common::parseLanguage(ConfMan.get("language"))) {
case Common::DE_DEU:
@@ -358,6 +360,62 @@ void SwordEngine::reinitialize(void) {
_systemVars.wantFade = true;
}
+void SwordEngine::syncSoundSettings() {
+ uint musicVol = ConfMan.getInt("music_volume");
+ uint sfxVol = ConfMan.getInt("sfx_volume");
+ uint speechVol = ConfMan.getInt("speech_volume");
+
+ uint musicBal = 50;
+ if (ConfMan.hasKey("music_balance")) {
+ musicBal = CLIP(ConfMan.getInt("music_balance"), 0, 100);
+ }
+
+ uint speechBal = 50;
+ if (ConfMan.hasKey("speech_balance")) {
+ speechBal = CLIP(ConfMan.getInt("speech_balance"), 0, 100);
+ }
+ uint sfxBal = 50;
+ if (ConfMan.hasKey("sfx_balance")) {
+ sfxBal = CLIP(ConfMan.getInt("sfx_balance"), 0, 100);
+ }
+
+ uint musicVolL = 2 * musicVol * musicBal / 100;
+ uint musicVolR = 2 * musicVol - musicVolL;
+
+ uint speechVolL = 2 * speechVol * speechBal / 100;
+ uint speechVolR = 2 * speechVol - speechVolL;
+
+ uint sfxVolL = 2 * sfxVol * sfxBal / 100;
+ uint sfxVolR = 2 * sfxVol - sfxVolL;
+
+ if (musicVolR > 255) {
+ musicVolR = 255;
+ }
+ if (musicVolL > 255) {
+ musicVolL = 255;
+ }
+
+ if (speechVolR > 255) {
+ speechVolR = 255;
+ }
+ if (speechVolL > 255) {
+ speechVolL = 255;
+ }
+ if (sfxVolR > 255) {
+ sfxVolR = 255;
+ }
+ if (sfxVolL > 255) {
+ sfxVolL = 255;
+ }
+
+ _music->setVolume(musicVolL, musicVolR);
+ _sound->setSpeechVol(speechVolL, speechVolR);
+ _sound->setSfxVol(sfxVolL, sfxVolR);
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
+}
+
void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
uint8 bitPos = 0;
while (flags) {
@@ -639,13 +697,13 @@ int SwordEngine::go() {
int saveSlot = ConfMan.getInt("save_slot");
// Savegames are numbered starting from 1 in the dialog window,
// but their filenames are numbered starting from 0.
- if (saveSlot > 0 && _control->restoreGameFromFile(saveSlot - 1)) {
+ if (saveSlot >= 0 && _control->savegamesExist() && _control->restoreGameFromFile(saveSlot)) {
_control->doRestore();
} else if (_control->savegamesExist()) {
_systemVars.controlPanelMode = CP_NEWGAME;
if (_control->runPanel() == CONTROL_GAME_RESTORED)
_control->doRestore();
- else if (!_systemVars.engineQuit)
+ else if (!quit())
_logic->startPositions(0);
} else {
// no savegames, start new game.
@@ -654,10 +712,10 @@ int SwordEngine::go() {
}
_systemVars.controlPanelMode = CP_NORMAL;
- while (!_systemVars.engineQuit) {
+ while (!quit()) {
uint8 action = mainLoop();
- if (!_systemVars.engineQuit) {
+ if (!quit()) {
// the mainloop was left, we have to reinitialize.
reinitialize();
if (action == CONTROL_GAME_RESTORED)
@@ -698,7 +756,7 @@ uint8 SwordEngine::mainLoop(void) {
uint8 retCode = 0;
_keyPressed.reset();
- while ((retCode == 0) && (!_systemVars.engineQuit)) {
+ while ((retCode == 0) && (!quit())) {
// do we need the section45-hack from sword.c here?
checkCd();
@@ -747,9 +805,9 @@ uint8 SwordEngine::mainLoop(void) {
}
_mouseState = 0;
_keyPressed.reset();
- } while ((Logic::_scriptVars[SCREEN] == Logic::_scriptVars[NEW_SCREEN]) && (retCode == 0) && (!_systemVars.engineQuit));
+ } while ((Logic::_scriptVars[SCREEN] == Logic::_scriptVars[NEW_SCREEN]) && (retCode == 0) && (!quit()));
- if ((retCode == 0) && (Logic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade && (!_systemVars.engineQuit)) {
+ if ((retCode == 0) && (Logic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade && (!quit())) {
_screen->fadeDownPalette();
int32 relDelay = (int32)_system->getMillis();
while (_screen->stillFading()) {
@@ -796,9 +854,6 @@ void SwordEngine::delay(int32 amount) { //copied and mutilated from sky.cpp
_mouseState |= BS1R_BUTTON_UP;
_mouseCoord = event.mouse;
break;
- case Common::EVENT_QUIT:
- _systemVars.engineQuit = true;
- break;
default:
break;
}
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index cfb6750a47..5bc80b4f6d 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -58,7 +58,6 @@ struct SystemVars {
bool runningFromCd;
uint32 currentCD; // starts at zero, then either 1 or 2 depending on section being played
uint32 justRestoredGame; // see main() in sword.c & New_screen() in gtm_core.c
- bool engineQuit;
uint8 controlPanelMode; // 1 death screen version of the control panel, 2 = successful end of game, 3 = force restart
bool forceRestart;
@@ -78,6 +77,7 @@ public:
virtual ~SwordEngine();
static SystemVars _systemVars;
void reinitialize(void);
+ virtual void syncSoundSettings();
uint32 _features;
protected:
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 48196a2f7d..76f14851e7 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -357,8 +357,8 @@ bool MoviePlayer::userInterrupt() {
case Common::EVENT_SCREEN_CHANGED:
handleScreenChanged();
break;
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
- _vm->closeGame();
terminate = true;
break;
case Common::EVENT_KEYDOWN:
@@ -379,7 +379,7 @@ void MoviePlayer::play(SequenceTextInfo *textList, uint32 numLines, int32 leadIn
bool startNextText = false;
// This happens if the user quits during the "eye" cutscene.
- if (_vm->_quit)
+ if (_vm->quit())
return;
_numSpeechLines = numLines;
diff --git a/engines/sword2/controls.cpp b/engines/sword2/controls.cpp
index 6b466d6be0..dcacbc78d4 100644
--- a/engines/sword2/controls.cpp
+++ b/engines/sword2/controls.cpp
@@ -396,7 +396,7 @@ int Dialog::runModal() {
_vm->_system->delayMillis(20);
- if (_vm->_quit)
+ if (_vm->quit())
setResult(0);
}
@@ -842,7 +842,7 @@ int StartDialog::runModal() {
if (startDialog.runModal())
return 1;
- if (_vm->_quit)
+ if (_vm->quit())
return 0;
RestoreDialog restoreDialog(_vm);
@@ -850,7 +850,7 @@ int StartDialog::runModal() {
if (restoreDialog.runModal())
return 0;
- if (_vm->_quit)
+ if (_vm->quit())
return 0;
}
@@ -882,7 +882,7 @@ int QuitDialog::runModal() {
int result = MiniDialog::runModal();
if (result)
- _vm->closeGame();
+ _vm->quitGame();
return result;
}
diff --git a/engines/sword2/function.cpp b/engines/sword2/function.cpp
index 84a5b5af76..31b799386f 100644
--- a/engines/sword2/function.cpp
+++ b/engines/sword2/function.cpp
@@ -2388,7 +2388,7 @@ int32 Logic::fnPlayCredits(int32 *params) {
// params: none
if (readVar(DEMO)) {
- _vm->closeGame();
+ _vm->quitGame();
return IR_STOP;
}
diff --git a/engines/sword2/palette.cpp b/engines/sword2/palette.cpp
index 81f93c77ae..b66a3c9a81 100644
--- a/engines/sword2/palette.cpp
+++ b/engines/sword2/palette.cpp
@@ -212,7 +212,7 @@ uint8 Screen::getFadeStatus() {
}
void Screen::waitForFade() {
- while (getFadeStatus() != RDFADE_NONE && getFadeStatus() != RDFADE_BLACK && !_vm->_quit) {
+ while (getFadeStatus() != RDFADE_NONE && getFadeStatus() != RDFADE_BLACK && !_vm->quit()) {
updateDisplay();
_vm->_system->delayMillis(20);
}
diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp
index 8cddddff78..326f90cd82 100644
--- a/engines/sword2/resman.cpp
+++ b/engines/sword2/resman.cpp
@@ -113,7 +113,7 @@ bool ResourceManager::init() {
// The resource.inf file is a simple text file containing the names of
// all the resource files.
- while (file.readLine(_resFiles[_totalClusters].fileName, sizeof(_resFiles[_totalClusters].fileName))) {
+ while (file.readLine_OLD(_resFiles[_totalClusters].fileName, sizeof(_resFiles[_totalClusters].fileName))) {
_resFiles[_totalClusters].numEntries = -1;
_resFiles[_totalClusters].entryTab = NULL;
if (++_totalClusters >= MAX_res_files) {
@@ -412,7 +412,7 @@ Common::File *ResourceManager::openCluFile(uint16 fileNum) {
// quit while the game is asking for the user to insert a CD.
// But recovering from this situation gracefully is just too
// much trouble, so quit now.
- if (_vm->_quit)
+ if (_vm->quit())
g_system->quit();
// If the file is supposed to be on hard disk, or we're
diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp
index fdabb3ee6f..1faef01939 100644
--- a/engines/sword2/screen.cpp
+++ b/engines/sword2/screen.cpp
@@ -389,7 +389,7 @@ void Screen::displayMsg(byte *text, int time) {
uint32 targetTime = _vm->getMillis() + (time * 1000);
_vm->sleepUntil(targetTime);
} else {
- while (!_vm->_quit) {
+ while (!_vm->quit()) {
MouseEvent *me = _vm->mouseEvent();
if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
break;
@@ -919,7 +919,7 @@ void Screen::rollCredits() {
while (1) {
char buffer[80];
- char *line = f.readLine(buffer, sizeof(buffer));
+ char *line = f.readLine_OLD(buffer, sizeof(buffer));
if (!line || *line == 0) {
if (!hasCenterMark) {
@@ -1035,7 +1035,7 @@ void Screen::rollCredits() {
uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);
- while (scrollPos < scrollSteps && !_vm->_quit) {
+ while (scrollPos < scrollSteps && !_vm->quit()) {
clearScene();
for (i = startLine; i < lineCount; i++) {
@@ -1123,13 +1123,13 @@ void Screen::rollCredits() {
// The music should either have stopped or be about to stop, so
// wait for it to really happen.
- while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
+ while (_vm->_sound->musicTimeRemaining() && !_vm->quit()) {
updateDisplay(false);
_vm->_system->delayMillis(100);
}
}
- if (_vm->_quit)
+ if (_vm->quit())
return;
waitForFade();
diff --git a/engines/sword2/sound.h b/engines/sword2/sound.h
index b89ef8f12b..684be3dacd 100644
--- a/engines/sword2/sound.h
+++ b/engines/sword2/sound.h
@@ -124,7 +124,7 @@ struct SoundFileHandle {
Common::File file;
uint32 *idxTab;
uint32 idxLen;
- uint32 fileSize;
+ int32 fileSize;
uint32 fileType;
volatile bool inUse;
};
diff --git a/engines/sword2/startup.cpp b/engines/sword2/startup.cpp
index 1841384897..09bf65bf75 100644
--- a/engines/sword2/startup.cpp
+++ b/engines/sword2/startup.cpp
@@ -64,19 +64,23 @@ bool Sword2Engine::initStartMenu() {
// extract the filenames
int start_ids[MAX_starts];
- char buf[10];
-
int lineno = 0;
- while (fp.readLine(buf, sizeof(buf))) {
+ while (!fp.eos() && !fp.ioFailed()) {
+ Common::String line = fp.readLine();
+
+ // Skip empty lines or, more likely, the end of the stream.
+ if (line.size() == 0)
+ continue;
+
char *errptr;
int id;
lineno++;
- id = strtol(buf, &errptr, 10);
+ id = strtol(line.c_str(), &errptr, 10);
if (*errptr) {
- warning("startup.inf:%d: Invalid string '%s'", lineno, buf);
+ warning("startup.inf:%d: Invalid string '%s'", lineno, line.c_str());
continue;
}
@@ -98,6 +102,10 @@ bool Sword2Engine::initStartMenu() {
}
}
+ // An I/O error before EOS? That's bad, but this is not a vital file.
+ if (fp.ioFailed() && !fp.eos())
+ warning("I/O error while reading startup.inf");
+
fp.close();
// Using this method the Gode generated resource.inf must have #0d0a
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 7331d1f761..dc884eaacb 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -33,6 +33,7 @@
#include "common/file.h"
#include "common/fs.h"
#include "common/events.h"
+#include "common/savefile.h"
#include "common/system.h"
#include "engines/metaengine.h"
@@ -79,13 +80,24 @@ public:
return "Broken Sword Games (C) Revolution";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual GameList getSupportedGames() const;
virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const FSList &fslist) const;
+ virtual GameList detectGames(const Common::FSList &fslist) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
virtual PluginError createInstance(OSystem *syst, Engine **engine) const;
};
+bool Sword2MetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
GameList Sword2MetaEngine::getSupportedGames() const {
const Sword2::GameSettings *g = Sword2::sword2_settings;
GameList games;
@@ -106,10 +118,10 @@ GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const {
return GameDescriptor(g->gameid, g->description);
}
-GameList Sword2MetaEngine::detectGames(const FSList &fslist) const {
+GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const {
GameList detectedGames;
const Sword2::GameSettings *g;
- FSList::const_iterator file;
+ Common::FSList::const_iterator file;
// TODO: It would be nice if we had code here which distinguishes
// between the 'sword2' and 'sword2demo' targets. The current code
@@ -139,8 +151,8 @@ GameList Sword2MetaEngine::detectGames(const FSList &fslist) const {
const char *fileName = file->getName().c_str();
if (0 == scumm_stricmp("clusters", fileName)) {
- FSList recList;
- if (file->getChildren(recList, FilesystemNode::kListAll)) {
+ Common::FSList recList;
+ if (file->getChildren(recList, Common::FilesystemNode::kListAll)) {
GameList recGames(detectGames(recList));
if (!recGames.empty()) {
detectedGames.push_back(recGames);
@@ -156,13 +168,52 @@ GameList Sword2MetaEngine::detectGames(const FSList &fslist) const {
return detectedGames;
}
+SaveStateList Sword2MetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ char saveDesc[SAVE_DESCRIPTION_LEN];
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ in->readUint32LE();
+ in->read(saveDesc, SAVE_DESCRIPTION_LEN);
+ saveList.push_back(SaveStateDescriptor(slotNum, Common::String(saveDesc), *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void Sword2MetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[6];
+ snprintf(extension, sizeof(extension), ".%03d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
PluginError Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(syst);
assert(engine);
- FSList fslist;
- FilesystemNode dir(ConfMan.get("path"));
- if (!dir.getChildren(fslist, FilesystemNode::kListAll)) {
+ Common::FSList fslist;
+ Common::FilesystemNode dir(ConfMan.get("path"));
+ if (!dir.getChildren(fslist, Common::FilesystemNode::kListAll)) {
return kInvalidPathError;
}
@@ -190,12 +241,12 @@ namespace Sword2 {
Sword2Engine::Sword2Engine(OSystem *syst) : Engine(syst) {
// Add default file directories
- Common::File::addDefaultDirectory(_gameDataPath + "CLUSTERS/");
- Common::File::addDefaultDirectory(_gameDataPath + "SWORD2/");
- Common::File::addDefaultDirectory(_gameDataPath + "VIDEO/");
- Common::File::addDefaultDirectory(_gameDataPath + "clusters/");
- Common::File::addDefaultDirectory(_gameDataPath + "sword2/");
- Common::File::addDefaultDirectory(_gameDataPath + "video/");
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("CLUSTERS"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("SWORD2"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("sword2"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("video"));
if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword2demo"))
_features = GF_DEMO;
@@ -229,7 +280,6 @@ Sword2Engine::Sword2Engine(OSystem *syst) : Engine(syst) {
_gameCycle = 0;
_gameSpeed = 1;
- _quit = false;
syst->getEventManager()->registerRandomSource(_rnd, "sword2");
}
@@ -371,7 +421,7 @@ int Sword2Engine::init() {
// player will kill the music for us. Otherwise, the restore
// will either have killed the music, or done a crossfade.
- if (_quit)
+ if (quit())
return 0;
if (result)
@@ -443,7 +493,7 @@ int Sword2Engine::go() {
// because we want the break to happen before updating the
// screen again.
- if (_quit)
+ if (quit())
break;
// creates the debug text blocks
@@ -463,10 +513,6 @@ int Sword2Engine::go() {
return 0;
}
-void Sword2Engine::closeGame() {
- _quit = true;
-}
-
void Sword2Engine::restartGame() {
ScreenInfo *screenInfo = _screen->getScreenInfo();
uint32 temp_demo_flag;
@@ -610,9 +656,6 @@ void Sword2Engine::parseInputEvents() {
_mouseEvent.buttons = RD_WHEELDOWN;
}
break;
- case Common::EVENT_QUIT:
- closeGame();
- break;
default:
break;
}
diff --git a/engines/sword2/sword2.h b/engines/sword2/sword2.h
index 05c5d7fa47..9b589c347e 100644
--- a/engines/sword2/sword2.h
+++ b/engines/sword2/sword2.h
@@ -141,8 +141,6 @@ public:
bool getSubtitles() { return _useSubtitles; }
void setSubtitles(bool b) { _useSubtitles = b; }
- bool _quit;
-
uint32 _features;
MemoryManager *_memory;
@@ -210,7 +208,6 @@ public:
void startGame();
void gameCycle();
- void closeGame();
void restartGame();
void sleepUntil(uint32 time);
diff --git a/engines/tinsel/config.cpp b/engines/tinsel/config.cpp
index 4c143f1b8d..803d2231e4 100644
--- a/engines/tinsel/config.cpp
+++ b/engines/tinsel/config.cpp
@@ -24,8 +24,6 @@
* This file contains configuration functionality
*/
-//#define USE_3FLAGS 1
-
#include "tinsel/config.h"
#include "tinsel/dw.h"
#include "tinsel/sound.h"
@@ -41,13 +39,13 @@ namespace Tinsel {
//----------------- GLOBAL GLOBAL DATA --------------------
int dclickSpeed = DOUBLE_CLICK_TIME;
-int volMidi = MAXMIDIVOL;
-int volSound = MAXSAMPVOL;
-int volVoice = MAXSAMPVOL;
+int volMidi = Audio::Mixer::kMaxChannelVolume;
+int volSound = Audio::Mixer::kMaxChannelVolume;
+int volVoice = Audio::Mixer::kMaxChannelVolume;
int speedText = DEFTEXTSPEED;
int bSubtitles = false;
int bSwapButtons = 0;
-LANGUAGE language = TXT_ENGLISH;
+LANGUAGE g_language = TXT_ENGLISH;
int bAmerica = 0;
@@ -55,19 +53,43 @@ int bAmerica = 0;
bool bNoBlocking;
/**
- * WriteConfig()
+ * Write settings to config manager and flush the config file to disk.
*/
-
void WriteConfig(void) {
ConfMan.setInt("dclick_speed", dclickSpeed);
- ConfMan.setInt("music_volume", (volMidi * Audio::Mixer::kMaxChannelVolume) / MAXMIDIVOL);
- ConfMan.setInt("sfx_volume", (volSound * Audio::Mixer::kMaxChannelVolume) / MAXSAMPVOL);
- ConfMan.setInt("speech_volume", (volVoice * Audio::Mixer::kMaxChannelVolume) / MAXSAMPVOL);
+ ConfMan.setInt("music_volume", volMidi);
+ ConfMan.setInt("sfx_volume", volSound);
+ ConfMan.setInt("speech_volume", volVoice);
ConfMan.setInt("talkspeed", (speedText * 255) / 100);
ConfMan.setBool("subtitles", bSubtitles);
//ConfMan.setBool("swap_buttons", bSwapButtons ? 1 : 0);
- //ConfigData.language = language; // not necessary, as language has been set in the launcher
//ConfigData.bAmerica = bAmerica; // EN_USA / EN_GRB
+
+ // Store language for multilingual versions
+ if ((_vm->getFeatures() & GF_USE_3FLAGS) || (_vm->getFeatures() & GF_USE_4FLAGS) || (_vm->getFeatures() & GF_USE_5FLAGS)) {
+ Common::Language lang;
+ switch (g_language) {
+ case TXT_FRENCH:
+ lang = Common::FR_FRA;
+ break;
+ case TXT_GERMAN:
+ lang = Common::DE_DEU;
+ break;
+ case TXT_SPANISH:
+ lang = Common::ES_ESP;
+ break;
+ case TXT_ITALIAN:
+ lang = Common::IT_ITA;
+ break;
+ default:
+ lang = Common::EN_ANY;
+ }
+
+ ConfMan.set("language", Common::getLanguageCode(lang));
+ }
+
+ // Write to disk
+ ConfMan.flushToDisk();
}
/*---------------------------------------------------------------------*\
@@ -79,9 +101,9 @@ void ReadConfig(void) {
if (ConfMan.hasKey("dclick_speed"))
dclickSpeed = ConfMan.getInt("dclick_speed");
- volMidi = (ConfMan.getInt("music_volume") * MAXMIDIVOL) / Audio::Mixer::kMaxChannelVolume;
- volSound = (ConfMan.getInt("sfx_volume") * MAXSAMPVOL) / Audio::Mixer::kMaxChannelVolume;
- volVoice = (ConfMan.getInt("speech_volume") * MAXSAMPVOL) / Audio::Mixer::kMaxChannelVolume;
+ volMidi = ConfMan.getInt("music_volume");
+ volSound = ConfMan.getInt("sfx_volume");
+ volVoice = ConfMan.getInt("speech_volume");
if (ConfMan.hasKey("talkspeed"))
speedText = (ConfMan.getInt("talkspeed") * 100) / 255;
@@ -94,24 +116,53 @@ void ReadConfig(void) {
//ConfigData.language = language; // not necessary, as language has been set in the launcher
//ConfigData.bAmerica = bAmerica; // EN_USA / EN_GRB
-// The flags here control how many country flags are displayed in one of the option dialogs.
-#if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
- language = ConfigData.language;
- #ifdef USE_3FLAGS
- if (language == TXT_ENGLISH || language == TXT_ITALIAN) {
- language = TXT_GERMAN;
- bSubtitles = true;
+ // Set language - we'll be clever here and use the ScummVM language setting
+ g_language = TXT_ENGLISH;
+ Common::Language lang = _vm->getLanguage();
+ if (lang == Common::UNK_LANG && ConfMan.hasKey("language"))
+ lang = Common::parseLanguage(ConfMan.get("language")); // For multi-lingual versions, fall back to user settings
+ switch (lang) {
+ case Common::FR_FRA:
+ g_language = TXT_FRENCH;
+ break;
+ case Common::DE_DEU:
+ g_language = TXT_GERMAN;
+ break;
+ case Common::ES_ESP:
+ g_language = TXT_SPANISH;
+ break;
+ case Common::IT_ITA:
+ g_language = TXT_ITALIAN;
+ break;
+ default:
+ g_language = TXT_ENGLISH;
}
- #endif
- #ifdef USE_4FLAGS
- if (language == TXT_ENGLISH) {
- language = TXT_GERMAN;
+
+ if (lang == Common::JA_JPN) {
+ // TODO: Add support for JAPAN version
+ } else if (lang == Common::HB_ISR) {
+ // TODO: Add support for HEBREW version
+
+ // The Hebrew version appears to the software as being English
+ // but it needs to have subtitles on...
+ g_language = TXT_ENGLISH;
bSubtitles = true;
+ } else if (_vm->getFeatures() & GF_USE_3FLAGS) {
+ // 3 FLAGS version supports French, German, Spanish
+ // Fall back to German if necessary
+ if (g_language != TXT_FRENCH && g_language != TXT_GERMAN && g_language != TXT_SPANISH) {
+ g_language = TXT_GERMAN;
+ bSubtitles = true;
+ }
+ } else if (_vm->getFeatures() & GF_USE_4FLAGS) {
+ // 4 FLAGS version supports French, German, Spanish, Italian
+ // Fall back to German if necessary
+ if (g_language != TXT_FRENCH && g_language != TXT_GERMAN &&
+ g_language != TXT_SPANISH && g_language != TXT_ITALIAN) {
+ g_language = TXT_GERMAN;
+ bSubtitles = true;
+ }
}
- #endif
-#else
- language = TXT_ENGLISH;
-#endif
}
bool isJapanMode() {
diff --git a/engines/tinsel/config.h b/engines/tinsel/config.h
index 73cc411cb6..fc85f0abe0 100644
--- a/engines/tinsel/config.h
+++ b/engines/tinsel/config.h
@@ -30,23 +30,11 @@
namespace Tinsel {
-// None of these defined -> 1 language, in ENGLISH.TXT
-//#define USE_5FLAGS 1 // All 5 flags
-//#define USE_4FLAGS 1 // French, German, Italian, Spanish
-//#define USE_3FLAGS 1 // French, German, Spanish
-
-// The Hebrew version appears to the software as being English
-// but it needs to have subtitles on...
-//#define HEBREW 1
-
-//#define JAPAN 1
-
-
// double click timer initial value
-#define DOUBLE_CLICK_TIME 6 // 6 @ 18Hz = .33 sec
-
-#define DEFTEXTSPEED 0
-
+enum {
+ DOUBLE_CLICK_TIME = 6, // 6 @ 18Hz = .33 sec
+ DEFTEXTSPEED = 0
+};
extern int dclickSpeed;
extern int volMidi;
@@ -55,7 +43,7 @@ extern int volVoice;
extern int speedText;
extern int bSubtitles;
extern int bSwapButtons;
-extern LANGUAGE language;
+extern LANGUAGE g_language;
extern int bAmerica;
void WriteConfig(void);
diff --git a/engines/tinsel/cursor.cpp b/engines/tinsel/cursor.cpp
index b95662cbfe..f933b2dd79 100644
--- a/engines/tinsel/cursor.cpp
+++ b/engines/tinsel/cursor.cpp
@@ -49,7 +49,7 @@ namespace Tinsel {
//----------------- LOCAL DEFINES --------------------
#define ITERATION_BASE FRAC_ONE
-#define ITER_ACCELLERATION (10L << (FRAC_BITS - 4))
+#define ITER_ACCELERATION (10L << (FRAC_BITS - 4))
//----------------- LOCAL GLOBAL DATA --------------------
@@ -404,7 +404,8 @@ static void MoveCursor(void) {
newY = intToFrac(ptMouse.y);
// modify mouse driver position depending on cursor keys
- if ((dir = _vm->getKeyDirection()) != 0) {
+ dir = _vm->getKeyDirection();
+ if (dir != 0) {
if (dir & MSK_LEFT)
newX -= IterationSize;
@@ -417,7 +418,7 @@ static void MoveCursor(void) {
if (dir & MSK_DOWN)
newY += IterationSize;
- IterationSize += ITER_ACCELLERATION;
+ IterationSize += ITER_ACCELERATION;
// set new mouse driver position
_vm->setMousePosition(Common::Point(fracToInt(newX), fracToInt(newY)));
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 7da4192456..526d72e4a4 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -29,6 +29,7 @@
#include "common/file.h"
#include "tinsel/tinsel.h"
+#include "tinsel/savescn.h" // needed by TinselMetaEngine::listSaves
namespace Tinsel {
@@ -111,6 +112,30 @@ static const TinselGameDescription gameDescriptions[] = {
TINSEL_V1,
},
+ { // Multilingual floppy with *.gra files.
+ // Note: It contains no english subtitles.
+ // Reported on our forums.
+ {
+ "dw",
+ "Floppy",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"french.txt", 0, NULL, -1},
+ {"german.txt", 0, NULL, -1},
+ {"italian.txt", 0, NULL, -1},
+ {"spanish.txt", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ GID_DW1,
+ 0,
+ GF_FLOPPY | GF_USE_4FLAGS,
+ TINSEL_V1,
+ },
+
{ // English CD. This version has *.gra files
{
"dw",
@@ -130,6 +155,96 @@ static const TinselGameDescription gameDescriptions[] = {
TINSEL_V1,
},
+ { // Multilingual CD with english speech and *.gra files.
+ // Note: It contains no english subtitles.
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"english.smp", 0, NULL, -1},
+ {"french.txt", 0, NULL, -1},
+ {"german.txt", 0, NULL, -1},
+ {"italian.txt", 0, NULL, -1},
+ {"spanish.txt", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS,
+ TINSEL_V1,
+ },
+ {
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"english.smp", 0, NULL, -1},
+ {"french.txt", 0, NULL, -1},
+ {"german.txt", 0, NULL, -1},
+ {"italian.txt", 0, NULL, -1},
+ {"spanish.txt", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS,
+ TINSEL_V1,
+ },
+ {
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"english.smp", 0, NULL, -1},
+ {"french.txt", 0, NULL, -1},
+ {"german.txt", 0, NULL, -1},
+ {"italian.txt", 0, NULL, -1},
+ {"spanish.txt", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS,
+ TINSEL_V1,
+ },
+ {
+ {
+ "dw",
+ "CD",
+ {
+ {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656},
+ {"english.smp", 0, NULL, -1},
+ {"french.txt", 0, NULL, -1},
+ {"german.txt", 0, NULL, -1},
+ {"italian.txt", 0, NULL, -1},
+ {"spanish.txt", 0, NULL, -1},
+ {NULL, 0, NULL, 0}
+ },
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ GID_DW1,
+ 0,
+ GF_CD | GF_USE_4FLAGS,
+ TINSEL_V1,
+ },
+
{ // English CD with SCN files
{
"dw",
@@ -189,25 +304,6 @@ static const TinselGameDescription gameDescriptions[] = {
{ AD_TABLE_END_MARKER, 0, 0, 0, 0 }
};
-/**
- * The fallback game descriptor used by the Tinsel engine's fallbackDetector.
- * Contents of this struct are to be overwritten by the fallbackDetector.
- */
-static TinselGameDescription g_fallbackDesc = {
- {
- "",
- "",
- AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
- Common::UNK_LANG,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- 0,
- 0,
- 0,
- 0,
-};
-
} // End of namespace Tinsel
static const Common::ADParams detectionParams = {
@@ -238,15 +334,42 @@ public:
}
virtual const char *getCopyright() const {
+ // FIXME: Bad copyright string.
+ // Should be something like "Tinsel (C) Psygnosis" or so... ???
return "Tinsel Engine";
}
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
- const Common::ADGameDescription *fallbackDetect(const FSList *fslist) const;
-
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual SaveStateList listSaves(const char *target) const;
};
+bool TinselMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves);
+}
+
+namespace Tinsel {
+extern int getList(Common::SaveFileManager *saveFileMan, const Common::String &target);
+}
+
+SaveStateList TinselMetaEngine::listSaves(const char *target) const {
+ int numStates = Tinsel::getList(g_system->getSavefileManager(), target);
+
+ SaveStateList saveList;
+ for (int i = 0; i < numStates; i++) {
+ SaveStateDescriptor sd(i,
+ Tinsel::ListEntry(i, Tinsel::LE_DESC),
+ Tinsel::ListEntry(i, Tinsel::LE_NAME));
+ // TODO: Also add savedFiles[i].dateTime to the SaveStateDescriptor
+ saveList.push_back(sd);
+ }
+
+ return saveList;
+}
+
+
bool TinselMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Tinsel::TinselGameDescription *gd = (const Tinsel::TinselGameDescription *)desc;
if (gd) {
@@ -255,21 +378,6 @@ bool TinselMetaEngine::createInstance(OSystem *syst, Engine **engine, const Comm
return gd != 0;
}
-const Common::ADGameDescription *TinselMetaEngine::fallbackDetect(const FSList *fslist) const {
- // Set the default values for the fallback descriptor's ADGameDescription part.
- Tinsel::g_fallbackDesc.desc.language = Common::UNK_LANG;
- Tinsel::g_fallbackDesc.desc.platform = Common::kPlatformPC;
- Tinsel::g_fallbackDesc.desc.flags = Common::ADGF_NO_FLAGS;
-
- // Set default values for the fallback descriptor's TinselGameDescription part.
- Tinsel::g_fallbackDesc.gameID = 0;
- Tinsel::g_fallbackDesc.features = 0;
- Tinsel::g_fallbackDesc.version = 0;
-
- //return (const Common::ADGameDescription *)&Tinsel::g_fallbackDesc;
- return NULL;
-}
-
#if PLUGIN_ENABLED_DYNAMIC(TINSEL)
REGISTER_PLUGIN_DYNAMIC(TINSEL, PLUGIN_TYPE_ENGINE, TinselMetaEngine);
#else
diff --git a/engines/tinsel/dw.h b/engines/tinsel/dw.h
index d14dd43fa2..9ceef37858 100644
--- a/engines/tinsel/dw.h
+++ b/engines/tinsel/dw.h
@@ -110,8 +110,11 @@ typedef int HPOLYGON;
// Language for the resource strings
enum LANGUAGE {
- TXT_ENGLISH, TXT_FRENCH, TXT_GERMAN,
- TXT_ITALIAN, TXT_SPANISH
+ TXT_ENGLISH,
+ TXT_FRENCH,
+ TXT_GERMAN,
+ TXT_ITALIAN,
+ TXT_SPANISH
};
} // end of namespace Tinsel
diff --git a/engines/tinsel/inventory.cpp b/engines/tinsel/inventory.cpp
index 2a0f3695c0..d20ada51ac 100644
--- a/engines/tinsel/inventory.cpp
+++ b/engines/tinsel/inventory.cpp
@@ -29,8 +29,6 @@
* And there's still a bit of tidying and commenting to do yet.
*/
-//#define USE_3FLAGS 1
-
#include "tinsel/actors.h"
#include "tinsel/anim.h"
#include "tinsel/background.h"
@@ -370,9 +368,7 @@ enum BFUNC {
NOFUNC, SAVEGAME, LOADGAME, IQUITGAME, CLOSEWIN,
OPENLOAD, OPENSAVE, OPENREST,
OPENSOUND, OPENCONT,
-#ifndef JAPAN
OPENSUBT,
-#endif
OPENQUIT,
INITGAME, MIDIVOL,
CLANG, RLANG
@@ -402,9 +398,7 @@ struct CONFBOX {
#define SIX_RESTART_OPTION 2
#define SIX_SOUND_OPTION 3
#define SIX_CONTROL_OPTION 4
-#ifndef JAPAN
#define SIX_SUBTITLES_OPTION 5
-#endif
#define SIX_QUIT_OPTION 6
#define SIX_RESUME_OPTION 7
#define SIX_LOAD_HEADING 8
@@ -531,9 +525,9 @@ CONFBOX restartBox[] = {
};
#else
CONFBOX soundBox[] = {
- { SLIDER, MIDIVOL, NULL, SIX_MVOL_SLIDER, 142, 25, MAXMIDIVOL, 2, &volMidi, 0 },
- { SLIDER, NOFUNC, NULL, SIX_SVOL_SLIDER, 142, 25+40, MAXSAMPVOL, 2, &volSound, 0 },
- { SLIDER, NOFUNC, NULL, SIX_VVOL_SLIDER, 142, 25+2*40, MAXSAMPVOL, 2, &volVoice, 0 }
+ { SLIDER, MIDIVOL, NULL, SIX_MVOL_SLIDER, 142, 25, Audio::Mixer::kMaxChannelVolume, 2, &volMidi, 0 },
+ { SLIDER, NOFUNC, NULL, SIX_SVOL_SLIDER, 142, 25+40, Audio::Mixer::kMaxChannelVolume, 2, &volSound, 0 },
+ { SLIDER, NOFUNC, NULL, SIX_VVOL_SLIDER, 142, 25+2*40, Audio::Mixer::kMaxChannelVolume, 2, &volVoice, 0 }
};
#endif
@@ -568,41 +562,60 @@ CONFBOX controlBox[] = {
/*-------------------------------------------------------------*\
-| This is the subtitles 'menu'. |
+| This is the subtitles 'menu'. |
\*-------------------------------------------------------------*/
-#ifndef JAPAN
CONFBOX subtitlesBox[] = {
-#ifdef USE_5FLAGS
+ { SLIDER, NOFUNC, NULL, SIX_TSPEED_SLIDER, 142, 20, 100, 2, &speedText, 0 },
+ { TOGGLE, NOFUNC, NULL, SIX_STITLE_TOGGLE, 142, 20+40, 23, 19, &bSubtitles, 0 },
+
+};
+
+CONFBOX subtitlesBox3Flags[] = {
+
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 15, 118, 56, 32, NULL, FIX_FR },
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 85, 118, 56, 32, NULL, FIX_GR },
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 155, 118, 56, 32, NULL, FIX_SP },
+
+ { SLIDER, NOFUNC, NULL, SIX_TSPEED_SLIDER, 142, 20, 100, 2, &speedText, 0 },
+ { TOGGLE, NOFUNC, NULL, SIX_STITLE_TOGGLE, 142, 20+40, 23, 19, &bSubtitles, 0 },
+
+ { ARSGBUT, CLANG, NULL, USE_POINTER, 230, 110, 23, 19, NULL, IX_TICK1 },
+ { AAGBUT, RLANG, NULL, USE_POINTER, 230, 140, 23, 19, NULL, IX_CROSS1 }
+
+};
+
+CONFBOX subtitlesBox4Flags[] = {
+
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 20, 100, 56, 32, NULL, FIX_FR },
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 108, 100, 56, 32, NULL, FIX_GR },
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 64, 137, 56, 32, NULL, FIX_IT },
+ { FRGROUP, NOFUNC, NULL, USE_POINTER, 152, 137, 56, 32, NULL, FIX_SP },
+
+ { SLIDER, NOFUNC, NULL, SIX_TSPEED_SLIDER, 142, 20, 100, 2, &speedText, 0 },
+ { TOGGLE, NOFUNC, NULL, SIX_STITLE_TOGGLE, 142, 20+40, 23, 19, &bSubtitles, 0 },
+
+ { ARSGBUT, CLANG, NULL, USE_POINTER, 230, 110, 23, 19, NULL, IX_TICK1 },
+ { AAGBUT, RLANG, NULL, USE_POINTER, 230, 140, 23, 19, NULL, IX_CROSS1 }
+
+};
+
+CONFBOX subtitlesBox5Flags[] = {
+
{ FRGROUP, NOFUNC, NULL, USE_POINTER, 15, 100, 56, 32, NULL, FIX_UK },
{ FRGROUP, NOFUNC, NULL, USE_POINTER, 85, 100, 56, 32, NULL, FIX_FR },
{ FRGROUP, NOFUNC, NULL, USE_POINTER, 155, 100, 56, 32, NULL, FIX_GR },
{ FRGROUP, NOFUNC, NULL, USE_POINTER, 50, 137, 56, 32, NULL, FIX_IT },
{ FRGROUP, NOFUNC, NULL, USE_POINTER, 120, 137, 56, 32, NULL, FIX_SP },
-#endif
-#ifdef USE_4FLAGS
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 20, 100, 56, 32, NULL, FIX_FR },
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 108, 100, 56, 32, NULL, FIX_GR },
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 64, 137, 56, 32, NULL, FIX_IT },
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 152, 137, 56, 32, NULL, FIX_SP },
-#endif
-#ifdef USE_3FLAGS
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 15, 118, 56, 32, NULL, FIX_FR },
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 85, 118, 56, 32, NULL, FIX_GR },
- { FRGROUP, NOFUNC, NULL, USE_POINTER, 155, 118, 56, 32, NULL, FIX_SP },
-#endif
{ SLIDER, NOFUNC, NULL, SIX_TSPEED_SLIDER, 142, 20, 100, 2, &speedText, 0 },
{ TOGGLE, NOFUNC, NULL, SIX_STITLE_TOGGLE, 142, 20+40, 23, 19, &bSubtitles, 0 },
-#if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
{ ARSGBUT, CLANG, NULL, USE_POINTER, 230, 110, 23, 19, NULL, IX_TICK1 },
{ AAGBUT, RLANG, NULL, USE_POINTER, 230, 140, 23, 19, NULL, IX_CROSS1 }
-#endif
};
-#endif
/*-------------------------------------------------------------*\
@@ -610,7 +623,7 @@ CONFBOX subtitlesBox[] = {
\*-------------------------------------------------------------*/
CONFBOX quitBox[] = {
-#ifdef JAPAN
+#ifdef g
{ AAGBUT, IQUITGAME, NULL, USE_POINTER,70, 44, 23, 19, NULL, IX_TICK1 },
{ AAGBUT, CLOSEWIN, NULL, USE_POINTER, 30, 44, 23, 19, NULL, IX_CROSS1 }
#else
@@ -652,13 +665,9 @@ CONFINIT ciSound = { 10, 5, 20, 16, false, soundBox, ARRAYSIZE(soundBox), NO_HEA
#else
CONFINIT ciControl = { 10, 5, 20, 16, false, controlBox, ARRAYSIZE(controlBox), NO_HEADING };
#endif
-#ifndef JAPAN
-#if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
-CONFINIT ciSubtitles = { 10, 6, 20, 16, false, subtitlesBox, ARRAYSIZE(subtitlesBox), NO_HEADING };
-#else
+
CONFINIT ciSubtitles = { 10, 3, 20, 16, false, subtitlesBox, ARRAYSIZE(subtitlesBox), NO_HEADING };
-#endif
-#endif
+
CONFINIT ciQuit = { 4, 2, 98, 53, false, quitBox, ARRAYSIZE(quitBox), SIX_QUIT_HEADING };
CONFINIT ciTopWin = { 6, 5, 72, 23, false, topwinBox, 0, NO_HEADING };
@@ -762,45 +771,39 @@ static void ConfActionSpecial(int i);
-#ifndef JAPAN
bool LanguageChange(void) {
- LANGUAGE nLang;
-
-#ifdef USE_3FLAGS
- // VERY quick dodgy bodge
- if (cd.selBox == 0)
- nLang = TXT_FRENCH;
- else if (cd.selBox == 1)
- nLang = TXT_GERMAN;
- else
- nLang = TXT_SPANISH;
- if (nLang != language) {
-#elif defined(USE_4FLAGS)
- nLang = (LANGUAGE)(cd.selBox + 1);
- if (nLang != language) {
-#else
- if (cd.selBox != language) {
+ LANGUAGE nLang = TXT_ENGLISH;
+
+ if (_vm->getFeatures() & GF_USE_3FLAGS) {
+ // VERY quick dodgy bodge
+ if (cd.selBox == 0)
+ nLang = TXT_FRENCH; // = 1
+ else if (cd.selBox == 1)
+ nLang = TXT_GERMAN; // = 2
+ else
+ nLang = TXT_SPANISH; // = 4
+ } else if (_vm->getFeatures() & GF_USE_4FLAGS) {
+ nLang = (LANGUAGE)(cd.selBox + 1);
+ } else if (_vm->getFeatures() & GF_USE_5FLAGS) {
nLang = (LANGUAGE)cd.selBox;
-#endif
+ }
+
+ if (nLang != g_language) {
KillInventory();
ChangeLanguage(nLang);
- language = nLang;
+ g_language = nLang;
return true;
- }
- else
+ } else
return false;
}
-#endif
/**************************************************************************/
/******************** Some miscellaneous functions ************************/
/**************************************************************************/
-/*---------------------------------------------------------------------*\
-| DumpIconArray()/DumpDobjArray()/DumpObjArray() |
-|-----------------------------------------------------------------------|
-| Delete all the objects in iconArray[]/DobjArray[]/objArray[] |
-\*---------------------------------------------------------------------*/
+/**
+ * Delete all the objects in iconArray[]
+ */
static void DumpIconArray(void){
for (int i = 0; i < MAX_ICONS; i++) {
if (iconArray[i] != NULL) {
@@ -813,7 +816,6 @@ static void DumpIconArray(void){
/**
* Delete all the objects in DobjArray[]
*/
-
static void DumpDobjArray(void) {
for (int i = 0; i < MAX_WCOMP; i++) {
if (DobjArray[i] != NULL) {
@@ -826,7 +828,6 @@ static void DumpDobjArray(void) {
/**
* Delete all the objects in objArray[]
*/
-
static void DumpObjArray(void) {
for (int i = 0; i < MAX_WCOMP; i++) {
if (objArray[i] != NULL) {
@@ -886,7 +887,6 @@ bool IsInInventory(int object, int invnum) {
/**
* Returns which item is held (INV_NOICON (-1) if none)
*/
-
int WhichItemHeld(void) {
return HeldItem;
}
@@ -895,7 +895,6 @@ int WhichItemHeld(void) {
* Called from the cursor module when it re-initialises (at the start of
* a new scene). For if we are holding something at scene-change time.
*/
-
void InventoryIconCursor(void) {
INV_OBJECT *invObj;
@@ -908,7 +907,6 @@ void InventoryIconCursor(void) {
/**
* Returns TRUE if the inventory is active.
*/
-
bool InventoryActive(void) {
return (InventoryState == ACTIVE_INV);
}
@@ -1214,8 +1212,8 @@ void Select(int i, bool force) {
break;
-#if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
case FRGROUP:
+ assert((_vm->getFeatures() & GF_USE_3FLAGS) || (_vm->getFeatures() & GF_USE_4FLAGS) || (_vm->getFeatures() & GF_USE_5FLAGS));
iconArray[HL2] = RectangleObject(BackPal(), COL_HILIGHT, cd.Box[i].w+6, cd.Box[i].h+6);
MultiInsertObject(GetPlayfieldList(FIELD_STATUS), iconArray[HL2]);
MultiSetAniXY(iconArray[HL2],
@@ -1224,7 +1222,7 @@ void Select(int i, bool force) {
MultiSetZPosition(iconArray[HL2], Z_INV_BRECT+1);
break;
-#endif
+
default:
break;
}
@@ -1276,7 +1274,6 @@ void DropItem(int item) {
* Stick the item into an inventory list (ItemOrder[]), and hold the
* item if requested.
*/
-
void AddToInventory(int invno, int icon, bool hold) {
int i;
bool bOpen;
@@ -1407,12 +1404,12 @@ int InvArea(int x, int y) {
int RightX = MultiRightmost(RectObject) + 1;
int BottomY = MultiLowest(RectObject) + 1;
-// Outside the whole rectangle?
+ // Outside the whole rectangle?
if (x <= LeftX - EXTRA || x > RightX + EXTRA
|| y <= TopY - EXTRA || y > BottomY + EXTRA)
return I_NOTIN;
-// The bottom line
+ // The bottom line
if (y > BottomY - 2 - EXTRA) { // Below top of bottom line?
if (x <= LeftX + 2 + EXTRA)
return I_BLEFT; // Bottom left corner
@@ -1422,7 +1419,7 @@ int InvArea(int x, int y) {
return I_BOTTOM; // Just plain bottom
}
-// The top line
+ // The top line
if (y <= TopY + 2 + EXTRA) { // Above bottom of top line?
if (x <= LeftX + 2 + EXTRA)
return I_TLEFT; // Top left corner
@@ -1432,24 +1429,24 @@ int InvArea(int x, int y) {
return I_TOP; // Just plain top
}
-// Sides
+ // Sides
if (x <= LeftX + 2 + EXTRA) // Left of right of left side?
return I_LEFT;
else if (x > RightX - 2 - EXTRA) // Right of left of right side?
return I_RIGHT;
-// From here down still needs fixing up properly
-/*
-* In the move area?
-*/
+ // From here down still needs fixing up properly
+ /*
+ * In the move area?
+ */
if (ino != INV_CONF
&& x >= LeftX + M_SW - 2 && x <= RightX - M_SW + 3 &&
y >= TopY + M_TH - 2 && y < TopY + M_TBB + 2)
return I_MOVE;
-/*
-* Scroll bits
-*/
+ /*
+ * Scroll bits
+ */
if (ino == INV_CONF && cd.bExtraWin) {
} else {
if (x > RightX - M_IAL + 3 && x <= RightX - M_IAR + 1) {
@@ -1476,7 +1473,6 @@ int InvArea(int x, int y) {
* Returns the id of the icon displayed under the given position.
* Also return co-ordinates of items tag display position, if requested.
*/
-
int InvItem(int *x, int *y, bool update) {
int itop, ileft;
int row, col;
@@ -1510,7 +1506,6 @@ int InvItem(int *x, int *y, bool update) {
/**
* Returns the id of the icon displayed under the given position.
*/
-
int InvItemId(int x, int y) {
int itop, ileft;
int row, col;
@@ -1539,21 +1534,21 @@ int InvItemId(int x, int y) {
return INV_NOICON;
}
-/*---------------------------------------------------------------------*\
-| WhichInvBox() |
-|-----------------------------------------------------------------------|
-| Finds which box the cursor is in. |
-\*---------------------------------------------------------------------*/
-#define MD_YSLIDTOP 7
-#define MD_YSLIDBOT 18
-#define MD_YBUTTOP 9
-#define MD_YBUTBOT 16
-#define MD_XLBUTL 1
-#define MD_XLBUTR 10
-#define MD_XRBUTL 105
-#define MD_XRBUTR 114
-
+/**
+ * Finds which box the cursor is in.
+ */
static int WhichInvBox(int curX, int curY, bool bSlides) {
+ enum {
+ MD_YSLIDTOP = 7,
+ MD_YSLIDBOT = 18,
+ MD_YBUTTOP = 9,
+ MD_YBUTBOT = 16,
+ MD_XLBUTL = 1,
+ MD_XLBUTR = 10,
+ MD_XRBUTL = 105,
+ MD_XRBUTR = 114
+ };
+
if (bSlides) {
for (int i = 0; i < numMdSlides; i++) {
if (curY > MultiHighest(mdSlides[i].obj) && curY < MultiLowest(mdSlides[i].obj)
@@ -1841,7 +1836,6 @@ void InvLabels(bool InBody, int aniX, int aniY) {
* It seems to set up slideStuff[], an array of possible first-displayed
* icons set against the matching y-positions of the slider.
*/
-
void AdjustTop(void) {
int tMissing, bMissing, nMissing;
int nslideY;
@@ -1904,7 +1898,6 @@ void AdjustTop(void) {
/**
* Insert an inventory icon object onto the display list.
*/
-
OBJECT *AddInvObject(int num, const FREEL **pfreel, const FILM **pfilm) {
INV_OBJECT *invObj; // Icon data
const MULTI_INIT *pmi; // Its INIT structure - from the reel
@@ -1929,7 +1922,6 @@ OBJECT *AddInvObject(int num, const FREEL **pfreel, const FILM **pfilm) {
/**
* Create display objects for the displayed icons in an inventory window.
*/
-
void FillInInventory(void) {
int Index; // Index into ItemOrder[]
int n = 0; // index into iconArray[]
@@ -2010,7 +2002,6 @@ void AddBackground(OBJECT **rect, OBJECT **title, int extraH, int extraV, int te
/**
* Insert a part of the inventory window frame onto the display list.
*/
-
static OBJECT *AddObject(const FREEL *pfreel, int num) {
const MULTI_INIT *pmi; // Get the MULTI_INIT structure
IMAGE *pim;
@@ -2043,7 +2034,6 @@ static OBJECT *AddObject(const FREEL *pfreel, int num) {
/**
* Display the scroll bar slider.
*/
-
void AddSlider(OBJECT **slide, const FILM *pfilm) {
SlideObject = *slide = AddObject(&pfilm->reels[IX_SLIDE], -1);
MultiSetAniXY(*slide, MultiRightmost(RectObject)-M_SXOFF+2, InvD[ino].inventoryY + slideY);
@@ -2062,7 +2052,6 @@ enum {
/**
* Display a box with some text in it.
*/
-
void AddBox(int *pi, int i) {
int x = InvD[ino].inventoryX + cd.Box[i].xpos;
int y = InvD[ino].inventoryY + cd.Box[i].ypos;
@@ -2126,8 +2115,8 @@ void AddBox(int *pi, int i) {
break;
-#if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
case FRGROUP:
+ assert((_vm->getFeatures() & GF_USE_3FLAGS) || (_vm->getFeatures() & GF_USE_4FLAGS) || (_vm->getFeatures() & GF_USE_5FLAGS));
assert(flagFilm != 0); // Language flags not declared!
pfilm = (const FILM *)LockMem(flagFilm);
@@ -2141,7 +2130,7 @@ void AddBox(int *pi, int i) {
*pi += 1;
break;
-#endif
+
case FLIP:
pfilm = (const FILM *)LockMem(winPartsf);
@@ -2234,7 +2223,6 @@ static void AddBoxes(bool posnSlide) {
/**
* Display the scroll bar slider.
*/
-
void AddEWSlider(OBJECT **slide, const FILM *pfilm) {
SlideObject = *slide = AddObject(&pfilm->reels[IX_SLIDE], -1);
MultiSetAniXY(*slide, InvD[ino].inventoryX + 24 + 127, slideY);
@@ -2244,7 +2232,6 @@ void AddEWSlider(OBJECT **slide, const FILM *pfilm) {
/**
* AddExtraWindow
*/
-
int AddExtraWindow(int x, int y, OBJECT **retObj) {
int n = 0;
const FILM *pfilm;
@@ -2479,7 +2466,7 @@ void ConstructInventory(InventoryType filling) {
OBJECT **rect, **title;
-// Draw background, slider and icons
+ // Draw background, slider and icons
if (filling == FULL) {
rect = &retObj[n++];
title = &retObj[n++];
@@ -2495,8 +2482,7 @@ void ConstructInventory(InventoryType filling) {
}
FillInInventory();
- }
- else if (filling == CONF) {
+ } else if (filling == CONF) {
rect = &retObj[n++];
title = &retObj[n++];
@@ -2800,7 +2786,6 @@ bool convHid(void) {
/**
* Start up an inventory window.
*/
-
void PopUpInventory(int invno) {
assert((invno == INV_1 || invno == INV_2 || invno == INV_CONV || invno == INV_CONF)); // Trying to open illegal inventory
@@ -2849,7 +2834,6 @@ void SetConfGlobals(CONFINIT *ci) {
/**
* PopupConf
*/
-
void PopUpConf(CONFTYPE type) {
int curX, curY;
@@ -2903,11 +2887,27 @@ void PopUpConf(CONFTYPE type) {
SetConfGlobals(&ciSound);
break;
-#ifndef JAPAN
case SUBT:
+ if (_vm->getFeatures() & GF_USE_3FLAGS) {
+ ciSubtitles.v = 6;
+ ciSubtitles.Box = subtitlesBox3Flags;
+ ciSubtitles.NumBoxes = ARRAYSIZE(subtitlesBox3Flags);
+ } else if (_vm->getFeatures() & GF_USE_4FLAGS) {
+ ciSubtitles.v = 6;
+ ciSubtitles.Box = subtitlesBox4Flags;
+ ciSubtitles.NumBoxes = ARRAYSIZE(subtitlesBox4Flags);
+ } else if (_vm->getFeatures() & GF_USE_5FLAGS) {
+ ciSubtitles.v = 6;
+ ciSubtitles.Box = subtitlesBox4Flags;
+ ciSubtitles.NumBoxes = ARRAYSIZE(subtitlesBox4Flags);
+ } else {
+ ciSubtitles.v = 3;
+ ciSubtitles.Box = subtitlesBox;
+ ciSubtitles.NumBoxes = ARRAYSIZE(subtitlesBox);
+ }
+
SetConfGlobals(&ciSubtitles);
break;
-#endif
case TOPWIN:
SetConfGlobals(&ciTopWin);
@@ -2927,25 +2927,21 @@ void PopUpConf(CONFTYPE type) {
if (type == SAVE || type == LOAD)
Select(0, false);
-#ifndef JAPAN
-#if !defined(USE_3FLAGS) || !defined(USE_4FLAGS) || !defined(USE_5FLAGS)
else if (type == SUBT) {
-#ifdef USE_3FLAGS
- // VERY quick dirty bodges
- if (language == TXT_FRENCH)
- Select(0, false);
- else if (language == TXT_GERMAN)
- Select(1, false);
- else
- Select(2, false);
-#elif defined(USE_4FLAGS)
- Select(language-1, false);
-#else
- Select(language, false);
-#endif
+ if (_vm->getFeatures() & GF_USE_3FLAGS) {
+ // VERY quick dirty bodges
+ if (g_language == TXT_FRENCH)
+ Select(0, false);
+ else if (g_language == TXT_GERMAN)
+ Select(1, false);
+ else
+ Select(2, false);
+ } else if (_vm->getFeatures() & GF_USE_4FLAGS) {
+ Select(g_language-1, false);
+ } else if (_vm->getFeatures() & GF_USE_5FLAGS) {
+ Select(g_language, false);
+ }
}
-#endif
-#endif // JAPAN
GetCursorXY(&curX, &curY, false);
InvCursor(IC_AREA, curX, curY);
@@ -2954,7 +2950,6 @@ void PopUpConf(CONFTYPE type) {
/**
* Close down an inventory window.
*/
-
void KillInventory(void) {
if (objArray[0] != NULL) {
DumpObjArray();
@@ -2976,6 +2971,9 @@ void KillInventory(void) {
if (bOpenConf) {
bOpenConf = false;
PopUpConf(OPTION);
+
+ // Write config changes
+ WriteConfig();
} else if (ino == INV_CONF)
InventoryIconCursor();
}
@@ -3073,7 +3071,7 @@ void InventoryProcess(CORO_PARAM, const void *) {
InvLoadGame();
break;
case IQUITGAME:
- _vm->quitFlag = true;
+ _vm->quitGame();
break;
case CLOSEWIN:
KillInventory();
@@ -3098,12 +3096,10 @@ void InventoryProcess(CORO_PARAM, const void *) {
KillInventory();
PopUpConf(CONTROLS);
break;
- #ifndef JAPAN
case OPENSUBT:
KillInventory();
PopUpConf(SUBT);
break;
- #endif
case OPENQUIT:
KillInventory();
PopUpConf(QUIT);
@@ -3112,7 +3108,6 @@ void InventoryProcess(CORO_PARAM, const void *) {
KillInventory();
bRestart = true;
break;
- #if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
case CLANG:
if (!LanguageChange())
KillInventory();
@@ -3120,7 +3115,6 @@ void InventoryProcess(CORO_PARAM, const void *) {
case RLANG:
KillInventory();
break;
- #endif
default:
break;
}
@@ -3344,10 +3338,8 @@ static void SlideMSlider(int x, SSFN fn) {
case S_END: // End of a drag on the slider
AddBoxes(false); // Might change position slightly
-#ifndef JAPAN
if (ino == INV_CONF && cd.Box == subtitlesBox)
- Select(language, false);
-#endif
+ Select(g_language, false);
break;
}
}
@@ -3780,8 +3772,8 @@ void ConfAction(int i, bool dbl) {
}
break;
-#if defined(USE_3FLAGS) || defined(USE_4FLAGS) || defined(USE_5FLAGS)
case FRGROUP:
+ assert((_vm->getFeatures() & GF_USE_3FLAGS) || (_vm->getFeatures() & GF_USE_4FLAGS) || (_vm->getFeatures() & GF_USE_5FLAGS));
if (dbl) {
Select(i, false);
LanguageChange();
@@ -3789,7 +3781,6 @@ void ConfAction(int i, bool dbl) {
Select(i, false);
}
break;
-#endif
case AAGBUT:
case ARSGBUT:
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 7d4efd8079..d165ba0a10 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -263,7 +263,7 @@ int GetMidiVolume() {
* @param vol New volume - 0..MAXMIDIVOL
*/
void SetMidiVolume(int vol) {
- assert(vol >= 0 && vol <= MAXMIDIVOL);
+ assert(vol >= 0 && vol <= Audio::Mixer::kMaxChannelVolume);
if (vol == 0 && volMidi == 0) {
// Nothing to do
@@ -343,10 +343,6 @@ MusicPlayer::~MusicPlayer() {
}
void MusicPlayer::setVolume(int volume) {
- Common::StackLock lock(_mutex);
-
- // FIXME: Could we simply change MAXMIDIVOL to match ScummVM's range?
- volume = CLIP((255 * volume) / MAXMIDIVOL, 0, 255);
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
if (_masterVolume == volume)
@@ -354,6 +350,8 @@ void MusicPlayer::setVolume(int volume) {
_masterVolume = volume;
+ Common::StackLock lock(_mutex);
+
for (int i = 0; i < 16; ++i) {
if (_channel[i]) {
_channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index 80456e2a76..3d647f95bf 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -34,8 +34,6 @@
namespace Tinsel {
-#define MAXMIDIVOL 127
-
bool PlayMidiSequence( // Plays the specified MIDI sequence through the sound driver
uint32 dwFileOffset, // handle of MIDI sequence data
bool bLoop); // Whether to loop the sequence
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index 1a6cc1202a..acdaf6c0bb 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -246,16 +246,11 @@ static char *NewName(void) {
* Store the file details, ordered by time, in savedFiles[] and return
* the number of files found).
*/
-int getList(void) {
- // No change since last call?
- // TODO/FIXME: Just always reload this data? Be careful about slow downs!!!
- if (!NeedLoad)
- return numSfiles;
-
+int getList(Common::SaveFileManager *saveFileMan, const Common::String &target) {
int i;
- const Common::String pattern = _vm->getSavegamePattern();
- Common::StringList files = _vm->getSaveFileMan()->listSavefiles(pattern.c_str());
+ const Common::String pattern = target + ".???";
+ Common::StringList files = saveFileMan->listSavefiles(pattern.c_str());
numSfiles = 0;
@@ -264,7 +259,7 @@ int getList(void) {
break;
const Common::String &fname = *file;
- Common::InSaveFile *f = _vm->getSaveFileMan()->openForLoading(fname.c_str());
+ Common::InSaveFile *f = saveFileMan->openForLoading(fname.c_str());
if (f == NULL) {
continue;
}
@@ -304,6 +299,15 @@ int getList(void) {
return numSfiles;
}
+int getList(void) {
+ // No change since last call?
+ // TODO/FIXME: Just always reload this data? Be careful about slow downs!!!
+ if (!NeedLoad)
+ return numSfiles;
+
+ return getList(_vm->getSaveFileMan(), _vm->getTargetName());
+}
+
char *ListEntry(int i, letype which) {
if (i == -1)
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index e2a24dbd47..e37c80ec61 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -74,7 +74,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
assert(id > 0 && id < _sampleIndexLen);
// get file offset for this sample
- uint32 dwSampleIndex = _sampleIndex[id];
+ int32 dwSampleIndex = _sampleIndex[id];
// move to correct position in the sample file
_sampleStream.seek(dwSampleIndex);
@@ -166,7 +166,7 @@ void SoundManager::openSampleFiles(void) {
if (_sampleIndex == NULL) {
// allocate a buffer for the indices
- _sampleIndex = (uint32 *)malloc(_sampleIndexLen);
+ _sampleIndex = (int32 *)malloc(_sampleIndexLen);
// make sure memory allocated
if (_sampleIndex == NULL) {
diff --git a/engines/tinsel/sound.h b/engines/tinsel/sound.h
index 56618eeb8e..330409cf59 100644
--- a/engines/tinsel/sound.h
+++ b/engines/tinsel/sound.h
@@ -37,7 +37,6 @@
namespace Tinsel {
-#define MAXSAMPVOL 127
/*----------------------------------------------------------------------*\
|* Function Prototypes *|
@@ -52,7 +51,7 @@ protected:
Audio::SoundHandle _handle;
/** Sample index buffer and number of entries */
- uint32 *_sampleIndex;
+ int32 *_sampleIndex;
/** Number of entries in the sample index */
long _sampleIndexLen;
diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp
index e8364e20dd..07c1b22b2a 100644
--- a/engines/tinsel/tinlib.cpp
+++ b/engines/tinsel/tinlib.cpp
@@ -1271,7 +1271,7 @@ void printtag(HPOLYGON hp, SCNHANDLE text) {
void quitgame(void) {
stopmidi();
stopsample();
- _vm->quitFlag = true;
+ _vm->quitGame();
}
/**
@@ -1991,7 +1991,6 @@ void topplay(CORO_PARAM, SCNHANDLE film, int x, int y, int complete, int actorid
/**
* Open or close the 'top window'
*/
-
void topwindow(int bpos) {
assert(bpos == TW_START || bpos == TW_END);
@@ -2010,7 +2009,6 @@ void topwindow(int bpos) {
/**
* unhookscene
*/
-
void unhookscene(void) {
UnHookScene();
}
@@ -2018,7 +2016,6 @@ void unhookscene(void) {
/**
* Un-define an actor as tagged.
*/
-
void untagactor(int actor) {
UnTagActor(actor);
}
@@ -2026,14 +2023,12 @@ void untagactor(int actor) {
/**
* vibrate
*/
-
void vibrate(void) {
}
/**
* waitframe(int actor, int frameNumber)
*/
-
void waitframe(CORO_PARAM, int actor, int frameNumber, bool escOn, int myescEvent) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -2056,7 +2051,6 @@ void waitframe(CORO_PARAM, int actor, int frameNumber, bool escOn, int myescEven
/**
* Return when a key pressed or button pushed.
*/
-
void waitkey(CORO_PARAM, bool escOn, int myescEvent) {
CORO_BEGIN_CONTEXT;
int startEvent;
@@ -2104,7 +2098,6 @@ void waitkey(CORO_PARAM, bool escOn, int myescEvent) {
/**
* Pause for requested time.
*/
-
void waittime(CORO_PARAM, int time, bool frame, bool escOn, int myescEvent) {
CORO_BEGIN_CONTEXT;
int time;
@@ -2261,7 +2254,6 @@ void walkingactor(uint32 id, SCNHANDLE *rp) {
* Walk a moving actor towards the polygon's tag, but return when the
* actor enters the polygon.
*/
-
void walkpoly(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int myescEvent) {
// COROUTINE
CORO_BEGIN_CONTEXT;
@@ -2309,7 +2301,6 @@ void walkpoly(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, in
/**
* walktag(actor, reel, hold)
*/
-
void walktag(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int myescEvent) {
// COROUTINE
CORO_BEGIN_CONTEXT;
@@ -2385,7 +2376,6 @@ void walktag(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int
/**
* whichinventory
*/
-
int whichinventory(void) {
return WhichInventoryOpen();
}
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 1f56385283..7fb949704a 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -206,13 +206,16 @@ void KeyboardProcess(CORO_PARAM, const void *) {
{
int sceneOffset = (_vm->getFeatures() & GF_SCNFILES) ? 1 : 0;
int sceneNumber = (GetSceneHandle() >> SCNHANDLE_SHIFT) - sceneOffset;
- if ((language == TXT_GERMAN) &&
+#if 0 // FIXME: Disabled this code for now, as it doesn't work as it should (see bug #2078922).
+ if ((g_language == TXT_GERMAN) &&
((sceneNumber >= 25 && sceneNumber <= 27) || (sceneNumber == 17))) {
// Skip to title screen
// It seems the German CD version uses scenes 25,26,27,17 for the intro,
// instead of 13,14,15,11; also, the title screen is 11 instead of 10
SetNewScene((11 + sceneOffset) << SCNHANDLE_SHIFT, 1, TRANS_CUT);
- } else if ((sceneNumber >= 13) && (sceneNumber <= 15) || (sceneNumber == 11)) {
+ } else
+#endif
+ if ((sceneNumber >= 13) && (sceneNumber <= 15) || (sceneNumber == 11)) {
// Skip to title screen
SetNewScene((10 + sceneOffset) << SCNHANDLE_SHIFT, 1, TRANS_CUT);
} else {
@@ -622,11 +625,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
//bool adlib = (midiDriver == MD_ADLIB);
- MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ _driver = MidiDriver::createMidi(midiDriver);
if (native_mt32)
- driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- _music = new MusicPlayer(driver);
+ _music = new MusicPlayer(_driver);
//_music->setNativeMT32(native_mt32);
//_music->setAdlib(adlib);
@@ -638,13 +641,14 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
_mousePos.y = 0;
_keyHandler = NULL;
_dosPlayerDir = 0;
- quitFlag = false;
}
TinselEngine::~TinselEngine() {
delete _sound;
delete _music;
delete _console;
+ delete _driver;
+ _screenSurface.free();
FreeSs();
FreeTextBuffer();
FreeHandleTable();
@@ -678,6 +682,8 @@ int TinselEngine::init() {
#if 1
// FIXME: The following is taken from RestartGame().
// It may have to be adjusted a bit
+ CountOut = 1;
+
RebootCursor();
RebootDeadTags();
RebootMovers();
@@ -692,25 +698,8 @@ int TinselEngine::init() {
// TODO: More stuff from dos_main.c may have to be added here
- // Set language - we'll be clever here and use the ScummVM language setting
- language = TXT_ENGLISH;
- switch (getLanguage()) {
- case Common::FR_FRA:
- language = TXT_FRENCH;
- break;
- case Common::DE_DEU:
- language = TXT_GERMAN;
- break;
- case Common::IT_ITA:
- language = TXT_ITALIAN;
- break;
- case Common::ES_ESP:
- language = TXT_SPANISH;
- break;
- default:
- language = TXT_ENGLISH;
- }
- ChangeLanguage(language);
+ // load in text strings
+ ChangeLanguage(g_language);
// load in graphics info
SetupHandleTable();
@@ -721,10 +710,6 @@ int TinselEngine::init() {
return 0;
}
-Common::String TinselEngine::getSavegamePattern() const {
- return _targetName + ".???";
-}
-
Common::String TinselEngine::getSavegameFilename(int16 saveNum) const {
char filename[256];
snprintf(filename, 256, "%s.%03d", getTargetName().c_str(), saveNum);
@@ -755,7 +740,7 @@ int TinselEngine::go() {
// Foreground loop
- while (!quitFlag) {
+ while (!quit()) {
assert(_console);
if (_console->isAttached())
_console->onFrame();
@@ -819,10 +804,6 @@ bool TinselEngine::pollEvent() {
// Handle the various kind of events
switch (event.type) {
- case Common::EVENT_QUIT:
- quitFlag = true;
- break;
-
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONDOWN:
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 44cc83af9b..9820be7ddd 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -55,12 +55,19 @@ enum TinselGameFeatures {
GF_DEMO = 1 << 0,
GF_CD = 1 << 1,
GF_FLOPPY = 1 << 2,
- GF_SCNFILES = 1 << 3
+ GF_SCNFILES = 1 << 3,
+
+ // The GF_USE_?FLAGS values specify how many country flags are displayed
+ // in the subtitles options dialog.
+ // None of these defined -> 1 language, in ENGLISH.TXT
+ GF_USE_3FLAGS = 1 << 4, // French, German, Spanish
+ GF_USE_4FLAGS = 1 << 5, // French, German, Spanish, Italian
+ GF_USE_5FLAGS = 1 << 6 // All 5 flags
};
enum TinselEngineVersion {
- TINSEL_V0 = 1 << 0, // Used in the DW1 demo only
- TINSEL_V1 = 1 << 1
+ TINSEL_V0 = 0, // Used in the DW1 demo only
+ TINSEL_V1 = 1
};
struct TinselGameDescription;
@@ -72,7 +79,7 @@ enum TinselKeyDirection {
typedef bool (*KEYFPTR)(const Common::KeyState &);
-class TinselEngine : public ::Engine {
+class TinselEngine : public Engine {
int _gameId;
Common::KeyState _keyPressed;
Common::RandomSource _random;
@@ -100,8 +107,8 @@ public:
Common::Language getLanguage() const;
uint16 getVersion() const;
Common::Platform getPlatform() const;
- bool quitFlag;
+ MidiDriver *_driver;
SoundManager *_sound;
MusicPlayer *_music;
@@ -120,7 +127,6 @@ private:
public:
const Common::String getTargetName() const { return _targetName; }
- Common::String getSavegamePattern() const;
Common::String getSavegameFilename(int16 saveNum) const;
Common::SaveFileManager *getSaveFileMan() { return _saveFileMan; }
Graphics::Surface &screen() { return _screenSurface; }
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index d2798d7060..bbc605ba46 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -25,6 +25,7 @@
#include "common/config-manager.h"
#include "common/advancedDetector.h"
+#include "common/savefile.h"
#include "base/plugins.h"
@@ -135,9 +136,20 @@ public:
return "Touche: The Adventures of the 5th Musketeer (C) Clipper Software";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
};
+bool ToucheMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDirectLoad) ||
+ (f == kSupportsDeleteSave);
+}
+
bool ToucheMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Common::ADGameDescription *gd = desc;
if (gd) {
@@ -146,6 +158,67 @@ bool ToucheMetaEngine::createInstance(OSystem *syst, Engine **engine, const Comm
return gd != 0;
}
+SaveStateList ToucheMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringList filenames;
+ char saveDesc[Touche::kGameStateDescriptionLen];
+ Common::String pattern = target;
+ pattern += ".?";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last digit of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 1);
+
+ if (slotNum >= 0 && slotNum <= 9) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ in->readUint16LE();
+ in->readUint16LE();
+ in->read(saveDesc, Touche::kGameStateDescriptionLen);
+ saveList.push_back(SaveStateDescriptor(slotNum, Common::String(saveDesc), *file));
+ delete in;
+ }
+ }
+ }
+
+ pattern += "?";
+
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 2 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 2);
+
+ if (slotNum >= 10 && slotNum <= 99) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ in->readUint16LE();
+ in->readUint16LE();
+ in->read(saveDesc, Touche::kGameStateDescriptionLen);
+ saveList.push_back(SaveStateDescriptor(slotNum, Common::String(saveDesc), *file));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void ToucheMetaEngine::removeSaveState(const char *target, int slot) const {
+ char extension[5];
+ snprintf(extension, sizeof(extension), ".%d", slot);
+
+ Common::String filename = target;
+ filename += extension;
+
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
+
#if PLUGIN_ENABLED_DYNAMIC(TOUCHE)
REGISTER_PLUGIN_DYNAMIC(TOUCHE, PLUGIN_TYPE_ENGINE, ToucheMetaEngine);
#else
diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp
index 6d2d90a572..82490fca38 100644
--- a/engines/touche/menu.cpp
+++ b/engines/touche/menu.cpp
@@ -297,7 +297,7 @@ void ToucheEngine::handleMenuAction(void *menu, int actionId) {
menuData->quit = true;
break;
case kActionQuitGame:
- _flagsTable[611] = 1;
+ quitGame();
menuData->quit = true;
break;
case kActionTextOnly:
@@ -395,10 +395,10 @@ void ToucheEngine::handleOptions(int forceDisplay) {
while (_eventMan->pollEvent(event)) {
const Button *button = 0;
switch (event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
menuData.quit = true;
menuData.exit = true;
- _flagsTable[611] = 1;
break;
case Common::EVENT_LBUTTONDOWN:
button = menuData.findButtonUnderCursor(event.mouse.x, event.mouse.y);
@@ -433,8 +433,9 @@ void ToucheEngine::handleOptions(int forceDisplay) {
_system->delayMillis(10);
}
_fullRedrawCounter = 2;
- if (!menuData.exit && _flagsTable[611] != 0) {
- _flagsTable[611] = displayQuitDialog();
+ if (!menuData.exit && quit()) {
+ if (displayQuitDialog())
+ quitGame();
}
}
}
@@ -556,6 +557,7 @@ int ToucheEngine::displayQuitDialog() {
Common::Event event;
while (_eventMan->pollEvent(event)) {
switch (event.type) {
+ case Common::EVENT_RTL:
case Common::EVENT_QUIT:
quitLoop = true;
ret = 1;
diff --git a/engines/touche/opcodes.cpp b/engines/touche/opcodes.cpp
index 4405c614ac..b2b16eb29d 100644
--- a/engines/touche/opcodes.cpp
+++ b/engines/touche/opcodes.cpp
@@ -408,6 +408,10 @@ void ToucheEngine::op_setFlag() {
case 104:
_currentKeyCharNum = val;
break;
+ case 611:
+ if (val != 0)
+ quitGame();
+ break;
case 612:
_flagsTable[613] = getRandomNumber(val);
break;
diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp
index 4fcf6e114d..fedd40eb76 100644
--- a/engines/touche/saveload.cpp
+++ b/engines/touche/saveload.cpp
@@ -31,11 +31,6 @@
namespace Touche {
-enum {
- kCurrentGameStateVersion = 6,
- kGameStateDescriptionLen = 32
-};
-
static void saveOrLoad(Common::WriteStream &stream, uint16 &i) {
stream.writeUint16LE(i);
}
@@ -292,7 +287,7 @@ void ToucheEngine::loadGameStateData(Common::ReadStream *stream) {
if (stream->readUint32LE() != saveLoadEndMarker) {
warning("Corrupted gamestate data");
// if that ever happens, exit the game
- _flagsTable[611] = 1;
+ quitGame();
}
_flagsTable[614] = roomOffsX;
_flagsTable[615] = roomOffsY;
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index a39517fe32..e122187dcd 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -95,7 +95,7 @@ int ToucheEngine::init() {
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
return 0;
}
@@ -234,6 +234,13 @@ Common::Point ToucheEngine::getMousePos() const {
return _eventMan->getMousePos();
}
+void ToucheEngine::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() {
restart();
@@ -245,10 +252,13 @@ void ToucheEngine::mainLoop() {
_inp_rightMouseButtonPressed = false;
if (ConfMan.hasKey("save_slot")) {
- loadGameState(ConfMan.getInt("save_slot"));
- _newEpisodeNum = 0;
- resetSortedKeyCharsTable();
- showCursor(true);
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0 && saveSlot <= 99) {
+ loadGameState(saveSlot);
+ _newEpisodeNum = 0;
+ resetSortedKeyCharsTable();
+ showCursor(true);
+ }
} else {
_newEpisodeNum = ConfMan.getInt("boot_param");
if (_newEpisodeNum == 0) {
@@ -258,7 +268,7 @@ void ToucheEngine::mainLoop() {
}
uint32 frameTimeStamp = _system->getMillis();
- for (uint32 cycleCounter = 0; _flagsTable[611] == 0; ++cycleCounter) {
+ for (uint32 cycleCounter = 0; !quit(); ++cycleCounter) {
if ((cycleCounter % 3) == 0) {
runCycle();
}
@@ -287,9 +297,6 @@ void ToucheEngine::processEvents(bool handleKeyEvents) {
Common::Event event;
while (_eventMan->pollEvent(event)) {
switch (event.type) {
- case Common::EVENT_QUIT:
- _flagsTable[611] = 1;
- break;
case Common::EVENT_KEYDOWN:
if (!handleKeyEvents) {
break;
@@ -297,7 +304,8 @@ void ToucheEngine::processEvents(bool handleKeyEvents) {
_flagsTable[600] = event.kbd.keycode;
if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
if (_displayQuitDialog) {
- _flagsTable[611] = displayQuitDialog();
+ if (displayQuitDialog())
+ quitGame();
}
} else if (event.kbd.keycode == Common::KEYCODE_F5) {
if (_flagsTable[618] == 0 && !_hideInventoryTexts) {
@@ -1829,7 +1837,7 @@ int ToucheEngine::handleActionMenuUnderCursor(const int16 *actions, int offs, in
_menuRedrawCounter = 2;
Common::Rect rect(0, y, kScreenWidth, y + h);
i = -1;
- while (_inp_rightMouseButtonPressed && _flagsTable[611] == 0) {
+ while (_inp_rightMouseButtonPressed && !quit()) {
Common::Point mousePos = getMousePos();
if (rect.contains(mousePos)) {
int c = (mousePos.y - y) / kTextHeight;
@@ -2692,10 +2700,10 @@ bool ToucheEngine::sortPointsData(int num1, int num2) {
const int md2 = _programWalkTable[num1].point2;
_programPointsTable[md2].order = 0;
}
- bool quit = false;
+ bool quitLoop = false;
int order = 1;
- while (!quit) {
- quit = true;
+ while (!quitLoop) {
+ quitLoop = true;
for (uint i = 0; i < _programWalkTable.size(); ++i) {
const int md1 = _programWalkTable[i].point1;
const int md2 = _programWalkTable[i].point2;
@@ -2703,11 +2711,11 @@ bool ToucheEngine::sortPointsData(int num1, int num2) {
assert((md2 & 0x4000) == 0);
if (_programPointsTable[md1].order == order - 1 && _programPointsTable[md2].order > order) {
_programPointsTable[md2].order = order;
- quit = false;
+ quitLoop = false;
}
if (_programPointsTable[md2].order == order - 1 && _programPointsTable[md1].order > order) {
_programPointsTable[md1].order = order;
- quit = false;
+ quitLoop = false;
}
}
}
@@ -2939,9 +2947,9 @@ void ToucheEngine::markWalkPoints(int keyChar) {
resetPointsData(0);
if (pointsDataNum != -1) {
_programPointsTable[pointsDataNum].order = 1;
- bool quit = false;
- while (!quit) {
- quit = true;
+ bool quitLoop = false;
+ while (!quitLoop) {
+ quitLoop = true;
for (uint i = 0; i < _programWalkTable.size(); ++i) {
int16 md1 = _programWalkTable[i].point1;
int16 md2 = _programWalkTable[i].point2;
@@ -2949,11 +2957,11 @@ void ToucheEngine::markWalkPoints(int keyChar) {
assert((md2 & 0x4000) == 0);
if (_programPointsTable[md1].order != 0 && _programPointsTable[md2].order == 0) {
_programPointsTable[md2].order = 1;
- quit = false;
+ quitLoop = false;
}
if (_programPointsTable[md2].order != 0 && _programPointsTable[md1].order == 0) {
_programPointsTable[md1].order = 1;
- quit = false;
+ quitLoop = false;
}
}
}
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index 41f5c832c5..f341769422 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -328,7 +328,9 @@ enum {
kCursorHeight = 42,
kTextHeight = 16,
kMaxProgramDataSize = 61440,
- kMaxSaveStates = 100
+ kMaxSaveStates = 100,
+ kGameStateDescriptionLen = 32, // Need these two values defined here
+ kCurrentGameStateVersion = 6 // for --list-saves support
};
enum StringType {
@@ -361,6 +363,7 @@ public:
virtual int init();
virtual int go();
+ virtual void syncSoundSettings();
protected:
diff --git a/graphics/dxa_player.cpp b/graphics/dxa_player.cpp
index 28a1bc4dbd..f4c93a51f1 100644
--- a/graphics/dxa_player.cpp
+++ b/graphics/dxa_player.cpp
@@ -24,6 +24,7 @@
*/
#include "common/endian.h"
+#include "common/file.h"
#include "graphics/dxa_player.h"
#include "common/util.h"
diff --git a/graphics/dxa_player.h b/graphics/dxa_player.h
index 5415e440d2..dbe39bbcee 100644
--- a/graphics/dxa_player.h
+++ b/graphics/dxa_player.h
@@ -27,11 +27,7 @@
#define GRAPHICS_DXA_PLAYER_H
#include "common/scummsys.h"
-#include "common/file.h"
-
-namespace Common {
- class File;
-}
+#include "common/stream.h"
namespace Graphics {
diff --git a/graphics/font.cpp b/graphics/font.cpp
index 3e817e3e6c..404e04d18e 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -524,6 +524,7 @@ int bdf_read_bitmaps(Common::SeekableReadStream &fp, NewFontData* pf) {
}
/* read the next non-comment line, returns buf or NULL if EOF*/
+// TODO: Can we use SeekableReadStream::readLine resp. readLine_NEW instead?
char *bdf_getline(Common::SeekableReadStream &fp, char *buf, int len) {
int c;
char *b;
diff --git a/graphics/iff.cpp b/graphics/iff.cpp
index 514fba9cc0..b3846c5d26 100644
--- a/graphics/iff.cpp
+++ b/graphics/iff.cpp
@@ -219,7 +219,7 @@ void PBMDecoder::readBODY(Common::IFFChunk& chunk) {
switch (_bitmapHeader.pack) {
case 0:
- while (!chunk.eos()) {
+ while (!chunk.hasReadAll()) {
((byte*)_surface->pixels)[si++] = chunk.readByte();
}
break;
@@ -245,7 +245,9 @@ PackBitsReadStream::~PackBitsReadStream() {
}
bool PackBitsReadStream::eos() const {
- return _input->eos() & (_rStoragePos == _wStoragePos);
+ //FIXME: eos definition needs to be changed in parallaction engine
+ // which is the only place where this class is used
+ return _input->eos() && (_rStoragePos == _wStoragePos);
}
uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) {
@@ -291,6 +293,9 @@ void PackBitsReadStream::unpack() {
while (_out < _outEnd && !_input->eos()) {
byteRun = _input->readByte();
+ //FIXME: eos definition needs to be changed in parallaction engine
+ // which is the only place where this class is used
+ //if (_input->eos()) break;
if (byteRun <= 127) {
i = byteRun + 1;
for (j = 0; j < i; j++) {
diff --git a/graphics/module.mk b/graphics/module.mk
index b3618ddcfc..d21915803e 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -15,7 +15,7 @@ MODULE_OBJS := \
mpeg_player.o \
primitives.o \
scaler.o \
- scaler/thumbnail.o \
+ scaler/thumbnail_intern.o \
surface.o \
VectorRenderer.o \
VectorRendererSpec.o
diff --git a/graphics/scaler.h b/graphics/scaler.h
index 2cf3f66239..95900de412 100644
--- a/graphics/scaler.h
+++ b/graphics/scaler.h
@@ -78,10 +78,22 @@ enum {
extern void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height);
/**
- * creates a thumbnail from the current screen (without overlay)
+ * Creates a thumbnail from the current screen (without overlay).
+ *
* @param surf a surface (will always have 16 bpp after this for now)
* @return false if a error occured
*/
-extern bool createThumbnailFromScreen(Graphics::Surface* surf);
+extern bool createThumbnailFromScreen(Graphics::Surface *surf);
+
+/**
+ * Creates a thumbnail from a buffer.
+ *
+ * @param surf destination surface (will always have 16 bpp after this for now)
+ * @param pixels raw pixel data
+ * @param w width
+ * @param h height
+ * @param palette palette in RGB format
+ */
+extern bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette);
#endif
diff --git a/graphics/scaler/thumbnail.cpp b/graphics/scaler/thumbnail_intern.cpp
index f1caa5d2e5..bdfa0ff5f6 100644
--- a/graphics/scaler/thumbnail.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -126,70 +126,93 @@ static bool grabScreen565(Graphics::Surface *surf) {
return true;
}
-bool createThumbnailFromScreen(Graphics::Surface* surf) {
- assert(surf);
-
- int screenWidth = g_system->getWidth();
- int screenHeight = g_system->getHeight();
-
- Graphics::Surface screen;
-
- if (!grabScreen565(&screen))
- return false;
+static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
+ uint16 width = in.w;
+ uint16 inHeight = in.h;
- uint16 width = screenWidth;
-
- if (screenWidth < 320) {
+ if (width < 320) {
// Special case to handle MM NES (uses a screen width of 256)
width = 320;
// center MM NES screen
Graphics::Surface newscreen;
- newscreen.create(width, screen.h, screen.bytesPerPixel);
+ newscreen.create(width, in.h, in.bytesPerPixel);
- uint8 *dst = (uint8*)newscreen.getBasePtr((320 - screenWidth) / 2, 0);
- uint8 *src = (uint8*)screen.getBasePtr(0, 0);
- uint16 height = screen.h;
+ uint8 *dst = (uint8*)newscreen.getBasePtr((320 - in.w) / 2, 0);
+ const uint8 *src = (uint8*)in.getBasePtr(0, 0);
+ uint16 height = in.h;
while (height--) {
- memcpy(dst, src, screen.pitch);
+ memcpy(dst, src, in.pitch);
dst += newscreen.pitch;
- src += screen.pitch;
+ src += in.pitch;
}
- screen.free();
- screen = newscreen;
- } else if (screenWidth == 720) {
+ in.free();
+ in = newscreen;
+ } else if (width == 720) {
// Special case to handle Hercules mode
width = 640;
- screenHeight = 400;
+ inHeight = 400;
// cut off menu and so on..
Graphics::Surface newscreen;
- newscreen.create(width, 400, screen.bytesPerPixel);
+ newscreen.create(width, 400, in.bytesPerPixel);
- uint8 *dst = (uint8*)newscreen.getBasePtr(0, (400 - 240) / 2);
- uint8 *src = (uint8*)screen.getBasePtr(41, 28);
+ uint8 *dst = (uint8*)in.getBasePtr(0, (400 - 240) / 2);
+ const uint8 *src = (uint8*)in.getBasePtr(41, 28);
for (int y = 0; y < 240; ++y) {
- memcpy(dst, src, 640 * screen.bytesPerPixel);
+ memcpy(dst, src, 640 * in.bytesPerPixel);
dst += newscreen.pitch;
- src += screen.pitch;
+ src += in.pitch;
}
- screen.free();
- screen = newscreen;
+ in.free();
+ in = newscreen;
}
- uint16 newHeight = !(screenHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;
+ uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;
int gBitFormatBackUp = gBitFormat;
gBitFormat = 565;
- surf->create(kThumbnailWidth, newHeight, sizeof(uint16));
- createThumbnail((const uint8*)screen.pixels, width * sizeof(uint16), (uint8*)surf->pixels, surf->pitch, width, screenHeight);
+ out.create(kThumbnailWidth, newHeight, sizeof(uint16));
+ createThumbnail((const uint8 *)in.pixels, width * sizeof(uint16), (uint8 *)out.pixels, out.pitch, width, inHeight);
gBitFormat = gBitFormatBackUp;
- screen.free();
+ in.free();
return true;
}
+
+bool createThumbnailFromScreen(Graphics::Surface* surf) {
+ assert(surf);
+
+ Graphics::Surface screen;
+
+ if (!grabScreen565(&screen))
+ return false;
+
+ return createThumbnail(*surf, screen);
+}
+
+bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette) {
+ assert(surf);
+
+ Graphics::Surface screen;
+ screen.create(w, h, 2);
+
+ for (uint y = 0; y < screen.h; ++y) {
+ for (uint x = 0; x < screen.w; ++x) {
+ byte r, g, b;
+ r = palette[pixels[y * w + x] * 3];
+ g = palette[pixels[y * w + x] * 3 + 1];
+ b = palette[pixels[y * w + x] * 3 + 2];
+
+ ((uint16 *)screen.pixels)[y * screen.w + x] = RGBToColor<ColorMasks<565> >(r, g, b);
+ }
+ }
+
+ return createThumbnail(*surf, screen);
+}
+
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index a9f3e75886..263a4fd23b 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -66,6 +66,11 @@ void Surface::free() {
bytesPerPixel = 0;
}
+void Surface::copyFrom(const Surface &surf) {
+ create(surf.w, surf.h, surf.bytesPerPixel);
+ memcpy(pixels, surf.pixels, h * pitch);
+}
+
void Surface::hLine(int x, int y, int x2, uint32 color) {
// Clipping
if (y < 0 || y >= h)
diff --git a/graphics/surface.h b/graphics/surface.h
index ff1ddda695..747bda9a26 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -30,7 +30,6 @@
namespace Graphics {
-
/**
* An arbitrary graphics surface, which can be the target (or source) of blit
* operations, font rendering, etc.
@@ -67,6 +66,12 @@ struct Surface {
*/
void free();
+ /**
+ * Copies data from another Surface, this calls *free* on the current surface, to assure
+ * it being clean.
+ */
+ void copyFrom(const Surface &surf);
+
void drawLine(int x0, int y0, int x1, int y1, uint32 color);
void hLine(int x, int y, int x2, uint32 color);
void vLine(int x, int y, int y2, uint32 color);
@@ -76,6 +81,18 @@ struct Surface {
void move(int dx, int dy, int height);
};
+/**
+ * For safe deletion of surface with SharedPtr.
+ * The deleter assures Surface::free is called on
+ * deletion.
+ */
+struct SharedPtrSurfaceDeleter {
+ void operator()(Surface *ptr) {
+ ptr->free();
+ delete ptr;
+ }
+};
+
} // End of namespace Graphics
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
new file mode 100644
index 0000000000..905fea3d93
--- /dev/null
+++ b/graphics/thumbnail.cpp
@@ -0,0 +1,174 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "graphics/thumbnail.h"
+#include "graphics/scaler.h"
+#include "common/endian.h"
+#include "common/system.h"
+
+namespace Graphics {
+
+namespace {
+#define THMB_VERSION 1
+
+struct ThumbnailHeader {
+ uint32 type;
+ uint32 size;
+ byte version;
+ uint16 width, height;
+ byte bpp;
+};
+
+#define ThumbnailHeaderSize (4+4+1+2+2+1)
+
+inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {
+ r = (((color >> 11) & 0x1F) << 3);
+ g = (((color >> 5) & 0x3F) << 2);
+ b = ((color&0x1F) << 3);
+}
+
+bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
+ header.type = in.readUint32BE();
+ // 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 (outputWarnings)
+ warning("couldn't find thumbnail header type");
+ return false;
+ }
+
+ header.size = in.readUint32BE();
+ header.version = in.readByte();
+
+ if (header.version > THMB_VERSION) {
+ if (outputWarnings)
+ warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION);
+ return false;
+ }
+
+ header.width = in.readUint16BE();
+ header.height = in.readUint16BE();
+ header.bpp = in.readByte();
+
+ return true;
+}
+} // end of anonymous namespace
+
+bool checkThumbnailHeader(Common::SeekableReadStream &in) {
+ uint32 position = in.pos();
+ ThumbnailHeader header;
+
+ bool hasHeader = loadHeader(in, header, false);
+
+ in.seek(position, SEEK_SET);
+
+ return hasHeader;
+}
+
+bool skipThumbnailHeader(Common::SeekableReadStream &in) {
+ uint32 position = in.pos();
+ ThumbnailHeader header;
+
+ if (!loadHeader(in, header, false)) {
+ in.seek(position, SEEK_SET);
+ return false;
+ }
+
+ in.seek(header.size - (in.pos() - position), SEEK_CUR);
+ return true;
+}
+
+bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to) {
+ ThumbnailHeader header;
+
+ if (!loadHeader(in, header, true))
+ return false;
+
+ if (header.bpp != 2) {
+ warning("trying to load thumbnail with unsupported bit depth %d", header.bpp);
+ return false;
+ }
+
+ to.create(header.width, header.height, sizeof(OverlayColor));
+
+ OverlayColor *pixels = (OverlayColor *)to.pixels;
+ for (int y = 0; y < to.h; ++y) {
+ for (int x = 0; x < to.w; ++x) {
+ uint8 r, g, b;
+ colorToRGB(in.readUint16BE(), r, g, b);
+
+ // converting to current OSystem Color
+ *pixels++ = g_system->RGBToColor(r, g, b);
+ }
+ }
+
+ return true;
+}
+
+bool saveThumbnail(Common::WriteStream &out) {
+ Graphics::Surface thumb;
+
+ if (!createThumbnailFromScreen(&thumb)) {
+ warning("Couldn't create thumbnail from screen, aborting thumbnail save");
+ return false;
+ }
+
+ bool success = saveThumbnail(out, thumb);
+ thumb.free();
+
+ return success;
+}
+
+bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) {
+ if (thumb.bytesPerPixel != 2) {
+ warning("trying to save thumbnail with bpp different than 2");
+ return false;
+ }
+
+ ThumbnailHeader header;
+ header.type = MKID_BE('THMB');
+ header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel;
+ header.version = THMB_VERSION;
+ header.width = thumb.w;
+ header.height = thumb.h;
+ header.bpp = thumb.bytesPerPixel;
+
+ out.writeUint32BE(header.type);
+ out.writeUint32BE(header.size);
+ out.writeByte(header.version);
+ out.writeUint16BE(header.width);
+ out.writeUint16BE(header.height);
+ out.writeByte(header.bpp);
+
+ // TODO: for later this shouldn't be casted to uint16...
+ uint16 *pixels = (uint16 *)thumb.pixels;
+ for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels)
+ out.writeUint16BE(*pixels);
+
+ return true;
+}
+
+} // end of namespace Graphics
+
diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h
new file mode 100644
index 0000000000..0553306519
--- /dev/null
+++ b/graphics/thumbnail.h
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_THUMBNAIL_H
+#define GRAPHICS_THUMBNAIL_H
+
+#include "common/stream.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+/**
+ * Checks for presence of the thumbnail save header.
+ * Seeks automatically back to start position after check.
+ *
+ * @param in stream to check for header
+ */
+bool checkThumbnailHeader(Common::SeekableReadStream &in);
+
+/**
+ * Skips a thumbnail header, if present.
+ *
+ * @param in stream to process
+ */
+bool skipThumbnailHeader(Common::SeekableReadStream &in);
+
+/**
+ * Lodas a thumbnail from the given input stream.
+ * The loaded thumbnail will be automatically converted to the
+ * current overlay pixelformat.
+ */
+bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to);
+
+/**
+ * Saves a thumbnail to the given write stream.
+ * Automatically creates a thumbnail from screen contents.
+ */
+bool saveThumbnail(Common::WriteStream &out);
+
+/**
+ * Saves a (given) thumbnail to the given write stream.
+ */
+bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb);
+
+} // end of namespace Graphics
+
+#endif
+
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index e75c2e295e..c04ca52834 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -525,7 +525,7 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) {
_themeName.clear();
char fileNameBuffer[32];
- char stxHeader[128];
+ Common::String stxHeader;
int parseCount = 0;
#ifdef USE_ZLIB
@@ -546,9 +546,9 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) {
Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true);
if (!strcmp(fileNameBuffer, "THEMERC")) {
- stream->readLine(stxHeader, 128);
+ stxHeader = stream->readLine();
- if (!themeConfigParseHeader(stxHeader, _themeName)) {
+ if (!themeConfigParseHeader(stxHeader.c_str(), _themeName)) {
warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str());
return false;
}
@@ -591,9 +591,9 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) {
} else if (i->getName() == "THEMERC") {
Common::File f;
f.open(*i);
- f.readLine(stxHeader, 128);
+ stxHeader = f.readLine();
- if (!themeConfigParseHeader(stxHeader, _themeName)) {
+ if (!themeConfigParseHeader(stxHeader.c_str(), _themeName)) {
warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str());
return false;
}
diff --git a/gui/about.cpp b/gui/about.cpp
index eeb2533e0d..1c1e3a3355 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -58,7 +58,7 @@ enum {
static const char *copyright_text[] = {
"\\C""",
-"\\C""Copyright (C) 2002-2007 The ScummVM project",
+"\\C""Copyright (C) 2001-2008 The ScummVM project",
"\\C""http://www.scummvm.org",
"\\C""",
"\\C""ScummVM is the legal property of its developers, whose names are too numerous to list here. Please refer to the COPYRIGHT file distributed with this binary.",
diff --git a/gui/browser.cpp b/gui/browser.cpp
index a5c71e6987..69f5dcd134 100644
--- a/gui/browser.cpp
+++ b/gui/browser.cpp
@@ -107,7 +107,7 @@ int BrowserDialog::runModal() {
err = FSRefMakePath(&ref, (UInt8*)buf, sizeof(buf)-1);
assert(err == noErr);
- _choice = FilesystemNode(buf);
+ _choice = Common::FilesystemNode(buf);
choiceMade = true;
}
@@ -160,9 +160,9 @@ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser)
void BrowserDialog::open() {
if (ConfMan.hasKey("browser_lastpath"))
- _node = FilesystemNode(ConfMan.get("browser_lastpath"));
+ _node = Common::FilesystemNode(ConfMan.get("browser_lastpath"));
if (!_node.isDirectory())
- _node = FilesystemNode(".");
+ _node = Common::FilesystemNode(".");
// Alway refresh file list
updateListing();
@@ -227,8 +227,9 @@ void BrowserDialog::updateListing() {
ConfMan.set("browser_lastpath", _node.getPath());
// Read in the data from the file system
- FilesystemNode::ListMode listMode = _isDirBrowser ? FilesystemNode::kListDirectoriesOnly
- : FilesystemNode::kListAll;
+ Common::FilesystemNode::ListMode listMode =
+ _isDirBrowser ? Common::FilesystemNode::kListDirectoriesOnly
+ : Common::FilesystemNode::kListAll;
if (!_node.getChildren(_nodeContent, listMode)) {
_nodeContent.clear();
} else {
@@ -237,7 +238,7 @@ void BrowserDialog::updateListing() {
// Populate the ListWidget
Common::StringList list;
- for (FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
+ for (Common::FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
if (!_isDirBrowser && i->isDirectory())
list.push_back(i->getDisplayName() + "/");
else
diff --git a/gui/browser.h b/gui/browser.h
index d330e32269..c8bdec26a2 100644
--- a/gui/browser.h
+++ b/gui/browser.h
@@ -39,8 +39,6 @@ class ListWidget;
class StaticTextWidget;
class BrowserDialog : public Dialog {
- typedef Common::String String;
- typedef Common::StringList StringList;
public:
BrowserDialog(const char *title, bool dirBrowser);
@@ -52,7 +50,7 @@ public:
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
#endif
- const FilesystemNode &getResult() { return _choice; }
+ const Common::FilesystemNode &getResult() { return _choice; }
protected:
#ifdef MACOSX
@@ -60,10 +58,10 @@ protected:
#else
ListWidget *_fileList;
StaticTextWidget *_currentPath;
- FilesystemNode _node;
- FSList _nodeContent;
+ Common::FilesystemNode _node;
+ Common::FSList _nodeContent;
#endif
- FilesystemNode _choice;
+ Common::FilesystemNode _choice;
bool _isDirBrowser;
#ifndef MACOSX
diff --git a/gui/credits.h b/gui/credits.h
index ca2fda811d..b8d2e345c8 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -175,11 +175,13 @@ static const char *credits[] = {
"\\C\\c0""",
"\\C\\c1""Miscellaneous",
"\\C\\c0""David Corrales-Lopez",
-"\\C\\c2""Filesystem access improvements",
+"\\C\\c2""Filesystem access improvements (GSoC 2007 task)",
"\\C\\c0""Jerome Fisher",
"\\C\\c2""MT-32 emulator",
"\\C\\c0""Jochen Hoenicke",
"\\C\\c2""Speaker & PCjr sound support, Adlib work",
+"\\C\\c0""Chris Page",
+"\\C\\c2""Return to launcher, savestate improvements, leak fixes, ... (GSoC 2008 task)",
"\\C\\c0""Robin Watts",
"\\C\\c2""ARM assembly routines for nice speedups on several ports; improvements to the sound mixer",
"\\C\\c0""",
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 9ecdbfb6d4..b79891ef76 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -29,6 +29,7 @@
#include "common/events.h"
#include "common/fs.h"
#include "common/util.h"
+#include "common/savefile.h"
#include "common/system.h"
#include "gui/about.h"
@@ -44,6 +45,7 @@
#include "gui/TabWidget.h"
#include "gui/PopUpWidget.h"
#include "graphics/cursorman.h"
+#include "graphics/scaler.h"
#include "sound/mididrv.h"
@@ -61,7 +63,10 @@ enum {
kAddGameCmd = 'ADDG',
kEditGameCmd = 'EDTG',
kRemoveGameCmd = 'REMG',
+ kLoadGameCmd = 'LOAD',
kQuitCmd = 'QUIT',
+ kChooseCmd = 'CHOS',
+ kDelCmd = 'DEL ',
kCmdGlobalGraphicsOverride = 'OGFX',
@@ -390,7 +395,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
if (browser.runModal() > 0) {
// User made this choice...
- FilesystemNode file(browser.getResult());
+ Common::FilesystemNode file(browser.getResult());
_soundFont->setLabel(file.getPath());
if (!file.getPath().empty() && (file.getPath() != "None"))
@@ -408,7 +413,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
BrowserDialog browser("Select directory with game data", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
// TODO: Verify the game can be found in the new directory... Best
// done with optional specific gameid to pluginmgr detectgames?
@@ -426,7 +431,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
BrowserDialog browser("Select additional game directory", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
_extraPathWidget->setLabel(dir.getPath());
draw();
}
@@ -438,7 +443,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
BrowserDialog browser("Select directory for saved games", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
_savePathWidget->setLabel(dir.getPath());
draw();
}
@@ -468,6 +473,296 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
}
}
+class SaveLoadChooser : public GUI::Dialog {
+ typedef Common::String String;
+ typedef Common::StringList StringList;
+protected:
+ GUI::ListWidget *_list;
+ GUI::ButtonWidget *_chooseButton;
+ GUI::ButtonWidget *_deleteButton;
+ GUI::GraphicsWidget *_gfxWidget;
+ GUI::ContainerWidget *_container;
+ GUI::StaticTextWidget *_date;
+ GUI::StaticTextWidget *_time;
+ GUI::StaticTextWidget *_playtime;
+
+ const EnginePlugin *_plugin;
+ bool _delSupport;
+ bool _metaInfoSupport;
+ bool _thumbnailSupport;
+ bool _saveDateSupport;
+ bool _playTimeSupport;
+ String _target;
+ SaveStateList _saveList;
+
+ uint8 _fillR, _fillG, _fillB;
+
+ void updateSaveList();
+ void updateSelection(bool redraw);
+public:
+ SaveLoadChooser(const String &title, const String &buttonLabel);
+ ~SaveLoadChooser();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ void setList(const StringList& list);
+ int runModal(const EnginePlugin *plugin, const String &target);
+
+ virtual void reflowLayout();
+
+ virtual void close();
+};
+
+SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel)
+ : Dialog("ScummSaveLoad"), _delSupport(0), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0) {
+ _delSupport = _metaInfoSupport = _thumbnailSupport = _saveDateSupport = _playTimeSupport = false;
+
+// _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR;
+
+ new StaticTextWidget(this, "ScummSaveLoad.Title", title);
+
+ // Add choice list
+ _list = new GUI::ListWidget(this, "ScummSaveLoad.List");
+ _list->setNumberingMode(GUI::kListNumberingOff);
+
+ _container = new GUI::ContainerWidget(this, 0, 0, 10, 10);
+// _container->setHints(GUI::THEME_HINT_USE_SHADOW);
+
+ _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
+
+ _date = new StaticTextWidget(this, 0, 0, 10, 10, "No date saved", kTextAlignCenter);
+ _time = new StaticTextWidget(this, 0, 0, 10, 10, "No time saved", kTextAlignCenter);
+ _playtime = new StaticTextWidget(this, 0, 0, 10, 10, "No playtime saved", kTextAlignCenter);
+
+ // Buttons
+ new GUI::ButtonWidget(this, "ScummSaveLoad.Cancel", "Cancel", kCloseCmd, 0);
+ _chooseButton = new GUI::ButtonWidget(this, "ScummSaveLoad.Choose", buttonLabel, kChooseCmd, 0);
+ _chooseButton->setEnabled(false);
+
+ _deleteButton = new GUI::ButtonWidget(this, "ScummSaveLoad.Delete", "Delete", kDelCmd, 0);
+ _deleteButton->setEnabled(false);
+
+ _delSupport = _metaInfoSupport = _thumbnailSupport = false;
+}
+
+SaveLoadChooser::~SaveLoadChooser() {
+}
+
+int SaveLoadChooser::runModal(const EnginePlugin *plugin, const String &target) {
+ if (_gfxWidget)
+ _gfxWidget->setGfx(0);
+
+ _plugin = plugin;
+ _target = target;
+ _delSupport = (*_plugin)->hasFeature(MetaEngine::kSupportsDeleteSave);
+ _metaInfoSupport = (*_plugin)->hasFeature(MetaEngine::kSupportsMetaInfos);
+ _thumbnailSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSupportsThumbnails);
+ _saveDateSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSupportsSaveDate);
+ _playTimeSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSupportsSavePlayTime);
+ reflowLayout();
+ updateSaveList();
+
+ int ret = Dialog::runModal();
+ return ret;
+}
+
+void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ int selItem = _list->getSelected();
+
+ switch (cmd) {
+ case GUI::kListItemActivatedCmd:
+ case GUI::kListItemDoubleClickedCmd:
+ if (selItem >= 0) {
+ if (!_list->getSelectedString().empty()) {
+ _list->endEditMode();
+ setResult(atoi(_saveList[selItem].save_slot().c_str()));
+ close();
+ }
+ }
+ break;
+ case kChooseCmd:
+ setResult(atoi(_saveList[selItem].save_slot().c_str()));
+ close();
+ break;
+ case GUI::kListSelectionChangedCmd: {
+ updateSelection(true);
+ } break;
+ case kDelCmd:
+ if (selItem >= 0 && _delSupport) {
+ MessageDialog alert("Do you really want to delete this savegame?",
+ "Delete", "Cancel");
+ if (alert.runModal() == GUI::kMessageOK) {
+ (*_plugin)->removeSaveState(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str()));
+
+ setResult(-1);
+ _list->setSelected(-1);
+
+ updateSaveList();
+ updateSelection(true);
+ }
+ }
+ break;
+ case kCloseCmd:
+ setResult(-1);
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void SaveLoadChooser::reflowLayout() {
+ if (g_gui.xmlEval()->getVar("Globals.ScummSaveLoad.ExtInfo.Visible") == 1 && _thumbnailSupport) {
+ int16 x, y;
+ uint16 w, h;
+
+ if (!g_gui.xmlEval()->getWidgetData("ScummSaveLoad.Thumbnail", x, y, w, h))
+ error("Error when loading position data for Save/Load Thumbnails.");
+
+ int thumbW = kThumbnailWidth;
+ int thumbH = ((g_system->getHeight() % 200 && g_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1);
+ int thumbX = x + (w >> 1) - (thumbW >> 1);
+ int thumbY = y + kLineHeight;
+
+ int textLines = 0;
+ if (_saveDateSupport)
+ textLines += 2;
+ if (_playTimeSupport)
+ textLines += 1;
+
+ if (textLines)
+ ++textLines;
+
+ _container->resize(x, y, w, h + textLines * kLineHeight);
+ _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
+
+ int height = thumbY + thumbH + kLineHeight;
+
+ if (_saveDateSupport) {
+ _date->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+ height += kLineHeight;
+ _time->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+ height += kLineHeight;
+ }
+
+ if (_playTimeSupport)
+ _playtime->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+
+ _container->clearFlags(GUI::WIDGET_INVISIBLE);
+ _gfxWidget->clearFlags(GUI::WIDGET_INVISIBLE);
+
+ if (_saveDateSupport) {
+ _date->clearFlags(GUI::WIDGET_INVISIBLE);
+ _time->clearFlags(GUI::WIDGET_INVISIBLE);
+ } else {
+ _date->setFlags(GUI::WIDGET_INVISIBLE);
+ _time->setFlags(GUI::WIDGET_INVISIBLE);
+ }
+
+ if (_playTimeSupport)
+ _playtime->clearFlags(GUI::WIDGET_INVISIBLE);
+ else
+ _playtime->setFlags(GUI::WIDGET_INVISIBLE);
+
+ _fillR = 0;
+ _fillG = 0;
+ _fillB = 0;
+ updateSelection(false);
+ } else {
+ _container->setFlags(GUI::WIDGET_INVISIBLE);
+ _gfxWidget->setFlags(GUI::WIDGET_INVISIBLE);
+ _date->setFlags(GUI::WIDGET_INVISIBLE);
+ _time->setFlags(GUI::WIDGET_INVISIBLE);
+ _playtime->setFlags(GUI::WIDGET_INVISIBLE);
+ }
+
+ Dialog::reflowLayout();
+}
+
+void SaveLoadChooser::updateSelection(bool redraw) {
+ int selItem = _list->getSelected();
+
+ bool isDeletable = _delSupport;
+
+ if (selItem >= 0 && !_list->getSelectedString().empty() && _metaInfoSupport) {
+ SaveStateDescriptor desc = (*_plugin)->querySaveMetaInfos(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str()));
+
+ isDeletable = desc.getBool("is_deletable") && _delSupport;
+
+ if (_thumbnailSupport) {
+ const Graphics::Surface *thumb = desc.getThumbnail();
+ if (thumb) {
+ _gfxWidget->setGfx(thumb);
+ _gfxWidget->useAlpha(256);
+ } else {
+ _gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
+ }
+ }
+
+ if (_saveDateSupport) {
+ Common::String date = "Date: ";
+ if (desc.contains("save_date"))
+ date += desc.getVal("save_date");
+ else
+ date = "No date saved";
+
+ Common::String time = "Time: ";
+ if (desc.contains("save_time"))
+ time += desc.getVal("save_time");
+ else
+ time = "No time saved";
+
+ _date->setLabel(date);
+ _time->setLabel(time);
+ }
+
+ if (_playTimeSupport) {
+ Common::String time = "Playtime: ";
+ if (desc.contains("play_time"))
+ time += desc.getVal("play_time");
+ else
+ time = "No playtime saved";
+
+ _playtime->setLabel(time);
+ }
+ }
+
+
+ // Disable these buttons if nothing is selected, or if an empty
+ // list item is selected.
+ _chooseButton->setEnabled(selItem >= 0 && (!_list->getSelectedString().empty()));
+ // Delete will always be disabled if the engine doesn't support it.
+ _deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty()));
+
+ if (redraw) {
+ _gfxWidget->draw();
+ _date->draw();
+ _time->draw();
+ _playtime->draw();
+ _chooseButton->draw();
+ _deleteButton->draw();
+ }
+}
+
+void SaveLoadChooser::close() {
+ _plugin = 0;
+ _target.clear();
+ _saveList.clear();
+ _list->setList(StringList());
+
+ Dialog::close();
+}
+
+void SaveLoadChooser::updateSaveList() {
+ _saveList = (*_plugin)->listSaves(_target.c_str());
+
+ StringList saveNames;
+ for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
+ Common::String description = x->save_slot();
+ description += ". ";
+ description += x->description();
+
+ saveNames.push_back(description);
+ }
+ _list->setList(saveNames);
+}
#pragma mark -
@@ -502,6 +797,9 @@ LauncherDialog::LauncherDialog()
_startButton =
new ButtonWidget(this, "Launcher.StartButton", "Start", kStartCmd, 'S');
+ _loadButton =
+ new ButtonWidget(this, "Launcher.LoadGameButton", "Load", kLoadGameCmd, 'L');
+
// Above the lowest button rows: two more buttons (directly below the list box)
_addButton =
new ButtonWidget(this, "Launcher.AddGameButton", "Add Game...", kAddGameCmd, 'A');
@@ -529,6 +827,9 @@ LauncherDialog::LauncherDialog()
// Create file browser dialog
_browser = new BrowserDialog("Select directory with game data", true);
+
+ // Create Load dialog
+ _loadDialog = new SaveLoadChooser("Load game:", "Load");
}
void LauncherDialog::selectGame(const String &name) {
@@ -546,6 +847,7 @@ void LauncherDialog::selectGame(const String &name) {
LauncherDialog::~LauncherDialog() {
delete _browser;
+ delete _loadDialog;
}
void LauncherDialog::open() {
@@ -654,9 +956,9 @@ void LauncherDialog::addGame() {
if (_browser->runModal() > 0) {
// User made his choice...
- FilesystemNode dir(_browser->getResult());
- FSList files;
- if (!dir.getChildren(files, FilesystemNode::kListAll)) {
+ Common::FilesystemNode dir(_browser->getResult());
+ Common::FSList files;
+ if (!dir.getChildren(files, Common::FilesystemNode::kListAll)) {
error("browser returned a node that is not a directory: '%s'",
dir.getPath().c_str());
}
@@ -795,6 +1097,37 @@ void LauncherDialog::editGame(int item) {
}
}
+void LauncherDialog::loadGame(int item) {
+ String gameId = ConfMan.get("gameid", _domains[item]);
+ if (gameId.empty())
+ gameId = _domains[item];
+
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+
+ String target = _domains[item];
+ target.toLowercase();
+
+ if (plugin) {
+ if ((*plugin)->hasFeature(MetaEngine::kSupportsListSaves) &&
+ (*plugin)->hasFeature(MetaEngine::kSupportsDirectLoad)) {
+ int slot = _loadDialog->runModal(plugin, target);
+ if (slot >= 0) {
+ ConfMan.setActiveDomain(_domains[item]);
+ ConfMan.setInt("save_slot", slot, Common::ConfigManager::kTransientDomain);
+ close();
+ }
+ } else {
+ MessageDialog dialog
+ ("This game does not support loading games from the launcher.", "OK");
+ dialog.runModal();
+ }
+ } else {
+ MessageDialog dialog("ScummVM could not find any engine capable of running the selected game!", "OK");
+ dialog.runModal();
+ }
+}
+
void LauncherDialog::handleKeyDown(Common::KeyState state) {
Dialog::handleKeyDown(state);
updateButtons();
@@ -818,6 +1151,9 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kEditGameCmd:
editGame(item);
break;
+ case kLoadGameCmd:
+ loadGame(item);
+ break;
case kOptionsCmd: {
GlobalOptionsDialog options;
options.runModal();
@@ -866,6 +1202,10 @@ void LauncherDialog::updateButtons() {
_removeButton->setEnabled(enable);
_removeButton->draw();
}
+ if (enable != _loadButton->isEnabled()) {
+ _loadButton->setEnabled(enable);
+ _loadButton->draw();
+ }
// Update the label of the "Add" button depending on whether shift is pressed or not
int modifiers = g_system->getEventManager()->getModifierState();
diff --git a/gui/launcher.h b/gui/launcher.h
index a9d09bf109..1b2b0a354e 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -26,7 +26,7 @@
#define LAUNCHER_DIALOG_H
#include "gui/dialog.h"
-#include "base/game.h"
+#include "engines/game.h"
#include "common/str.h"
namespace GUI {
@@ -34,11 +34,10 @@ namespace GUI {
class BrowserDialog;
class ListWidget;
class GraphicsWidget;
-
+class SaveLoadChooser;
Common::String addGameToConf(const GameDescriptor &result);
-
class LauncherDialog : public Dialog {
typedef Common::String String;
typedef Common::StringList StringList;
@@ -55,6 +54,7 @@ protected:
ListWidget *_list;
ButtonWidget *_addButton;
Widget *_startButton;
+ Widget *_loadButton;
Widget *_editButton;
Widget *_removeButton;
#ifndef DISABLE_FANCY_THEMES
@@ -62,6 +62,7 @@ protected:
#endif
StringList _domains;
BrowserDialog *_browser;
+ SaveLoadChooser *_loadDialog;
virtual void reflowLayout();
@@ -73,7 +74,8 @@ protected:
virtual void addGame();
void removeGame(int item);
void editGame(int item);
-
+ void loadGame(int item);
+
void selectGame(const String &name);
};
diff --git a/gui/massadd.cpp b/gui/massadd.cpp
index 6842466ad9..c34c190776 100644
--- a/gui/massadd.cpp
+++ b/gui/massadd.cpp
@@ -58,7 +58,7 @@ enum {
-MassAddDialog::MassAddDialog(const FilesystemNode &startDir)
+MassAddDialog::MassAddDialog(const Common::FilesystemNode &startDir)
: Dialog("massadddialog"),
_dirsScanned(0),
_okButton(0),
@@ -156,10 +156,10 @@ void MassAddDialog::handleTickle() {
// Perform a breadth-first scan of the filesystem.
while (!_scanStack.empty() && (g_system->getMillis() - t) < kMaxScanTime) {
- FilesystemNode dir = _scanStack.pop();
+ Common::FilesystemNode dir = _scanStack.pop();
- FSList files;
- if (!dir.getChildren(files, FilesystemNode::kListAll)) {
+ Common::FSList files;
+ if (!dir.getChildren(files, Common::FilesystemNode::kListAll)) {
error("browser returned a node that is not a directory: '%s'",
dir.getPath().c_str());
}
@@ -206,7 +206,7 @@ void MassAddDialog::handleTickle() {
// Recurse into all subdirs
- for (FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
+ for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
if (file->isDirectory()) {
_scanStack.push(*file);
}
diff --git a/gui/massadd.h b/gui/massadd.h
index e0eff75c64..733559cf37 100644
--- a/gui/massadd.h
+++ b/gui/massadd.h
@@ -38,14 +38,14 @@ class StaticTextWidget;
class MassAddDialog : public Dialog {
public:
- MassAddDialog(const FilesystemNode &startDir);
+ MassAddDialog(const Common::FilesystemNode &startDir);
//void open();
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
void handleTickle();
private:
- Common::Stack<FilesystemNode> _scanStack;
+ Common::Stack<Common::FilesystemNode> _scanStack;
GameList _games;
/**
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index 72b7f2612c..1fa0038ff2 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -25,6 +25,7 @@
#include "common/events.h"
#include "common/system.h"
#include "common/util.h"
+#include "engines/engine.h"
#include "graphics/cursorman.h"
#include "gui/newgui.h"
#include "gui/dialog.h"
@@ -67,9 +68,9 @@ void GuiObject::reflowLayout() {
error("Widget <%s> has x + w > %d (%d)", _name.c_str(), g_system->getOverlayWidth(), _x + _w);
if (_y < 0)
error("Widget <%s> has y < 0", _name.c_str());
- if (_y >= g_system->getOverlayWidth())
+ if (_y >= g_system->getOverlayHeight())
error("Widget <%s> has y > %d", _name.c_str(), g_system->getOverlayHeight());
- if (_y + _h > g_system->getOverlayWidth())
+ if (_y + _h > g_system->getOverlayHeight())
error("Widget <%s> has y + h > %d (%d)", _name.c_str(), g_system->getOverlayHeight(), _y + _h);
}
}
@@ -221,7 +222,7 @@ void NewGui::runLoop() {
Common::Event event;
while (eventMan->pollEvent(event)) {
- if (activeDialog != getTopDialog() && event.type != Common::EVENT_QUIT && event.type != Common::EVENT_SCREEN_CHANGED)
+ if (activeDialog != getTopDialog() && event.type != Common::EVENT_SCREEN_CHANGED)
continue;
Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
@@ -286,7 +287,8 @@ void NewGui::runLoop() {
activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
break;
case Common::EVENT_QUIT:
- _system->quit();
+ if (!g_engine)
+ _system->quit();
return;
case Common::EVENT_SCREEN_CHANGED:
screenChange();
diff --git a/gui/options.cpp b/gui/options.cpp
index 110f7c9b69..ea80283f97 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -858,7 +858,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
BrowserDialog browser("Select directory for savegames", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
if (dir.isWritable()) {
_savePath->setLabel(dir.getPath());
} else {
@@ -874,7 +874,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
BrowserDialog browser("Select directory for GUI themes", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
_themePath->setLabel(dir.getPath());
draw();
}
@@ -884,7 +884,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
BrowserDialog browser("Select directory for extra files", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
_extraPath->setLabel(dir.getPath());
draw();
}
@@ -895,7 +895,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
BrowserDialog browser("Select directory for plugins", true);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode dir(browser.getResult());
+ Common::FilesystemNode dir(browser.getResult());
_pluginsPath->setLabel(dir.getPath());
draw();
}
@@ -906,7 +906,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
BrowserDialog browser("Select SoundFont", false);
if (browser.runModal() > 0) {
// User made his choice...
- FilesystemNode file(browser.getResult());
+ Common::FilesystemNode file(browser.getResult());
_soundFont->setLabel(file.getPath());
if (!file.getPath().empty() && (file.getPath() != "None"))
diff --git a/gui/theme.cpp b/gui/theme.cpp
index 3a6280ab95..df9ae34017 100644
--- a/gui/theme.cpp
+++ b/gui/theme.cpp
@@ -23,7 +23,8 @@
*/
#include "gui/theme.h"
-#include "common/fs.h"
+#include "common/file.h"
+#include "common/archive.h"
#include "common/unzip.h"
namespace GUI {
@@ -44,24 +45,11 @@ const Graphics::Font *Theme::loadFont(const char *filename) {
return font;
#ifdef USE_ZLIB
- unzFile zipFile = unzOpen((getThemeFileName()).c_str());
- if (zipFile && unzLocateFile(zipFile, cacheFilename.c_str(), 2) == UNZ_OK) {
- unz_file_info fileInfo;
- unzOpenCurrentFile(zipFile);
- unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
- uint8 *buffer = new uint8[fileInfo.uncompressed_size+1];
- assert(buffer);
- memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8));
- unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size);
- unzCloseCurrentFile(zipFile);
- Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1);
-
- font = Graphics::NewFont::loadFromCache(stream);
-
- delete[] buffer;
- buffer = 0;
+ ZipArchive zipArchive(getThemeFileName().c_str());
+ if (zipArchive.hasFile(cacheFilename)) {
+ Common::FilePtr stream(zipArchive.openFile(cacheFilename));
+ font = Graphics::NewFont::loadFromCache(*stream.get());
}
- unzClose(zipFile);
#endif
if (font)
return font;
@@ -74,24 +62,11 @@ const Graphics::Font *Theme::loadFont(const char *filename) {
#ifdef USE_ZLIB
if (!font) {
- unzFile zipFile = unzOpen((getThemeFileName()).c_str());
- if (zipFile && unzLocateFile(zipFile, filename, 2) == UNZ_OK) {
- unz_file_info fileInfo;
- unzOpenCurrentFile(zipFile);
- unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
- uint8 *buffer = new uint8[fileInfo.uncompressed_size+1];
- assert(buffer);
- memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8));
- unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size);
- unzCloseCurrentFile(zipFile);
- Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1);
-
- font = Graphics::NewFont::loadFont(stream);
-
- delete[] buffer;
- buffer = 0;
+ ZipArchive zipArchive(getThemeFileName().c_str());
+ if (zipArchive.hasFile(filename)) {
+ Common::FilePtr stream(zipArchive.openFile(filename));
+ font = Graphics::NewFont::loadFont(*stream.get());
}
- unzClose(zipFile);
}
#endif
@@ -154,8 +129,8 @@ bool Theme::themeConfigParseHeader(Common::String header, Common::String &themeN
return tok.empty();
}
-bool Theme::themeConfigUseable(const FilesystemNode &node, Common::String &themeName) {
- char stxHeader[128];
+bool Theme::themeConfigUseable(const Common::FilesystemNode &node, Common::String &themeName) {
+ Common::String stxHeader;
bool foundHeader = false;
if (ConfMan.hasKey("themepath"))
@@ -170,40 +145,27 @@ bool Theme::themeConfigUseable(const FilesystemNode &node, Common::String &theme
if (node.getName().hasSuffix(".zip")) {
#ifdef USE_ZLIB
- unzFile zipFile = unzOpen(node.getPath().c_str());
-
- if (zipFile && unzLocateFile(zipFile, "THEMERC", 2) == UNZ_OK) {
- unz_file_info fileInfo;
- unzOpenCurrentFile(zipFile);
- unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
- uint8 *buffer = new uint8[fileInfo.uncompressed_size+1];
- assert(buffer);
- memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8));
- unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size);
- unzCloseCurrentFile(zipFile);
- Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1);
- stream.readLine(stxHeader, 128);
-
- if (themeConfigParseHeader(stxHeader, themeName))
+ ZipArchive zipArchive(node.getPath().c_str());
+ if (zipArchive.hasFile("THEMERC")) {
+ Common::FilePtr stream(zipArchive.openFile("THEMERC"));
+ stxHeader = stream->readLine();
+ // TODO: Read first line of file. How?
+ if (themeConfigParseHeader(stxHeader.c_str(), themeName))
foundHeader = true;
-
- delete[] buffer;
- buffer = 0;
}
- unzClose(zipFile);
#else
return false;
#endif
} else if (node.isDirectory()) {
- FilesystemNode headerfile = node.getChild("THEMERC");
+ Common::FilesystemNode headerfile = node.getChild("THEMERC");
if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory())
return false;
+ // TODO: File or FilePtr?
Common::File f;
f.open(headerfile);
- f.readLine(stxHeader, 128);
-
- if (themeConfigParseHeader(stxHeader, themeName))
+ stxHeader = f.readLine();
+ if (themeConfigParseHeader(stxHeader.c_str(), themeName))
foundHeader = true;
}
diff --git a/gui/theme.h b/gui/theme.h
index 57744db584..302029247b 100644
--- a/gui/theme.h
+++ b/gui/theme.h
@@ -28,7 +28,7 @@
#include "common/system.h"
#include "common/rect.h"
#include "common/str.h"
-#include "common/file.h"
+#include "common/fs.h"
#include "common/config-file.h"
#include "graphics/surface.h"
@@ -305,7 +305,7 @@ public:
bool isThemeLoadingRequired();
virtual ThemeEval *evaluator() = 0;
- static bool themeConfigUseable(const FilesystemNode &node, Common::String &themeName);
+ static bool themeConfigUseable(const Common::FilesystemNode &node, Common::String &themeName);
static bool themeConfigParseHeader(Common::String header, Common::String &themeName);
virtual const Common::String &getThemeFileName() const = 0;
@@ -321,7 +321,8 @@ public:
//! Special image ids for images used in the GUI
enum kThemeImages {
- kImageLogo = 0 //! ScummVM Logo used in the launcher
+ kImageLogo = 0, //! ScummVM Logo used in the launcher
+ kImageLogoSmall //! ScummVM logo used in the GMM
};
/**
diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp
index f764b05f6a..c935f04143 100644
--- a/gui/themebrowser.cpp
+++ b/gui/themebrowser.cpp
@@ -140,33 +140,31 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) {
if (level < 0)
return;
- FilesystemNode node(dir);
+ Common::FilesystemNode node(dir);
if (!node.exists() || !node.isReadable())
return;
- FSList fslist;
-
-#ifdef USE_ZLIB
- if (node.lookupFile(fslist, "*.zip", false, true, 0)) {
- for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) {
- Entry th;
- if (isTheme(*i, th)) {
- bool add = true;
-
- for (ThList::const_iterator p = list.begin(); p != list.end(); ++p) {
- if (p->name == th.name || p->file == th.file) {
- add = false;
- break;
- }
- }
+ Common::FSList fslist;
+ if (!node.getChildren(fslist, Common::FilesystemNode::kListAll))
+ return;
- if (add)
- list.push_back(th);
+ for (Common::FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) {
+ Entry th;
+ if (isTheme(*i, th)) {
+ bool add = true;
+
+ for (ThList::const_iterator p = list.begin(); p != list.end(); ++p) {
+ if (p->name == th.name || p->file == th.file) {
+ add = false;
+ break;
+ }
}
+
+ if (add)
+ list.push_back(th);
}
}
-#endif
if (node.lookupFile(fslist, "THEMERC", false, true, 1)) {
for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) {
@@ -188,7 +186,7 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) {
}
}
-bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) {
+bool ThemeBrowser::isTheme(const Common::FilesystemNode &node, Entry &out) {
out.file = node.getPath();
#ifdef USE_ZLIB
diff --git a/gui/themebrowser.h b/gui/themebrowser.h
index 7a3bc2ca7d..c3a46aa3b0 100644
--- a/gui/themebrowser.h
+++ b/gui/themebrowser.h
@@ -57,7 +57,7 @@ private:
void updateListing();
void addDir(ThList &list, const Common::String &dir, int level = 4);
- bool isTheme(const FilesystemNode &node, Entry &out);
+ bool isTheme(const Common::FilesystemNode &node, Entry &out);
};
} // end of namespace GUI
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 71e655f5bc..c0ea4a9228 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -364,6 +364,9 @@
"/> "
"<widget name = 'GameList'/> "
"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> "
+"<widget name = 'LoadGameButton' "
+"height = '20' "
+"/> "
"<widget name = 'AddGameButton' "
"height = '20' "
"/> "
@@ -811,6 +814,10 @@
"</layout> "
"<layout type = 'horizontal' padding = '0, 0, 0, 0'> "
"<space/> "
+"<widget name = 'Delete' "
+"type = 'Button' "
+"/> "
+"<space size = '32'/> "
"<widget name = 'Cancel' "
"type = 'Button' "
"/> "
@@ -901,6 +908,9 @@
"/> "
"<widget name = 'GameList'/> "
"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> "
+"<widget name = 'LoadGameButton' "
+"height = '12' "
+"/> "
"<widget name = 'AddGameButton' "
"height = '12' "
"/> "
@@ -1343,6 +1353,10 @@
"<widget name = 'List' /> "
"<layout type = 'horizontal' padding = '0, 0, 16, 0'> "
"<space/> "
+"<widget name = 'Delete' "
+"type = 'Button' "
+"/> "
+"<space size = '16'/> "
"<widget name = 'Cancel' "
"type = 'Button' "
"/> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 22928d2a85..5f04792330 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 005ebb89f3..9416a5a4a0 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -91,6 +91,9 @@
/>
<widget name = 'GameList'/>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+ <widget name = 'LoadGameButton'
+ height = '20'
+ />
<widget name = 'AddGameButton'
height = '20'
/>
@@ -556,6 +559,10 @@
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
<space/>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '32'/>
<widget name = 'Cancel'
type = 'Button'
/>
diff --git a/gui/themes/scummclassic/classic_layout_320.stx b/gui/themes/scummclassic/classic_layout_320.stx
index 1a6f8afa04..89ed033bd5 100644
--- a/gui/themes/scummclassic/classic_layout_320.stx
+++ b/gui/themes/scummclassic/classic_layout_320.stx
@@ -87,6 +87,9 @@
/>
<widget name = 'GameList'/>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+ <widget name = 'LoadGameButton'
+ height = '12'
+ />
<widget name = 'AddGameButton'
height = '12'
/>
@@ -549,6 +552,10 @@
<widget name = 'List' />
<layout type = 'horizontal' padding = '0, 0, 16, 0'>
<space/>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '16'/>
<widget name = 'Cancel'
type = 'Button'
/>
diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip
index 2a896ca374..93977a3cc7 100644
--- a/gui/themes/scummodern.zip
+++ b/gui/themes/scummodern.zip
Binary files differ
diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx
index 9d3c009eff..c1029088af 100644
--- a/gui/themes/scummodern/scummodern_layout.stx
+++ b/gui/themes/scummodern/scummodern_layout.stx
@@ -105,6 +105,9 @@
<widget name = 'StartButton'
type = 'Button'
/>
+ <widget name = 'LoadGameButton'
+ type = 'Button'
+ />
<space size = '16' />
<widget name = 'AddGameButton'
type = 'Button'
@@ -568,6 +571,10 @@
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
<space/>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '32'/>
<widget name = 'Cancel'
type = 'Button'
/>
diff --git a/gui/themes/scummodern/scummodern_layout_320.stx b/gui/themes/scummodern/scummodern_layout_320.stx
index 9d689e5c8d..e154ffdb9a 100644
--- a/gui/themes/scummodern/scummodern_layout_320.stx
+++ b/gui/themes/scummodern/scummodern_layout_320.stx
@@ -85,6 +85,9 @@
/>
<widget name = 'GameList'/>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'>
+ <widget name = 'LoadGameButton'
+ height = 'Globals.Button.Height'
+ />
<widget name = 'AddGameButton'
height = 'Globals.Button.Height'
/>
@@ -546,6 +549,10 @@
<widget name = 'List' />
<layout type = 'horizontal' padding = '0, 0, 16, 0'>
<space/>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '16'/>
<widget name = 'Cancel'
type = 'Button'
/>
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 685b6dfc65..818676dbf4 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -346,8 +346,7 @@ void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
return;
// TODO: add conversion to OverlayColor
- _gfx.create(gfx->w, gfx->h, gfx->bytesPerPixel);
- memcpy(_gfx.pixels, gfx->pixels, gfx->h * gfx->pitch);
+ _gfx.copyFrom(*gfx);
}
void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
diff --git a/ports.mk b/ports.mk
index 80efcfacc4..00a272f748 100644
--- a/ports.mk
+++ b/ports.mk
@@ -10,7 +10,7 @@
#
install: all
$(INSTALL) -d "$(DESTDIR)$(BINDIR)"
- $(INSTALL) -c -s -m 755 "$(srcdir)/scummvm$(EXEEXT)" "$(DESTDIR)$(BINDIR)/scummvm$(EXEEXT)"
+ $(INSTALL) -c -s -m 755 "./scummvm$(EXEEXT)" "$(DESTDIR)$(BINDIR)/scummvm$(EXEEXT)"
$(INSTALL) -d "$(DESTDIR)$(MANDIR)/man6/"
$(INSTALL) -c -m 644 "$(srcdir)/dists/scummvm.6" "$(DESTDIR)$(MANDIR)/man6/scummvm.6"
$(INSTALL) -d "$(DESTDIR)$(PREFIX)/share/pixmaps/"
diff --git a/sound/adpcm.cpp b/sound/adpcm.cpp
index ad072af360..a30cf9c61e 100644
--- a/sound/adpcm.cpp
+++ b/sound/adpcm.cpp
@@ -38,7 +38,7 @@ class ADPCMInputStream : public AudioStream {
private:
Common::SeekableReadStream *_stream;
bool _disposeAfterUse;
- uint32 _endpos;
+ int32 _endpos;
int _channels;
typesADPCM _type;
uint32 _blockAlign;
diff --git a/sound/audiocd.cpp b/sound/audiocd.cpp
index 343d5bc440..8fc9100926 100644
--- a/sound/audiocd.cpp
+++ b/sound/audiocd.cpp
@@ -29,7 +29,6 @@
#include "sound/vorbis.h"
#include "sound/flac.h"
#include "engines/engine.h"
-#include "common/file.h"
#include "common/util.h"
#include "common/system.h"
diff --git a/sound/flac.cpp b/sound/flac.cpp
index f058d2dc6f..7b46f0660f 100644
--- a/sound/flac.cpp
+++ b/sound/flac.cpp
@@ -27,7 +27,7 @@
#ifdef USE_FLAC
-#include "common/file.h"
+#include "common/stream.h"
#include "common/util.h"
#include "sound/audiostream.h"
@@ -72,9 +72,6 @@ typedef FLAC__StreamDecoder FLAC__SeekableStreamDecoder;
#endif
-using Common::File;
-
-
namespace Audio {
#pragma mark -
@@ -149,7 +146,7 @@ public:
bool isStreamDecoderReady() const { return getStreamDecoderState() == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC ; }
protected:
- uint getChannels() const { return MIN(_streaminfo.channels, MAX_OUTPUT_CHANNELS); }
+ uint getChannels() const { return MIN<uint>(_streaminfo.channels, MAX_OUTPUT_CHANNELS); }
bool allocateBuffer(uint minSamples);
@@ -659,7 +656,7 @@ inline ::FLAC__StreamDecoderWriteStatus FlacInputStream::callbackWrite(const ::F
inline ::FLAC__SeekableStreamDecoderSeekStatus FlacInputStream::callbackSeek(FLAC__uint64 absoluteByteOffset) {
_inStream->seek(absoluteByteOffset, SEEK_SET);
- const bool result = (absoluteByteOffset == _inStream->pos());
+ const bool result = (absoluteByteOffset == (FLAC__uint64)_inStream->pos());
#ifdef LEGACY_FLAC
return result ? FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK : FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
diff --git a/sound/flac.h b/sound/flac.h
index 5c825847b6..8a51441afd 100644
--- a/sound/flac.h
+++ b/sound/flac.h
@@ -31,7 +31,6 @@
#ifdef USE_FLAC
namespace Common {
- class File;
class SeekableReadStream;
}
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index 358d42d751..473612f6bc 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -46,7 +46,11 @@ static const MidiDriverDescription s_musicDrivers[] = {
{"alsa", "ALSA", MD_ALSA, MDT_MIDI},
#endif
-#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__)
+#if defined(__MINT__)
+ {"stmidi", "Atari ST MIDI", MD_STMIDI, MDT_MIDI},
+#endif
+
+#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__)
{"seq", "SEQ", MD_SEQ, MDT_MIDI},
#endif
@@ -247,7 +251,10 @@ MidiDriver *MidiDriver::createMidi(int midiDriver) {
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
case MD_WINDOWS: return MidiDriver_WIN_create(g_system->getMixer());
#endif
-#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__)
+#if defined(__MINT__)
+ case MD_STMIDI: return MidiDriver_STMIDI_create(g_system->getMixer());
+#endif
+#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__)
case MD_SEQ: return MidiDriver_SEQ_create(g_system->getMixer());
#endif
#if defined(UNIX)
diff --git a/sound/mididrv.h b/sound/mididrv.h
index 12513268a8..9d5a7d4407 100644
--- a/sound/mididrv.h
+++ b/sound/mididrv.h
@@ -51,6 +51,9 @@ enum MidiDriverType {
// Windows
MD_WINDOWS,
+ // Atari ST
+ MD_STMIDI,
+
// Linux
MD_ALSA,
MD_SEQ,
@@ -271,6 +274,7 @@ public:
extern MidiDriver *MidiDriver_NULL_create(Audio::Mixer *mixer);
extern MidiDriver *MidiDriver_ADLIB_create(Audio::Mixer *mixer);
extern MidiDriver *MidiDriver_WIN_create(Audio::Mixer *mixer);
+extern MidiDriver *MidiDriver_STMIDI_create(Audio::Mixer *mixer);
extern MidiDriver *MidiDriver_SEQ_create(Audio::Mixer *mixer);
extern MidiDriver *MidiDriver_TIMIDITY_create(Audio::Mixer *mixer);
extern MidiDriver *MidiDriver_QT_create(Audio::Mixer *mixer);
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index 27e031f108..824143d829 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -23,7 +23,6 @@
*
*/
-#include "common/file.h"
#include "common/util.h"
#include "common/system.h"
diff --git a/sound/mods/infogrames.cpp b/sound/mods/infogrames.cpp
index 97987b037a..a5b3ea1f35 100644
--- a/sound/mods/infogrames.cpp
+++ b/sound/mods/infogrames.cpp
@@ -25,6 +25,7 @@
#include "sound/mods/infogrames.h"
#include "common/endian.h"
+#include "common/file.h"
namespace Audio {
@@ -50,12 +51,20 @@ void Infogrames::Instruments::init() {
_sampleData = 0;
}
+bool Infogrames::Instruments::load(const char *ins) {
+ Common::File f;
+
+ if (f.open(ins))
+ return load(f);
+ return false;
+}
+
bool Infogrames::Instruments::load(Common::SeekableReadStream &ins) {
int i;
- uint32 fsize;
- uint32 offset[32];
- uint32 offsetRepeat[32];
- uint32 dataOffset;
+ int32 fsize;
+ int32 offset[32];
+ int32 offsetRepeat[32];
+ int32 dataOffset;
unload();
@@ -191,6 +200,14 @@ void Infogrames::reset() {
_chn[i].cmdBlockIndices = 0;
}
+bool Infogrames::load(const char *dum) {
+ Common::File f;
+
+ if (f.open(dum))
+ return load(f);
+ return false;
+}
+
bool Infogrames::load(Common::SeekableReadStream &dum) {
int subSong = 0;
int i;
diff --git a/sound/mods/infogrames.h b/sound/mods/infogrames.h
index 572c5a6426..d44ea0475c 100644
--- a/sound/mods/infogrames.h
+++ b/sound/mods/infogrames.h
@@ -28,7 +28,6 @@
#include "sound/mods/paula.h"
#include "common/stream.h"
-#include "common/file.h"
namespace Audio {
@@ -46,13 +45,7 @@ public:
~Instruments();
bool load(Common::SeekableReadStream &ins);
- bool load(const char *ins) {
- Common::File f;
-
- if (f.open(ins))
- return load(f);
- return false;
- }
+ bool load(const char *ins);
void unload(void);
uint8 getCount(void) const { return _count; }
@@ -82,13 +75,7 @@ public:
void setRepeating (int32 repCount) { _repCount = repCount; }
bool load(Common::SeekableReadStream &dum);
- bool load(const char *dum) {
- Common::File f;
-
- if (f.open(dum))
- return load(f);
- return false;
- }
+ bool load(const char *dum);
void unload(void);
void restart(void) {
if (_data) {
diff --git a/sound/mp3.cpp b/sound/mp3.cpp
index 70467bdb39..0249032e2f 100644
--- a/sound/mp3.cpp
+++ b/sound/mp3.cpp
@@ -27,7 +27,7 @@
#ifdef USE_MAD
-#include "common/file.h"
+#include "common/stream.h"
#include "common/util.h"
#include "sound/audiocd.h"
diff --git a/sound/mp3.h b/sound/mp3.h
index d544e60e0e..a27fc9dec5 100644
--- a/sound/mp3.h
+++ b/sound/mp3.h
@@ -31,7 +31,6 @@
#ifdef USE_MAD
namespace Common {
- class File;
class SeekableReadStream;
}
diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp
index 360ef4539d..3e3f9d91ff 100644
--- a/sound/softsynth/mt32.cpp
+++ b/sound/softsynth/mt32.cpp
@@ -96,12 +96,9 @@ public:
size_t read(void *in, size_t size) {
return _in.read(in, size);
}
- bool readLine(char *in, size_t size) {
- return _in.readLine(in, size) != NULL;
- }
bool readBit8u(MT32Emu::Bit8u *in) {
byte b = _in.readByte();
- if (_in.eof())
+ if (_in.eos())
return false;
*in = b;
return true;
@@ -114,7 +111,7 @@ public:
return !_out.ioFailed();
}
bool isEOF() {
- return _in.isOpen() ? _in.eof() : _out.eof();
+ return _in.isOpen() && _in.eos();
}
};
diff --git a/sound/softsynth/mt32/mt32_file.cpp b/sound/softsynth/mt32/mt32_file.cpp
index 86cb29fd49..f4eba73d33 100644
--- a/sound/softsynth/mt32/mt32_file.cpp
+++ b/sound/softsynth/mt32/mt32_file.cpp
@@ -44,10 +44,6 @@ namespace MT32Emu {
return fread(in, 1, size, fp);
}
- bool ANSIFile::readLine(char *in, size_t size) {
- return fgets(in, (int)size, fp) != NULL;
- }
-
bool ANSIFile::readBit8u(Bit8u *in) {
int c = fgetc(fp);
if (c == EOF)
diff --git a/sound/softsynth/mt32/mt32_file.h b/sound/softsynth/mt32/mt32_file.h
index 5f05c9e9ae..27c8ccbe46 100644
--- a/sound/softsynth/mt32/mt32_file.h
+++ b/sound/softsynth/mt32/mt32_file.h
@@ -35,7 +35,6 @@ public:
virtual ~File() {}
virtual void close() = 0;
virtual size_t read(void *in, size_t size) = 0;
- virtual bool readLine(char *in, size_t size) = 0;
virtual bool readBit8u(Bit8u *in) = 0;
virtual bool readBit16u(Bit16u *in);
virtual bool readBit32u(Bit32u *in);
@@ -55,7 +54,6 @@ public:
bool open(const char *filename, OpenMode mode);
void close();
size_t read(void *in, size_t size);
- bool readLine(char *in, size_t size);
bool readBit8u(Bit8u *in);
size_t write(const void *out, size_t size);
bool writeBit8u(Bit8u out);
diff --git a/sound/softsynth/mt32/partial.cpp b/sound/softsynth/mt32/partial.cpp
index 1aab2a8de7..2866c7757d 100644
--- a/sound/softsynth/mt32/partial.cpp
+++ b/sound/softsynth/mt32/partial.cpp
@@ -25,7 +25,7 @@
#include "mt32emu.h"
-#if defined(MACOSX) || defined(__solaris__)
+#if defined(MACOSX) || defined(SOLARIS)
// Older versions of Mac OS X didn't supply a powf function, so using it
// will cause a binary incompatibility when trying to run a binary built
// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
diff --git a/sound/softsynth/mt32/synth.cpp b/sound/softsynth/mt32/synth.cpp
index 785e8098c7..366da50d01 100644
--- a/sound/softsynth/mt32/synth.cpp
+++ b/sound/softsynth/mt32/synth.cpp
@@ -25,7 +25,7 @@
#include "mt32emu.h"
-#if defined(MACOSX) || defined(__solaris__)
+#if defined(MACOSX) || defined(SOLARIS)
// Older versions of Mac OS X didn't supply a powf function, so using it
// will cause a binary incompatibility when trying to run a binary built
// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
diff --git a/sound/softsynth/mt32/tables.cpp b/sound/softsynth/mt32/tables.cpp
index 20b7cf289a..5865ba2950 100644
--- a/sound/softsynth/mt32/tables.cpp
+++ b/sound/softsynth/mt32/tables.cpp
@@ -25,7 +25,7 @@
#include "mt32emu.h"
-#if defined(MACOSX) || defined(__solaris__)
+#if defined(MACOSX) || defined(SOLARIS)
// Older versions of Mac OS X didn't supply a powf function, so using it
// will cause a binary incompatibility when trying to run a binary built
// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
diff --git a/sound/vorbis.cpp b/sound/vorbis.cpp
index 64f67d2a13..da29b1b454 100644
--- a/sound/vorbis.cpp
+++ b/sound/vorbis.cpp
@@ -27,7 +27,7 @@
#ifdef USE_VORBIS
-#include "common/file.h"
+#include "common/stream.h"
#include "common/util.h"
#include "sound/audiostream.h"
diff --git a/sound/vorbis.h b/sound/vorbis.h
index 758bfd9487..012c33e310 100644
--- a/sound/vorbis.h
+++ b/sound/vorbis.h
@@ -31,7 +31,6 @@
#ifdef USE_VORBIS
namespace Common {
- class File;
class SeekableReadStream;
}
diff --git a/sound/wave.cpp b/sound/wave.cpp
index 249518aafc..72a3992401 100644
--- a/sound/wave.cpp
+++ b/sound/wave.cpp
@@ -34,7 +34,7 @@
namespace Audio {
bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
- const uint32 initialPos = stream.pos();
+ const int32 initialPos = stream.pos();
byte buf[4+1];
buf[4] = 0;
@@ -45,7 +45,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
return false;
}
- uint32 wavLength = stream.readUint32LE();
+ int32 wavLength = stream.readUint32LE();
stream.read(buf, 4);
if (memcmp(buf, "WAVE", 4) != 0) {
diff --git a/test/common/bufferedreadstream.h b/test/common/bufferedreadstream.h
index 7733949d9a..c580fd18de 100644
--- a/test/common/bufferedreadstream.h
+++ b/test/common/bufferedreadstream.h
@@ -9,12 +9,11 @@ class BufferedReadStreamTestSuite : public CxxTest::TestSuite {
Common::MemoryReadStream ms(contents, 10);
// Use a buffer size of 4 -- note that 10 % 4 != 0,
- // so we test what happens if the cache can't be completly
+ // so we test what happens if the cache can't be completely
// refilled.
Common::BufferedReadStream srs(&ms, 4);
- int i;
- byte b;
+ byte i, b;
for (i = 0; i < 10; ++i) {
TS_ASSERT( !srs.eos() );
@@ -22,6 +21,10 @@ class BufferedReadStreamTestSuite : public CxxTest::TestSuite {
TS_ASSERT_EQUALS( i, b );
}
- TS_ASSERT( srs.eos() );
+ TS_ASSERT( !srs.eos() );
+
+ b = srs.readByte();
+
+ TS_ASSERT ( srs.eos() );
}
};
diff --git a/test/common/bufferedseekablereadstream.h b/test/common/bufferedseekablereadstream.h
index 63941904cd..f039acd2a8 100644
--- a/test/common/bufferedseekablereadstream.h
+++ b/test/common/bufferedseekablereadstream.h
@@ -10,8 +10,7 @@ class BufferedSeekableReadStreamTestSuite : public CxxTest::TestSuite {
Common::BufferedSeekableReadStream ssrs(&ms, 4);
- int i;
- byte b;
+ byte i, b;
for (i = 0; i < 10; ++i) {
TS_ASSERT( !ssrs.eos() );
@@ -21,6 +20,9 @@ class BufferedSeekableReadStreamTestSuite : public CxxTest::TestSuite {
TS_ASSERT_EQUALS( i, b );
}
+ TS_ASSERT( !ssrs.eos() );
+
+ TS_ASSERT( 0 == ssrs.read(&b, 1) );
TS_ASSERT( ssrs.eos() );
}
@@ -31,34 +33,37 @@ class BufferedSeekableReadStreamTestSuite : public CxxTest::TestSuite {
Common::BufferedSeekableReadStream ssrs(&ms, 4);
byte b;
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)0 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 0 );
ssrs.seek(1, SEEK_SET);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)1 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 1 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 1 );
ssrs.seek(5, SEEK_CUR);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)7 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 7 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 7 );
ssrs.seek(-3, SEEK_CUR);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)5 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 5 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 5 );
ssrs.seek(0, SEEK_END);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)10 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 10 );
+ TS_ASSERT( !ssrs.eos() );
+ b = ssrs.readByte();
TS_ASSERT( ssrs.eos() );
ssrs.seek(3, SEEK_END);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)7 );
+ TS_ASSERT( !ssrs.eos() );
+ TS_ASSERT_EQUALS( ssrs.pos(), 7 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 7 );
ssrs.seek(8, SEEK_END);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)2 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 2 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 2 );
}
diff --git a/test/common/hashmap.h b/test/common/hashmap.h
index 5aa609bc00..acde1da028 100644
--- a/test/common/hashmap.h
+++ b/test/common/hashmap.h
@@ -1,12 +1,12 @@
#include <cxxtest/TestSuite.h>
#include "common/hashmap.h"
+#include "common/hash-str.h"
class HashMapTestSuite : public CxxTest::TestSuite
{
public:
- void test_empty_clear( void )
- {
+ void test_empty_clear(void) {
Common::HashMap<int, int> container;
TS_ASSERT( container.empty() );
container[0] = 17;
@@ -14,10 +14,17 @@ class HashMapTestSuite : public CxxTest::TestSuite
TS_ASSERT( !container.empty() );
container.clear();
TS_ASSERT( container.empty() );
+
+ Common::StringMap container2;
+ TS_ASSERT( container2.empty() );
+ container2["foo"] = "bar";
+ container2["quux"] = "blub";
+ TS_ASSERT( !container2.empty() );
+ container2.clear();
+ TS_ASSERT( container2.empty() );
}
- void test_contains( void )
- {
+ void test_contains(void) {
Common::HashMap<int, int> container;
container[0] = 17;
container[1] = 33;
@@ -25,25 +32,41 @@ class HashMapTestSuite : public CxxTest::TestSuite
TS_ASSERT( container.contains(1) );
TS_ASSERT( !container.contains(17) );
TS_ASSERT( !container.contains(-1) );
+
+ Common::StringMap container2;
+ container2["foo"] = "bar";
+ container2["quux"] = "blub";
+ TS_ASSERT( container2.contains("foo") );
+ TS_ASSERT( container2.contains("quux") );
+ TS_ASSERT( !container2.contains("bar") );
+ TS_ASSERT( !container2.contains("asdf") );
}
- void test_add_remove( void )
- {
+ void test_add_remove(void) {
Common::HashMap<int, int> container;
container[0] = 17;
container[1] = 33;
+ container[2] = 45;
+ container[3] = 12;
+ container[4] = 96;
TS_ASSERT( container.contains(1) );
container.erase(1);
TS_ASSERT( !container.contains(1) );
container[1] = 42;
TS_ASSERT( container.contains(1) );
container.erase(0);
+ TS_ASSERT( !container.empty() );
container.erase(1);
+ TS_ASSERT( !container.empty() );
+ container.erase(2);
+ TS_ASSERT( !container.empty() );
+ container.erase(3);
+ TS_ASSERT( !container.empty() );
+ container.erase(4);
TS_ASSERT( container.empty() );
}
- void test_lookup( void )
- {
+ void test_lookup(void) {
Common::HashMap<int, int> container;
container[0] = 17;
container[1] = -1;
@@ -58,8 +81,7 @@ class HashMapTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( container[4], 96 );
}
- void test_iterator_begin_end( void )
- {
+ void test_iterator_begin_end(void) {
Common::HashMap<int, int> container;
// The container is initially empty ...
@@ -74,12 +96,11 @@ class HashMapTestSuite : public CxxTest::TestSuite
TS_ASSERT( container.begin() == container.end() );
}
- void test_hash_map_copy( void )
- {
- Common::HashMap<int, int> map1, map2;
+ void test_hash_map_copy(void) {
+ Common::HashMap<int, int> map1, container2;
map1[323] = 32;
- map2 = map1;
- TS_ASSERT_EQUALS(map2[323], 32);
+ container2 = map1;
+ TS_ASSERT_EQUALS(container2[323], 32);
}
// TODO: Add test cases for iterators, find, ...
diff --git a/test/common/queue.h b/test/common/queue.h
new file mode 100644
index 0000000000..7eedec9a5d
--- /dev/null
+++ b/test/common/queue.h
@@ -0,0 +1,80 @@
+#include <cxxtest/TestSuite.h>
+
+#include "common/queue.h"
+
+class QueueTestSuite : public CxxTest::TestSuite {
+public:
+ void test_empty_clear() {
+ Common::Queue<int> queue;
+ TS_ASSERT(queue.empty());
+
+ queue.push(1);
+ queue.push(2);
+ TS_ASSERT(!queue.empty());
+
+ queue.clear();
+
+ TS_ASSERT(queue.empty());
+ }
+
+ void test_size() {
+ Common::Queue<int> queue;
+ TS_ASSERT_EQUALS(queue.size(), 0);
+
+ queue.push(5);
+ TS_ASSERT_EQUALS(queue.size(), 1);
+
+ queue.push(9);
+ queue.push(0);
+ TS_ASSERT_EQUALS(queue.size(), 3);
+
+ queue.pop();
+ TS_ASSERT_EQUALS(queue.size(), 2);
+ }
+
+ void test_front_back_pop() {
+ Common::Queue<int> queue;
+
+ queue.push( 42);
+ queue.push(-23);
+
+ TS_ASSERT_EQUALS(queue.front(), 42);
+ TS_ASSERT_EQUALS(queue.back(), -23);
+
+ queue.front() = -23;
+ queue.back() = 42;
+ TS_ASSERT_EQUALS(queue.front(), -23);
+ TS_ASSERT_EQUALS(queue.back(), 42);
+
+ queue.pop();
+ TS_ASSERT_EQUALS(queue.front(), 42);
+ }
+
+ void test_assign() {
+ Common::Queue<int> q1, q2;
+
+ for (int i = 0; i < 5; ++i) {
+ q1.push(i);
+ q2.push(4-i);
+ }
+
+ Common::Queue<int> q3(q1);
+
+ for (int i = 0; i < 5; ++i) {
+ TS_ASSERT_EQUALS(q3.front(), i);
+ q3.pop();
+ }
+
+ TS_ASSERT(q3.empty());
+
+ q3 = q2;
+
+ for (int i = 4; i >= 0; --i) {
+ TS_ASSERT_EQUALS(q3.front(), i);
+ q3.pop();
+ }
+
+ TS_ASSERT(q3.empty());
+ }
+};
+
diff --git a/test/common/seekablesubreadstream.h b/test/common/seekablesubreadstream.h
index 4e517093a5..68febc7fd6 100644
--- a/test/common/seekablesubreadstream.h
+++ b/test/common/seekablesubreadstream.h
@@ -17,12 +17,14 @@ class SeekableSubReadStreamTestSuite : public CxxTest::TestSuite {
for (i = start; i < end; ++i) {
TS_ASSERT( !ssrs.eos() );
- TS_ASSERT_EQUALS( uint32(i - start), ssrs.pos() );
+ TS_ASSERT_EQUALS( i - start, ssrs.pos() );
ssrs.read(&b, 1);
TS_ASSERT_EQUALS( i, b );
}
+ TS_ASSERT( !ssrs.eos() );
+ TS_ASSERT( 0 == ssrs.read(&b, 1) );
TS_ASSERT( ssrs.eos() );
}
@@ -33,34 +35,37 @@ class SeekableSubReadStreamTestSuite : public CxxTest::TestSuite {
Common::SeekableSubReadStream ssrs(&ms, 1, 9);
byte b;
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)0 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 0 );
ssrs.seek(1, SEEK_SET);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)1 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 1 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 2 );
ssrs.seek(5, SEEK_CUR);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)7 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 7 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 8 );
ssrs.seek(-3, SEEK_CUR);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)5 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 5 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 6 );
ssrs.seek(0, SEEK_END);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)8 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 8 );
+ TS_ASSERT( !ssrs.eos() );
+ b = ssrs.readByte();
TS_ASSERT( ssrs.eos() );
ssrs.seek(3, SEEK_END);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)5 );
+ TS_ASSERT( !ssrs.eos() );
+ TS_ASSERT_EQUALS( ssrs.pos(), 5 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 6 );
ssrs.seek(8, SEEK_END);
- TS_ASSERT_EQUALS( ssrs.pos(), (uint32)0 );
+ TS_ASSERT_EQUALS( ssrs.pos(), 0 );
b = ssrs.readByte();
TS_ASSERT_EQUALS( b, 1 );
}
diff --git a/test/common/str.h b/test/common/str.h
index 72d4df6f61..c352bd1887 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -157,4 +157,81 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(str, "TEST IT, NOW! 42");
TS_ASSERT_EQUALS(str2, "Test it, NOW! 42");
}
+
+ void test_deleteChar( void )
+ {
+ Common::String str("01234567890123456789012345678901");
+ str.deleteChar(10);
+ TS_ASSERT_EQUALS( str, "0123456789123456789012345678901" );
+ str.deleteChar(10);
+ TS_ASSERT_EQUALS( str, "012345678923456789012345678901" );
+ }
+
+ void test_sharing( void )
+ {
+ Common::String str("01234567890123456789012345678901");
+ Common::String str2(str);
+ TS_ASSERT_EQUALS( str2, "01234567890123456789012345678901" );
+ str.deleteLastChar();
+ TS_ASSERT_EQUALS( str, "0123456789012345678901234567890" );
+ TS_ASSERT_EQUALS( str2, "01234567890123456789012345678901" );
+ }
+
+ void test_lastPathComponent(void) {
+ TS_ASSERT(Common::lastPathComponent("/", '/') == "");
+ TS_ASSERT(Common::lastPathComponent("/foo/bar", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("/foo//bar/", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("/foo/./bar", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("/foo//./bar//", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("/foo//.bar//", '/') == ".bar");
+
+ TS_ASSERT(Common::lastPathComponent("", '/') == "");
+ TS_ASSERT(Common::lastPathComponent("foo/bar", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("foo//bar/", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("foo/./bar", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("foo//./bar//", '/') == "bar");
+ TS_ASSERT(Common::lastPathComponent("foo//.bar//", '/') == ".bar");
+ }
+
+ void test_normalizePath(void) {
+ TS_ASSERT(Common::normalizePath("/", '/') == "/");
+ TS_ASSERT(Common::normalizePath("/foo/bar", '/') == "/foo/bar");
+ TS_ASSERT(Common::normalizePath("/foo//bar/", '/') == "/foo/bar");
+ TS_ASSERT(Common::normalizePath("/foo/./bar", '/') == "/foo/bar");
+ TS_ASSERT(Common::normalizePath("/foo//./bar//", '/') == "/foo/bar");
+ TS_ASSERT(Common::normalizePath("/foo//.bar//", '/') == "/foo/.bar");
+
+ TS_ASSERT(Common::normalizePath("", '/') == "");
+ TS_ASSERT(Common::normalizePath("foo/bar", '/') == "foo/bar");
+ TS_ASSERT(Common::normalizePath("foo//bar/", '/') == "foo/bar");
+ TS_ASSERT(Common::normalizePath("foo/./bar", '/') == "foo/bar");
+ TS_ASSERT(Common::normalizePath("foo//./bar//", '/') == "foo/bar");
+ TS_ASSERT(Common::normalizePath("foo//.bar//", '/') == "foo/.bar");
+ }
+
+ void test_matchString(void) {
+ TS_ASSERT( Common::matchString("", "*"));
+ TS_ASSERT( Common::matchString("a", "*"));
+ TS_ASSERT( Common::matchString("monkey.s01", "*"));
+
+ TS_ASSERT(!Common::matchString("", "?"));
+ TS_ASSERT( Common::matchString("a", "?"));
+ TS_ASSERT(!Common::matchString("monkey.s01", "?"));
+
+ TS_ASSERT( Common::matchString("monkey.s01", "monkey.s??"));
+ TS_ASSERT( Common::matchString("monkey.s99", "monkey.s??"));
+ TS_ASSERT(!Common::matchString("monkey.s101", "monkey.s??"));
+
+ TS_ASSERT( Common::matchString("monkey.s01", "monkey.s?1"));
+ TS_ASSERT(!Common::matchString("monkey.s99", "monkey.s?1"));
+ TS_ASSERT(!Common::matchString("monkey.s101", "monkey.s?1"));
+
+ TS_ASSERT( Common::matchString("monkey.s01", "monkey.s*"));
+ TS_ASSERT( Common::matchString("monkey.s99", "monkey.s*"));
+ TS_ASSERT( Common::matchString("monkey.s101", "monkey.s*"));
+
+ TS_ASSERT( Common::matchString("monkey.s01", "monkey.s*1"));
+ TS_ASSERT(!Common::matchString("monkey.s99", "monkey.s*1"));
+ TS_ASSERT( Common::matchString("monkey.s101", "monkey.s*1"));
+ }
};
diff --git a/test/common/stream.h b/test/common/stream.h
new file mode 100644
index 0000000000..a605d34a2c
--- /dev/null
+++ b/test/common/stream.h
@@ -0,0 +1,46 @@
+#include <cxxtest/TestSuite.h>
+
+#include "common/stream.h"
+
+class ReadLineStreamTestSuite : public CxxTest::TestSuite {
+ public:
+ void test_readline(void) {
+ byte contents[] = { 'a', 'b', '\n', '\n', 'c', '\n' };
+ Common::MemoryReadStream ms(contents, sizeof(contents));
+
+ char buffer[100];
+
+ TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer)));
+ TS_ASSERT(0 == strcmp(buffer, "ab\n"));
+
+ TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer)));
+ TS_ASSERT(0 == strcmp(buffer, "\n"));
+
+ TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer)));
+ TS_ASSERT(0 == strcmp(buffer, "c\n"));
+
+ TS_ASSERT(!ms.eos());
+
+ TS_ASSERT(0 == ms.readLine_NEW(buffer, sizeof(buffer)));
+
+ TS_ASSERT(ms.eos());
+ }
+
+ void test_readline2(void) {
+ byte contents[] = { 'a', 'b', '\n', '\n', 'c' };
+ Common::MemoryReadStream ms(contents, sizeof(contents));
+
+ char buffer[100];
+
+ TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer)));
+ TS_ASSERT(0 == strcmp(buffer, "ab\n"));
+
+ TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer)));
+ TS_ASSERT(0 == strcmp(buffer, "\n"));
+
+ TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer)));
+ TS_ASSERT(0 == strcmp(buffer, "c"));
+
+ TS_ASSERT(ms.eos());
+ }
+};
diff --git a/test/common/subreadstream.h b/test/common/subreadstream.h
index 4e14448c06..2ac453576a 100644
--- a/test/common/subreadstream.h
+++ b/test/common/subreadstream.h
@@ -21,6 +21,8 @@ class SubReadStreamTestSuite : public CxxTest::TestSuite {
TS_ASSERT_EQUALS( i, b );
}
+ TS_ASSERT( !srs.eos() );
+ b = srs.readByte();
TS_ASSERT( srs.eos() );
}
};
diff --git a/tools/create_drascula/create_drascula.cpp b/tools/create_drascula/create_drascula.cpp
index 2676376e42..e150fa7518 100644
--- a/tools/create_drascula/create_drascula.cpp
+++ b/tools/create_drascula/create_drascula.cpp
@@ -38,7 +38,7 @@
#include "create_drascula.h"
#include "staticdata.h"
-#define DRASCULA_DAT_VER 2 // 1 byte
+#define DRASCULA_DAT_VER 4 // 1 byte
static void writeByte(FILE *fp, uint8 b) {
fwrite(&b, 1, 1, fp);
@@ -172,6 +172,16 @@ int main(int argc, char *argv[]) {
writeSint16BE(outFile, roomActions[i].speechID);
}
+ // Write talk sequences
+ writeUint16BE(outFile, ARRAYSIZE(talkSequences));
+
+ for (i = 0; i < ARRAYSIZE(talkSequences); i++) {
+ writeSint16BE(outFile, talkSequences[i].chapter);
+ writeSint16BE(outFile, talkSequences[i].sequence);
+ writeSint16BE(outFile, talkSequences[i].commandType);
+ writeSint16BE(outFile, talkSequences[i].action);
+ }
+
// langs
writeUint16BE(outFile, NUM_LANGS);
diff --git a/tools/create_drascula/create_drascula.h b/tools/create_drascula/create_drascula.h
index ed81651e86..51287c43d2 100644
--- a/tools/create_drascula/create_drascula.h
+++ b/tools/create_drascula/create_drascula.h
@@ -93,5 +93,39 @@ struct RoomUpdate {
int type; // 0 - background, 1 - rect
};
+enum TalkSequenceCommands {
+ kPause = 0,
+ kSetFlag = 1,
+ kClearFlag = 2,
+ kPickObject = 3,
+ kAddObject = 4,
+ kBreakOut = 5,
+ kConverse = 6,
+ kPlaceVB = 7,
+ kUpdateRoom = 8,
+ kUpdateScreen = 9,
+ kTrackProtagonist = 10,
+ kPlaySound = 11,
+ kFinishSound = 12,
+ kTalkerGeneral = 13,
+ kTalkerDrunk = 14,
+ kTalkerPianist = 15,
+ kTalkerBJ = 16,
+ kTalkerVBNormal = 17,
+ kTalkerVBDoor = 18,
+ kTalkerIgorSeated = 19,
+ kTalkerWerewolf = 20,
+ kTalkerMus = 21,
+ kTalkerDrascula = 22,
+ kTalkerBartender0 = 23,
+ kTalkerBartender1 = 24
+};
+
+struct TalkSequenceCommand {
+ int chapter;
+ int sequence;
+ int commandType;
+ int action;
+};
#endif /* CREATE_DRASCULA_H */
diff --git a/tools/create_drascula/staticdata.h b/tools/create_drascula/staticdata.h
index 4778c530e4..f5fd018172 100644
--- a/tools/create_drascula/staticdata.h
+++ b/tools/create_drascula/staticdata.h
@@ -636,6 +636,254 @@ RoomTalkAction roomActions[] = {
};
+TalkSequenceCommand talkSequences[] = {
+ // Chapter, sequence, command type, action
+ { 1, 2, kTalkerBJ, 2 },
+ { 1, 2, kTalkerGeneral, 215 },
+ { 1, 2, kTalkerBJ, 3 },
+ { 1, 2, kTalkerGeneral, 216 },
+ { 1, 2, kTalkerBJ, 4 },
+ { 1, 2, kTalkerBJ, 5 },
+ { 1, 2, kTalkerBJ, 6 },
+ { 1, 2, kTalkerGeneral, 217 },
+ { 1, 2, kTalkerBJ, 7 },
+ { 1, 2, kTalkerGeneral, 218 },
+ { 1, 2, kTalkerBJ, 8 },
+ { 1, 2, kTalkerGeneral, 219 },
+ { 1, 2, kTalkerBJ, 9 },
+ { 1, 2, kTalkerGeneral, 220 },
+ { 1, 2, kTalkerGeneral, 221 },
+ { 1, 2, kTalkerBJ, 10 },
+ { 1, 2, kTalkerGeneral, 222 },
+ //
+ { 1, 3, kTalkerGeneral, 192 },
+ { 1, 3, kTalkerBartender0, 1 },
+ { 1, 3, kTalkerGeneral, 193 },
+ { 1, 3, kTalkerBartender0, 2 },
+ { 1, 3, kTalkerGeneral, 194 },
+ { 1, 3, kTalkerBartender0, 3 },
+ { 1, 3, kTalkerGeneral, 195 },
+ { 1, 3, kTalkerBartender0, 4 },
+ { 1, 3, kTalkerGeneral, 196 },
+ { 1, 3, kTalkerBartender0, 5 },
+ { 1, 3, kTalkerBartender0, 6 },
+ { 1, 3, kTalkerGeneral, 197 },
+ { 1, 3, kTalkerBartender0, 7 },
+ { 1, 3, kTalkerGeneral, 198 },
+ { 1, 3, kTalkerBartender0, 8 },
+ { 1, 3, kTalkerGeneral, 199 },
+ { 1, 3, kTalkerBartender0, 9 },
+ { 1, 3, kTalkerGeneral, 200 },
+ { 1, 3, kTalkerGeneral, 201 },
+ { 1, 3, kTalkerGeneral, 202 },
+ { 1, 3, kSetFlag, 0 },
+ //
+ { 1, 10, kTalkerDrunk, 1 },
+ { 1, 11, kTalkerDrunk, 2 },
+ { 1, 12, kTalkerDrunk, 3 },
+ //
+ { 2, 8, kTalkerPianist, 6 },
+ { 2, 8, kTalkerGeneral, 358 },
+ { 2, 8, kTalkerPianist, 7 },
+ { 2, 8, kTalkerPianist, 8 },
+ //
+ { 2, 9, kTalkerPianist, 9 },
+ { 2, 9, kTalkerPianist, 10 },
+ { 2, 9, kTalkerPianist, 11 },
+ //
+ { 2, 10, kTalkerPianist, 12 },
+ { 2, 10, kTalkerGeneral, 361 },
+ { 2, 10, kPause, 40 },
+ { 2, 10, kTalkerPianist, 13 },
+ { 2, 10, kTalkerGeneral, 362 },
+ { 2, 10, kTalkerPianist, 14 },
+ { 2, 10, kTalkerGeneral, 363 },
+ { 2, 10, kTalkerPianist, 15 },
+ { 2, 10, kTalkerGeneral, 364 },
+ { 2, 10, kTalkerPianist, 16 },
+ { 2, 10, kTalkerGeneral, 365 },
+ //
+ { 2, 11, kTalkerGeneral, 352 },
+ { 2, 11, kTalkerBartender0, 1 },
+ { 2, 11, kTalkerGeneral, 353 },
+ { 2, 11, kTalkerBartender0, 17 },
+ { 2, 11, kTalkerGeneral, 354 },
+ { 2, 11, kTalkerBartender0, 18 },
+ { 2, 11, kTalkerGeneral, 355 },
+ { 2, 11, kPause, 40 },
+ { 2, 11, kTalkerBartender0, 82 },
+ //
+ { 2, 13, kTalkerGeneral, 103 },
+ { 2, 13, kTalkerDrunk, 4 },
+ { 2, 13, kSetFlag, 12 },
+ { 2, 13, kTalkerGeneral, 367 },
+ { 2, 13, kTalkerDrunk, 5 },
+ { 2, 13, kSetFlag, 12 },
+ { 2, 13, kTalkerGeneral, 368 },
+ { 2, 13, kTalkerDrunk, 6 },
+ { 2, 13, kTalkerDrunk, 7 },
+ { 2, 13, kSetFlag, 41 },
+ { 2, 13, kConverse, 2 },
+ //
+ { 2, 15, kTalkerDrunk, 8 },
+ { 2, 15, kPause, 7 },
+ { 2, 15, kTalkerDrunk, 9 },
+ { 2, 15, kTalkerDrunk, 10 },
+ { 2, 15, kTalkerDrunk, 11 },
+ //
+ { 2, 17, kTalkerDrunk, 13 },
+ { 2, 17, kTalkerDrunk, 14 },
+ { 2, 17, kSetFlag, 40 },
+ { 2, 19, kTalkerVBDoor, 5 },
+ { 2, 21, kTalkerVBDoor, 6 },
+ //
+ { 2, 22, kTalkerGeneral, 374 },
+ { 2, 22, kTrackProtagonist, 2 },
+ { 2, 22, kUpdateRoom, -1 },
+ { 2, 22, kUpdateScreen, -1 },
+ { 2, 22, kPlaySound, 13 },
+ { 2, 22, kFinishSound, -1 },
+ { 2, 22, kTrackProtagonist, 1 },
+ { 2, 22, kTalkerVBDoor, 1 },
+ { 2, 22, kTalkerGeneral, 375 },
+ { 2, 22, kTalkerVBDoor, 2 },
+ { 2, 22, kTalkerGeneral, 376 },
+ { 2, 22, kTalkerVBDoor, 3 },
+ { 2, 22, kSetFlag, 18 },
+ //
+ { 2, 28, kTalkerVBNormal, 27 },
+ { 2, 28, kTalkerVBNormal, 28 },
+ { 2, 28, kTalkerVBNormal, 29 },
+ { 2, 28, kTalkerVBNormal, 30 },
+ //
+ { 2, 29, kTalkerVBNormal, 32 },
+ { 2, 29, kTalkerGeneral, 398 },
+ { 2, 29, kTalkerVBNormal, 33 },
+ { 2, 29, kTalkerGeneral, 399 },
+ { 2, 29, kTalkerVBNormal, 34 },
+ { 2, 29, kTalkerVBNormal, 35 },
+ { 2, 29, kTalkerGeneral, 400 },
+ { 2, 29, kTalkerVBNormal, 36 },
+ { 2, 29, kTalkerVBNormal, 37 },
+ { 2, 29, kTalkerGeneral, 386 },
+ { 2, 29, kTalkerVBNormal, 38 },
+ { 2, 29, kTalkerVBNormal, 39 },
+ { 2, 29, kTalkerGeneral, 401 },
+ { 2, 29, kTalkerVBNormal, 40 },
+ { 2, 29, kTalkerVBNormal, 41 },
+ { 2, 29, kSetFlag, 33 },
+ //
+ { 2, 30, kTalkerVBNormal, 31 },
+ { 2, 30, kTalkerGeneral, 396 },
+ //
+ { 2, 31, kTrackProtagonist, 2 },
+ { 2, 31, kUpdateRoom, -1 },
+ { 2, 31, kUpdateScreen, -1 },
+ { 2, 31, kPause, 78 },
+ { 2, 31, kTrackProtagonist, 0 },
+ { 2, 31, kUpdateRoom, -1 },
+ { 2, 31, kUpdateScreen, -1 },
+ { 2, 31, kPause, 22 },
+ { 2, 31, kTalkerGeneral, 406 },
+ { 2, 31, kPlaceVB, 98 },
+ { 2, 31, kTalkerVBNormal, 45 },
+ { 2, 31, kTalkerVBNormal, 46 },
+ { 2, 31, kTalkerVBNormal, 47 },
+ { 2, 31, kTalkerGeneral, 407 },
+ { 2, 31, kTalkerVBNormal, 48 },
+ { 2, 31, kTalkerVBNormal, 49 },
+ { 2, 31, kTalkerGeneral, 408 },
+ { 2, 31, kTalkerVBNormal, 50 },
+ { 2, 31, kTalkerVBNormal, 51 },
+ { 2, 31, kTalkerGeneral, 409 },
+ { 2, 31, kTalkerVBNormal, 52 },
+ { 2, 31, kTalkerVBNormal, 53 },
+ { 2, 31, kPause, 12 },
+ { 2, 31, kTalkerVBNormal, 54 },
+ { 2, 31, kTalkerVBNormal, 55 },
+ { 2, 31, kTalkerGeneral, 410 },
+ { 2, 31, kTalkerVBNormal, 56 },
+ { 2, 31, kBreakOut, 1 },
+ { 2, 31, kClearFlag, 38 },
+ { 2, 31, kSetFlag, 36 },
+ //
+ { 4, 2, kTalkerIgorSeated, 16 },
+ { 4, 2, kTalkerGeneral, 278 },
+ { 4, 2, kTalkerIgorSeated, 17 },
+ { 4, 2, kTalkerGeneral, 279 },
+ { 4, 2, kTalkerIgorSeated, 18 },
+ { 4, 3, kTalkerIgorSeated, 19 },
+ { 4, 3, kTalkerIgorSeated, 20 },
+ { 4, 3, kTalkerGeneral, 281 },
+ { 4, 4, kTalkerGeneral, 287 },
+ { 4, 4, kTalkerIgorSeated, 21 },
+ { 4, 4, kTalkerGeneral, 284 },
+ { 4, 4, kTalkerIgorSeated, 22 },
+ { 4, 4, kTalkerGeneral, 285 },
+ { 4, 4, kTalkerIgorSeated, 23 },
+ //
+ { 5, 2, kTalkerBJ, 22 },
+ { 5, 3, kTalkerBJ, 23 },
+ { 5, 3, kPickObject, 10 },
+ { 5, 3, kBreakOut, 1 },
+ //
+ { 5, 4, kSetFlag, 7 },
+ { 5, 4, kUpdateRoom, -1 },
+ { 5, 4, kUpdateScreen, -1 },
+ { 5, 4, kTalkerGeneral, 228 },
+ { 5, 4, kTalkerWerewolf, 1 },
+ { 5, 4, kTalkerWerewolf, 2 },
+ { 5, 4, kPause, 23 },
+ { 5, 4, kTalkerGeneral, 229 },
+ { 5, 4, kTalkerWerewolf, 3 },
+ { 5, 4, kTalkerWerewolf, 4 },
+ { 5, 4, kTalkerGeneral, 230 },
+ { 5, 4, kTalkerWerewolf, 5 },
+ { 5, 4, kTalkerGeneral, 231 },
+ { 5, 4, kTalkerWerewolf, 6 },
+ { 5, 4, kTalkerWerewolf, 7 },
+ { 5, 4, kPause, 33 },
+ { 5, 4, kTalkerGeneral, 232 },
+ { 5, 4, kTalkerWerewolf, 8 },
+ //
+ { 5, 6, kTalkerWerewolf, 9 },
+ { 5, 6, kTalkerGeneral, 234 },
+ { 5, 7, kTalkerWerewolf, 10 },
+ { 5, 7, kTalkerGeneral, 236 },
+ { 5, 7, kTalkerWerewolf, 11 },
+ { 5, 7, kTalkerWerewolf, 12 },
+ { 5, 7, kTalkerWerewolf, 13 },
+ { 5, 7, kPause, 34 },
+ { 5, 7, kTalkerWerewolf, 14 },
+ { 5, 8, kTalkerWerewolf, 15 },
+ { 5, 8, kTalkerGeneral, 238 },
+ { 5, 8, kTalkerWerewolf, 16 },
+ { 5, 15, kTalkerMus, 4 },
+ { 5, 15, kTalkerMus, 5 },
+ { 5, 15, kTalkerMus, 6 },
+ { 5, 15, kTalkerGeneral, 291 },
+ { 5, 15, kTalkerMus, 7 },
+ { 5, 16, kTalkerMus, 8 },
+ { 5, 17, kTalkerMus, 9 },
+ //
+ { 6, 2, kTalkerDrascula, 24 },
+ { 6, 3, kTalkerDrascula, 24 },
+ { 6, 4, kTalkerDrascula, 25 },
+ { 6, 11, kTalkerBartender1, 10 },
+ { 6, 11, kTalkerGeneral, 268 },
+ { 6, 11, kTalkerBartender1, 11 },
+ { 6, 12, kTalkerBartender1, 12 },
+ { 6, 12, kTalkerGeneral, 270 },
+ { 6, 12, kTalkerBartender1, 13 },
+ { 6, 12, kTalkerBartender1, 14 },
+ { 6, 13, kTalkerBartender1, 15 },
+ { 6, 14, kTalkerBartender1, 24 },
+ { 6, 14, kAddObject, 21 },
+ { 6, 14, kSetFlag, 10 },
+ { 6, 14, kBreakOut, 1 },
+ { 6, 15, kTalkerBartender1, 16 }
+};
+
const char *_text[NUM_LANGS][NUM_TEXT] = {
{
// 0
@@ -3056,84 +3304,84 @@ const char *_text[NUM_LANGS][NUM_TEXT] = {
{
// 0
"",
- "\220 la seconda porta pi\243 grande che ho vista nella mia vita",
- "Forse.., no",
- "\202 chiusa con tabelle. La chiesa deve essere abbandonata da tanti anni fa.",
- "Ma se non la ho aperta",
+ "\324 LA SECONDA PORTA PI\353 GRANDE CHE IO ABBIA MAI VISTO",
+ "BEH, FORSE NO",
+ "\324 SIGILLATA CON TAVOLE. LA CHIESA DEV'ESSERE STATA ABBANDONATA PARECCHI ANNI FA.",
+ "NON L'HO APERTA",
// 5
- "Che faccio? La tolgo?",
- "Ciao porta. Vado a farti una cornice",
- "Troppo per me",
- "una finestra chiusa con tabelle",
- "Non ce la faccio",
+ "CHE FACCIO? LA TOLGO?",
+ "CIAO PORTA. STO PER TRASFORMARTI IN UNO STIPITE.",
+ "\324 TROPPO PER ME.",
+ "UNA FINESTRA SIGILLATA CON TAVOLE.",
+ "NON POSSO.",
// 10
- "Eccolo",
- "E per che?",
- "Ciao finestra. Hai qualcosa da fare stasera?",
- "No senza il permesso del Ministero dei Lavori Pubblici",
- "-eh! quella finestra ha soltanto una tabella..",
+ "GI\267 FATTO.",
+ "E PERCH\220?",
+ "CIAO FINESTRA. HAI QUALCOSA DA FARE STANOTTE?",
+ "NON SENZA IL PERMESSO DEL MINISTERO DELLE OPERE PUBBLICHE",
+ "SE SOLO QUESTA FINESTRA NON FOSSE SIGILLATA...",
// 15
- "-Eooooo! -Finestra!",
- "Tu, ciao",
- "",
- "Non ce la faccio",
- "Va bene dov'\202 ",
+ "YOO-HOO! FINESTRA!",
+ "SALVE.",
+ "COME QUELLA DELLA MICROCHOF.",
+ "NON RIESCO AD ARRIVARCI.",
+ "STA BENE DOV'\324.",
// 20
"",
- "\220 una tomba in forma di croce",
- "Non grazie",
- "Ciao morto. Vuoi delle patatine a forma di vermi?",
- "Si. Come in Poltergueist.",
+ "\324 UNA LAPIDE A FORMA DI CROCE",
+ "NO GRAZIE.",
+ "CIAO, MORTO. NON TI SCOMODARE AD ALZARTI!",
+ "S\326, CERTO. COME IN POLTERGEIST.",
// 25
"",
"",
- "Torno in quindici minuti",
- "Vietato affigere manifesti",
- "",
+ "TORNO TRA QUINDICI MINUTI.",
+ "VIETATO AFFIGGERE MANIFESTI.",
+ "\324 LA TOMBA DELLO ZIO EVARISTO.",
// 30
- "\220 chiuso con la chiave",
- "Ne ho gi\240 uno.",
- "",
- "Non risponde.",
- "No, \202 ben parcheggiato.",
+ "\324 CHIUSA A CHIAVE",
+ "NE HO GI\267 UNO.",
+ "YOO HOO, ZIO EVARISTO!",
+ "NON RISPONDE.",
+ "NO, \324 FISSATO PER BENE.",
// 35
- "\220 una porta.",
- "Un casseto del tavolino.",
- "Un sospettoso armadio.",
- "Ciao armadio. Come va?.",
+ "\324 UNA PORTA.",
+ "UN CASSETTO DEL TAVOLO.",
+ "UN ARMADIO SOSPETTO.",
+ "CIAO ARMADIO. COME VA?",
"",
// 40
"",
- "\220 un candelabro molto vecchio.",
- "Deve essere qu\241 da che Mazinguer-Z era una vite.",
- "No.\220 una reliquia.",
- "\220 una bella pala.",
+ "\324 UN CANDELABRO MOLTO ANTICO.",
+ "DEV'ESSERE QUI DA QUANDO MAZINGA Z ERA UNA VITE.",
+ "NO, \324 UNA RELIQUIA.",
+ "\324 UNA GRAZIOSA PALA D'ALTARE.",
// 45
"",
- "Hi, hi, hi",
+ "HI, HI, HI.",
"",
- "No.",
+ "NO.",
"",
// 50
- "Ha,ha,ha . - che buono!",
+ "HA, HA, HA. FANTASTICO!",
"",
"",
"",
- "Non vedo niente di speciale.",
+ "NON VEDO NIENTE DI SPECIALE.",
// 55
- "Ferdinan, la pianta.",
- "\220 una degli spunzoni della cancellata.",
- "-Eh! Qu\241 sotto c'\202 una scatola di cerini",
- "-Guarda! un pacco di fazzoletti. -E c'\202 ne uno senza utilizzare!.",
- "Non c'\202 niente di pi\243 nel secchio.",
+ "\324 FERNAN, LA PIANTA.",
+ "\324 UNO DEI PALETTI DELLA STACCIONATA.",
+ "HEY! C'\324 UN PACCHETTO DI FIAMMIFERI QUI SOTTO.",
+ "MA GUARDA! UN PACCHETTO DI FAZZOLETTI. CE N'\324 ANCORA UNO NON USATO!",
+ "NON C'\324 ALTRO NEL CESTINO.",
// 60
- "\220 un cieco che non vede",
+ "\324 UN CIECO CHE NON VEDE.",
"",
"",
"",
"",
// 65
- "\220 una abbondante quantit\240 di soldi",
+ "\324 UNA BELLA SOMMA DI DENARO.",
"",
"",
"",
@@ -3175,487 +3423,487 @@ const char *_text[NUM_LANGS][NUM_TEXT] = {
"",
"",
// 100
- "NON HA NULLA DI SPECIALE",
- "NON \324 MICA SPECIALE",
- "TU! CHE C'\324 ?",
+ "NON HA NULLA DI SPECIALE.",
+ "NON \324 NIENTE DI INSOLITO.",
+ "COME TE LA PASSI?",
"CIAO",
- "NIENTE NUOVO?",
+ "NIENTE DI NUOVO?",
// 105
- "-COME VA LA FAMIGLIA?",
- "- MA CHE STAI A DIRE?",
- "-MA COME VADO A PRENDERE QUELLA COSA!",
- "\324 VIETATO DALLA MIA RELIGIONE",
- "MEGLIO DI NO",
+ "COME VA LA FAMIGLIA?",
+ "DICI SUL SERIO?",
+ "MA COME FACCIO A PRENDERLO?",
+ "LA MIA RELIGIONE ME LO PROIBISCE.",
+ "MEGLIO DI NO.",
// 110
- "-COME NO!",
- "NEANCHE PARLARNE",
+ "SICURO!",
+ "NEANCHE A PARLARNE.",
"IMPOSSIBILE",
"QUESTO NON SI APRE",
- "IO SOLO NON CE LA FACCIO",
+ "NON CE LA FACCIO DA SOLO",
// 115
- "SE VORREI POTREI, MA MI FA PIGRIZIA",
- "NON TROVO UNA BUONA RAGIONE",
- "\324 UN CERVELLO ABBASTANZA CARINO",
- "ALLORA, CERVELLO, CHE NE PENSI DI FARE STASERA?",
- "NO, DEVE CONSERVARSI IN UN POSTO CHIUSO ALLA AZIONE MUTANTE DELLA ATMOSFERA",
+ "POTREI FARLO, MA MI SENTO UN PO' PIGRO.",
+ "NON NE VEDO IL MOTIVO.",
+ "\324 UN CERVELLO PIUTTOSTO CARINO.",
+ "E ALLORA, CERVELLO, CHE PENSI DI FARE STANOTTE?",
+ "NO, DEVE ESSERE CONSERVATO IN UN POSTO LONTANO DALL'AZIONE MUTAGENA DELL'ATMOSFERA",
// 120
- "\324 COS\336 DURO, COME IL MIO CAPO",
- "UNA TALEA MOLTO AFFILATA",
- "FEDELE TALEA AFFILATAAA, NOBILE ROVERE TRANSILVANOOO",
- "-INSOMMA, DEVO TAGLIARMI LE UNGHIE!",
- "-LA, DENTRO, C'\324 B.J,E MAMMA MIA, CHE FIGA!",
+ "\324 RIGIDO, COME IL MIO CAPO",
+ "UN PICCHETTO MOLTO AFFILATO.",
+ "FEDELE PICCHETTO APPUNTITOOO, NOBILE ROVERE TRANSILVANOOO",
+ "ACCIDENTI, MI DEVO TAGLIARE LE UNGHIE!",
+ "L\326 DENTRO C'\324 B.J., DOVREI VEDERE COME STA LA RAGAZZA!",
// 125
- "\324 CHIUSA SOTTO LUCCHETTO E CATENACCIO",
- "\"LUCCHETTO E CATENACCIO S.A\"",
- "\324 IL TIPICO SCHELETRO CHE C'\324 IN TUTTE LE CARCERE DI TUTTI I VIDEO-GIOCHI",
- "SI UTILIZA PER DARE ELETRICIT\267 AGLI APARATTI COLLEGATI A LUI",
- "\324 TOTALMEN11TE ARTIGIANO, PERCHE I GIAPONESSI LI FANNO TASCABILI",
+ "\324 CHIUSA CON LUCCHETTO E CATENACCIO",
+ "\"LUCCHETTO E CATENACCIO S.P.A.\"",
+ "\324 IL TIPICO SCHELETRO CHE C'\324 IN TUTTE LE CARCERI DI TUTTI I VIDEOGIOCHI",
+ "SI USA PER FORNIRE ELETTRICIT\267 AGLI APPARECCHI COLLEGATI",
+ "\324 COMPLETAMENTE ARTIGIANALE, VISTO CHE I GIAPPONESI LI FANNO TASCABILI",
// 130
- "NELLA MIA VITA, HO VISTO SOLTANTO UNA VOLTA UNA COSA COS\336 BRUTTA",
- "SMETILLA. NON DICO NULLA PER SE SI ARRABBIA",
+ "SOLO UNA VOLTA NELLA MIA VITA HO VISTO UNA COSA COS\326 BRUTTA",
+ "LASCIA STARE. NON GLI DICO NULLA ALTRIMENTI SI ARRABBIA",
"SEMBRA ABBASTANZA RAZIONALE",
- "\324 UNA FOTO DI PLATONE SCRIVENDO IL SUO DISCORSO PERSO",
- "NON SONO DI QUELLI CHE PARLANO CON POSTERS",
+ "\324 UNA FOTO DI PLATONE MENTRE SCRIVE IL SUO DIALOGO PERDUTO",
+ "NON SONO UNO DI QUELLI CHE PARLANO CON I POSTER",
// 135
"UNA SCRIVANIA MOLTO CARINA",
- "\324 UN DIPLOMA DI CACCIA-CACCIA-VAMPIRI OMOLOGATO DALLA UNIVERSIT\267 DI OXFORD",
- "\324 NOTTE BUIA CON LUNA PIENA",
- "SEMBRA CHE QUESTE VITI NON SONO MOLTO AVVITATE",
- "NON GUARDARE, MA CREDO CHE UNA TELECAMERA NASCOSTA MI ST\267 REGISTRANDO",
+ "\324 UN DIPLOMA DI CACCIA-CACCIA-VAMPIRI APPROVATO DALL'UNIVERSIT\267 DI OXFORD",
+ "\324 UNA NOTTE BUIA CON LUNA PIENA",
+ "SEMBRA CHE QUESTE VITI NON SIANO AVVITATE DEL TUTTO",
+ "NON GUARDARE, MA CREDO CHE UNA TELECAMERA NASCOSTA MI STIA REGISTRANDO",
// 140
- "UN DETETTORE DI TALEE MOLTO MODERNO",
- "NO, IL LABORATORIO SI TROVA NEL SECONDO PIANO",
- "UN BEL TAVOLINO",
- "\324 UN SACCO DI SOLDI CHE NON PUO MANCARE IN UNA AVVENTURA CHE SIA COS\336 IMPORTANTE",
- "IF I WERE A RICHMAN, DUBIDUBIDUBIDUBIDUBIDUBIDUBIDU",
+ "UN RILEVATORE DI PALETTI MOLTO MODERNO",
+ "NO, IL LABORATORIO SI TROVA AL SECONDO PIANO",
+ "UN BEL COMODINO",
+ "\324 UN MUCCHIO DI DENARO CHE NON PU\343 MANCARE IN NESSUNA AVVENTURA CHE SI RISPETTI",
+ "SE FOSSI RICCO, DUBIDUBIDUBIDUBIDUBIDUBIDUBIDU",
// 145
- "SONO DELLE STRANE FOGLIE. DEVONO AVERLE PORTATE DALLA SUDAMERICA",
- "NON CREDO CHE SIA RISPOSTO",
- "\324 UN BEL CROCIFISSO DI LEGNO. LA ICONA NON RIFLESSA TUTTA LA SUA BELLEZA",
- "IO SOLO PREGO PRIMA DI ANDARMENE AL LETTO",
- "-EH, SEMBRA CHE QUESTO SPUNZONE \324 UN PO ALLENTATO!",
+ "SONO DELLE STRANE FOGLIE. DEVONO AVERLE PORTATE DAL SUDAMERICA O GI\353 DI L\326",
+ "NON CREDO CHE MI RISPONDEREBBERO",
+ "\324 UN MERAVIGLIOSO CROCIFISSO DI LEGNO. L'ICONA NON RIFLETTE TUTTA LA SUA BELLEZZA",
+ "IO PREGO SOLAMENTE PRIMA DI CORICARMI",
+ "EH, PARE CHE QUESTA SBARRA SIA UN PO' ALLENTATA!",
// 150
- "E POI TI LAMENTI PERCHE NON TI DO SUGGERIMENTI",
- "\324 UNO SPUNZONI ABBASTANZA CONVENZIONALE",
- "SONO CARINI, SEBBENE HANNO PARECHIO POLVERE",
- "NO, NON MI SENTIRANO; HI,HI,HI -CHE BUONO!",
- "\"LA BELLA ADDORMENTATA DEL BOSCO\" DI CIAIKOSKY, O CIOIFRUSKY, O COME SI DICA",
+ "E POI TI LAMENTI PERCH\220 NON TI DO SUGGERIMENTI",
+ "\324 UNA SBARRA ABBASTANZA CONVENZIONALE",
+ "SONO CARINI, SEBBENE SIANO RICOPERTI DA UN PO' DI SCHIFEZZE",
+ "NO, NON MI SENTIRANNO. HI,HI,HI CHE BUONO!",
+ "\"LA BELLA ADDORMENTATA NEL BOSCO\" DI CHAIKOSKY, O CHOIFRUSKY, O COME SI DICE",
// 155
"MOLTO APPETITOSA",
- "NO, IO NON SONO DI QUELLI CHE SI METTONO IN BOCCA GOMME USATE",
- "UNA FALCE MOLTO CARINA. MI DOMANDO DOVE CI SAR\265 IL MARTELLO",
- "\"I FABBRICANTI DI TABACCO AVVERTONO CHE IL TABACCO NUOCE GRAVEMENTE LA SALUTE\"",
- "UNA CANDELA NORMALE, ANZI CON CERA",
+ "NO, NON SONO UNO DI QUELLI CHE SI METTONO IN BOCCA GOMME USATE",
+ "UNA FALCE MOLTO CARINA. MI CHIEDO DOVE SIA IL MARTELLO",
+ "I FABBRICANTI DI TABACCO AVVERTONO CHE LE AUTORIT\267 SANITARIE NUOCCIONO GRAVEMENTE ALLA SALUTE",
+ "UNA CANDELA ASSOLUTAMENTE NORMALE, CON CERA E TUTTO",
// 160
- "MAMMA MIA COME BRILLANO QUESTE DUE BRILLANTI MONETE",
- "MAMMA MIA COME BRILLA QUESTA BRILLANTE MONETA",
- "CON QUESTO SAR\220 IMMUNE AI MORSI DEI VAMPIRI",
- "NO, ANCORA NON \220 IL MOMENTO",
- "C'E UN BIGLIETTO DI DIECIMILA E UN PAIO DI MONETE",
+ "ACCIDENTI COME SONO LUCENTI QUESTE DUE MONETE!",
+ "ACCIDENTI COM'\324 LUCENTE QUESTA MONETA!",
+ "CON QUESTO SAR\343 IMMUNE AL MORSO DEI VAMPIRI",
+ "NO, ANCORA NON \324 IL MOMENTO",
+ "C'E UN BIGLIETTO DA MILLE E UN PAIO DI MONETE",
// 165
- "DICE \"SI PREGA DI NON BUTTARE CIBO AL PIANISTA\"",
- "OMELETTA, 3.000 .PESCI FRITI, 2.000,PATATINE, 2.500",
- "LE MIGLIORI HAMBURGUER A QUESTA PARTE DEL DANUBIO, SOLTANTO PER 4.000",
- "UN BEL TESCHIO, CON UNO SGUARDO MOLTO PENETRANTE. HI,HI,HI, CHE BUONO!",
- "CIAO TESCHIO, MI RICORDI AL ZIO DI HAMLET",
+ "DICE \"SI PREGA DI NON TIRARE CIBO AL PIANISTA\"",
+ "OMELETTE, 200. PESCE FRITTO, 150, PATATINE CON MAIONESE, 225",
+ "I MIGLIORI HAMBURGER DI QUESTA RIVA DEL DANUBIO, SOLTANTO PER 325!",
+ "\324 UN BEL TESCHIO, CON UNO SGUARDO MOLTO PENETRANTE. HI, HI, HI, BUONA QUESTA!",
+ "CIAO TESCHIO, MI RICORDI LO ZIO DI AMLETO",
// 170
- "HO L'ABITUDINE DI NON TOCCARE COSE CHE SIANO STATE VIVE",
- "UN CESTINO",
- "UN TOTOCALCIO PER LA PARTITA DI STASERA",
- "MI DOMANDO CHE CI SAR\265 DIETRO",
- "-EH, QUESTA TENDE NON SI MUOVE!",
+ "HO L'ABITUDINE DI NON TOCCARE COSE CHE SONO STATE VIVE",
+ "\324 UN CESTINO",
+ "\324 UNA SCOMMESSA PER LA PARTITA DI STANOTTE",
+ "MI DOMANDO CHE CI SAR\267 DIETRO",
+ "EH, QUESTA TENDA NON SI MUOVE!",
// 175
- "MADONNA, CHE TETRO \220 QUESTO CASTELLO.",
- "NON CE LA FACCIO, \220 TROPPO LONTANO PER SENTIRMI",
- "UN TIPICO BOSCO TRANSILVANO, CON GLI ALBERI",
- "-MA CHE SCIOCHEZZE DICI, \220 MOLTO BUIO",
- "PASTICCERIA ROSSI. DOLCI E GOMME",
+ "CAVOLI, CHE TETRO QUESTO CASTELLO, EH?",
+ "NON POSSO, \324 TROPPO LONTANO PER SENTIRMI",
+ "\324 UN TIPICO BOSCO TRANSILVANO, CON ALBERI",
+ "CERTO CHE NE SPARI DI SCIOCCHEZZE, CON IL BUIO CHE C'\324!",
+ "NEGOZIO DI DOLCI GARCIA. TORTE E GOMME DA MASTICARE",
// 180
"UNA PORTA MOLTO BELLA",
- "\220 CHIUSA",
- "UN FUSTO COMPLETAMENTE CHIUSO",
+ "\324 CHIUSA",
+ "\324 UN BARILE COMPLETAMENTE SIGILLATO",
"",
- "CHE ANIMALETTI COS\326 BELLI!",
+ "CHE BELLE BESTIOLINE!",
// 185
- "BSSSSSS,BSSSS, GATINO..",
- "NON RISPONDE",
- "LA LUNA \220 UN SATELLITE CHE GIRA INTORNO LA TERRA CON UN PERIODO DI RIVOLUZIONE DI 28 GIORNI",
+ "PSSST, PSSST, GATTINO...",
+ "NON C'\324 RISPOSTA",
+ "LA LUNA \324 UN SATELLITE CHE GIRA INTORNO ALLA TERRA CON UN PERIODO DI RIVOLUZIONE DI 28 GIORNI",
"CIAO, LUNA LUNETTA",
- "\220 TOTALMENTE CHIUSA CON TABELLE",
+ "\324 COMPLETAMENTE SIGILLATA DA DELLE TAVOLE",
// 190
- "IMPOSSIBILE. QUESTO, NON LO APRE N\220 HOUDINI",
- ".EH, SEMBRA CHE L'OMBRA DEL CIPRESSE \220 ALUNGATA",
- "-EOOO, BARISTA",
+ "IMPOSSIBILE. QUESTA NON LA APRE NEANCHE BRACCIO DI FERRO",
+ "EHI, SEMBRA CHE L'OMBRA DEL CIPRESSO SIA ALLUNGATA!",
+ "EHI, BARISTA!",
"VORREI UNA CAMERA",
- "SA DOVE POSSO TROVARE A UNO CHE SI FA CHIAMARE CONDE DRASCULA",
+ "SA DOVE POSSO TROVARE UN CERTO CONTE DRASCULA?",
// 195
- "SI, PER CHE?",
- "COME MAI?",
- "DA.....DAVVERO?",
- "BUONA DOMANDA, GLI RACONTER\220 LA MIA STORIA, SENTA..",
- "SONO SOLTANTO CINQUE MINUTI",
+ "S\326, COSA C'\324?",
+ "AH S\326?",
+ "DA... DAVVERO?",
+ "BELLA DOMANDA. LE RACCONTER\343 LA MIA STORIA. ALLORA...",
+ "SONO SOLO CINQUE MINUTI",
// 200
- "MI CHIAMO JOHN HACKER, E SONO RAPPRESENTANTE DI UNA IMMOBILIARIE BRITANICA",
- "MI HANNO DETTO CHE IL CONDE DRASCULA VUOLE COMPRARE DEI TERRENI A GIBRALTAR, E SONO QU\326 PER NEGOZIARE LA VENDITA",
- "MA CREDO IO CHE DOMANI PRESTO TORNO CON LA MAMMA",
- "BELLA NOTTE, VERO?",
+ "MI CHIAMO JOHN HACKER, E RAPPRESENTO UNA COMPAGNIA IMMOBILIARE BRITANNICA",
+ "SEMBRA CHE IL CONTE DRASCULA VOGLIA COMPRARE DEI TERRENI A GIBILTERRA E MI HANNO MANDATO QUI PER NEGOZIARE LA VENDITA",
+ "MA CREDO CHE DOMATTINA PRESTO TORNER\343 DA MIA MADRE",
+ "BELLA NOTTATA, VERO?",
"NO, NIENTE",
// 205
- "EOOOO, PIANISTA",
- "BELLA NOTTE",
- "ANZI, NON FA FREDDO",
- "ALLORA... TI LASCIO CONTINUARE A SUONARE",
- "VA BENE",
+ "EHI, PIANISTA",
+ "BELLA NOTTATA",
+ "E NON FA NEMMENO FREDDO",
+ "VA BENE, TI LASCIO CONTINUARE A SUONARE",
+ "BENE ALLORA",
// 210
"CIAO CAPO, COME VA?",
"E LA FAMIGLIA?",
- "C'\220 GENTE QU\326, EH?",
- "MEGLIO NON DICO NULLA",
- "SI ST\265 MEGLIO A CASA CHE A NESSUN POSTO... -EH? MA SE LEI NON \220 LA ZIA EMMA. ANZI. SE IO NON HO NESSUNA ZIA EMMA.",
+ "CARINO COME POSTO, EH?",
+ "MEGLIO CHE NON DICA NULLA",
+ "NON C'\324 POSTO PI\353 BELLO DELLA PROPRIA CASA... NON C'\324... EH? MA TU NON SEI LA ZIA EMMA. IN EFFETTI IO NON HO NESSUNA ZIA EMMA!",
// 215
- "SI, IL MIO ANCHE. LEI PUO CHIAMARMI COME GLI PARA, MA SE MI CHIAMA JOHNY, VENGO SUBITO COME I CANI",
- "SI, CHE SPIRITOSO SONO, VERO? MAA.. DOVE MI TROVO?",
- "SI.",
- "MANAGIA..",
- "OH, SI. COME NO",
+ "S\326, ANCHE IL MIO. MI PU\343 CHIAMARE COME PI\353 LE PIACE, MA SE MI CHIAMA JOHNNY, CORRER\343 DA LEI COME UN CAGNOLINO",
+ "S\326, SONO PROPRIO SPIRITOSO, VERO? COMUNQUE, DOVE MI TROVO?",
+ "S\326.",
+ "MANNAGGIA...",
+ "OH, S\326. IMMAGINO DI S\326",
// 220
- "ALLORA GRAZIE MILE PER DARMI IL TUO AIUTO. NON TI DISTURBO PI\351 . SE MI DICI DOV'\220 LA PORTA, PER FAVORE...",
- "PERCHE LA BOTTA HA DOVUTO DAGNARMI IL CERVELLO E NON VEDO UNA MADONNA",
- "NON FA NIENTE. SEMPRE NE PORTO ALTRI IN PI\351 ",
- "-UFFA, CHE FIGA!- NON MI ERA ACCORTO, CERTO, SENZA GLI OCCHIALI",
- "SENTI..",
+ "BEH, GRAZIE PER IL TUO AIUTO. NON TI DISTURBER\343 PI\353 . POTRESTI DIRMI DOV'\324 LA PORTA, PER FAVORE...",
+ "LA BOTTA DEVE AVERMI DANNEGGIATO IL CERVELLO... NON RIESCO A VEDERE UN TUBO...",
+ "BAH, NON IMPORTA. NE PORTO SEMPRE UN PAIO DI RISERVA",
+ "WOW, CHE BELLA RAGAZZA! NON ME NE ERO ACCORTO PRIMA! CERTO, SENZA GLI OCCHIALI!",
+ "SENTI...",
// 225
- "COME MAI...?!",
- "NON TI PREOCUPARE B.J., AMORE MIO! TI LIBERER\220 DA QUEL TIZIO",
- "MI HA FATTO ARRABBIARE",
- ".AHHH, IL LUPO- MANNARO! -MUORE MALDITO!",
- "BENE, CREDO...",
+ "E QUESTOOO?!",
+ "NON TI PREOCCUPARE B.J., AMORE MIO! TI SALVER\343 DALLE SUE GRINFIE",
+ "MI HAI FATTO DAVVERO ARRABBIARE...",
+ "AHHH, UN LUPO MANNARO! MUORI, MALEDETTO!",
+ "S\326, BEH...",
// 230
- "BENE, CREDO CHE PROSSIGUER\220 LA MIA STRADA. PERMESSOO..",
- "-COME?",
- "LA VERIT\267, PENSANDOCI MEGLIO, CREDO DI NO",
- "DIMI, OH ERUDITO FILOSOFO, C'\324 QUALCUNA RELAZIONE CAUSA-EFETTO TRA LA VELOCIT\267 E LA PANCETA?",
- "VA BENE, SMETTILA. COMUNQUE NON SO PERCHE HO DETTO QUESTO",
+ "S\326, BEH... CREDO CHE PROSEGUIR\343 PER LA MIA STRADA. CON PERMESSO...",
+ "COSA?",
+ "PER LA VERIT\267, PENSANDOCI BENE... CREDO DI NO",
+ "DIMMI, O ERUDITO FILOSOFO, ESISTE UNA QUALCHE RELAZIONE CAUSA-EFFETTO TRA LA VELOCIT\267 E LA PANCETTA?",
+ "VA BENE, VA BENE, LASCIA PERDERE. NON SO NEANCHE PERCH\220 L'HO DETTO.",
// 235
- "COSA FAI QU\336 FILOSOFANDO, CHE NON STAI MANGIANDO GENTE?",
+ "PERCH\220 STAI QUI A FILOSOFARE, INVECE DI ANDARE A MANGIARE LE PERSONE?",
"COME MAI?",
- "SENTI, PUOI RIPETERE QUELLO DI \"INCLINAZIONI PRE-EVOLUTIVE\"?",
- "SI SI, QUELLA STORIA CHE MI HAI RACCONTATO PRIMA. PERCHE NON HO CAPITO MOLTO BENE.",
- "NO, MEGLIO NON DICO NULLA, NON VOGLIO METTERE IL COLTELLO NELLA PIAGA...",
+ "SENTI, PUOI RIPETERE QUELLA COSA SULLE RELAZIONI PRE-EVOLUTIVE?",
+ "S\326, AMICO. QUELLA MENATA CHE MI HAI FATTO SENTIRE PRIMA. \324 CHE NON L'HO CAPITA MOLTO BENE...",
+ "NO, MEGLIO NON DIRE NULLA, NON VOGLIO METTERE IL COLTELLO NELLA PIAGA...",
// 240
- "SI, MI DICA?",
- "SI, CHE SUCCEDE?",
- "AH, ADESSO CHE CITA IL SOGGETTO GLI DIR\343 CHE...",
+ "PRONTO?",
+ "S\326, CHE SUCCEDE?",
+ "AH, VISTO CHE NE PARLA, LE DIR\343 CHE...",
"",
- "AH.., COSA SUCCEDEREBBE SE UN VAMPIRO PRENDEREBBE LA RICETA..",
+ "A PROPOSITO, NON CHE SIA QUESTO IL CASO, CERTO, MA COSA ACCADREBBE SE PER CASO UN VAMPIRO OTTENESSE LA RICETTA?",
// 245
- "NIENTE. SENTI, QUESTO SEMBRA UN POSTICCIO MESSO SUL COPIONE PER FINIRE PRESTO IL VIDEO-GIOCO?. BENE, FORSE, NO",
+ "AD OGNI MODO. SENTI, QUESTA NON TI SEMBRA UNA TROVATA MESSA SUL COPIONE PER FINIRE PRESTO IL GIOCO? BEH, FORSE NO",
"\324 VUOTO!",
- "PERCHE HAI RUBATO IL MIO AMORE, B.J., SENZA LEI LA MIA VITA NON HA SENSO",
- "-IL SUO CERVELLO?!",
- "NO NIENTE, MA CREDO CHE ALLA FINE IL TUO PICCOLINO MOSTRO MI HA FATTO ARRABBIARE",
+ "PERCH\220 MI HAI RUBATO IL MIO UNICO AMORE, B.J.? SENZA DI LEI LA MIA VITA NON HA SENSO",
+ "IL SUO CERVELLO?!",
+ "NON PER NIENTE, MA CREDO DI AVERNE ABBASTANZA DEL TUO MOSTRICIATTOLO",
// 250
- "SANTA MADONNA AIUTAMI!",
- "NON TE LA CAVEREI. SICURO CHE APPARISCE SUPERMAN E MI LIBERA!",
- "CHE SCHIFFO DI VIDEO-GIOCO NEL CUI MUORE IL PROTAGONISTA",
- "UN ATTIMO, COSA SUCCEDE COL MIO ULTIMO DESIDERIO?",
- "-HA,HA! ORA SONO IMMUNIZZATO CONTRO TE, MALEDETTO DEMONIO. QUESTA SIGARETTA \324 UNA POZIONE ANTI-VAMPIRI CHE MI HA DATTO VON BRAUN",
+ "SANTA VERGINE, SALVAMI DA ALTRE SFORTUNE!",
+ "NON TE LA CAVERAI. SICURAMENTE APPARIR\267 SUPERMAN E MI SALVER\267!",
+ "CHE SCHIFO DI GIOCO \324 QUESTO, UNO IN CUI MUORE IL PROTAGONISTA!",
+ "EHI, UN MOMENTO, COSA NE \324 DEL MIO ULTIMO DESIDERIO?",
+ "AH, AH! ORA SONO IMMUNIZZATO CONTRO DI TE, MALEDETTO DEMONIO. QUESTA SIGARETTA CONTIENE UNA POZIONE ANTI-VAMPIRO CHE MI HA DATO VON BRAUN",
// 255
- "SI CERTO. MA NON RIUSCIRAI MAI A FARMI DIRTI LA RICETA",
- "POSSO SOPPORTARE LA TORTURA, ANZI CREARLA",
- "-NO, PER FAVORE!- PARLER\220, MA NON FARMI QUESTO!",
- "BENE, TI HO GI\267 DETTO QUELLO CHE VOLEVI SAPERE. ORA LIBERA B.J. E ME, E LASCIACI PERDERE",
- "-B.J-.! COSA FAI QU\336? DOV'\324 DRASCULA?",
+ "S\326, CERTO. MA NON RIUSCIRAI MAI A FARMI DIRE LA RICETTA",
+ "POSSO SOPPORTARE QUALUNQUE TORTURA.",
+ "NO, TI PREGO! PARLER\343, MA NON FARMI QUESTO!",
+ "BENE. TI HO DETTO QUELLO CHE VOLEVI SAPERE. ORA LIBERA B.J. E ME, E LASCIACI IN PACE!",
+ "B.J.! COSA CI FAI QUI? DOV'\324 DRASCULA?",
// 260
- "CHE PERVERSO! SOLTANTO PERCH'\324 NOBILE PENSA CHE HA IL DIRITTO SU TUTTI QUANTI",
- "ABASSO LA ARISTOCRAZIA!",
- "FORZA I POVERI DEL MONDOOO...",
- "E QUELLO CHE VEDO \324 CHE TI HA INCATENATO ANZI CON LUCCHETTO",
- "O.K., NON AVRAI UNA FONCINA?",
+ "CHE SPREGEVOLE! SOLTANTO PERCH\220 APPARTIENE ALLA NOBILT\267 PENSA DI AVERE LO \"IUS PRIMAE NOCTIS\" SU QUALUNQUE RAGAZZA LUI VOGLIA",
+ "ABBASSO IL DISPOTISMO ARISTOCRATICO!",
+ "FORZA I POVERI DEL MONDOOO...!",
+ "A QUANTO VEDO TI HA INCATENATO CON LUCCHETTO E TUTTO, EH?",
+ "VA BENE. NON HAI UNA FORCINA?",
// 265
- "BENE BENE, NON PRENDERTELA COS\336, CI PENSER\220 IO",
- "EH, BARISTA",
+ "VA BENE, VA BENE. NON PRENDERTELA COS\326, MI VERR\267 IN MENTE QUALCOSA.",
+ "EHI, BARISTA!",
"COME VA LA PARTITA?",
"CHI?",
- "MA NON VEDI CHE DRASCULA \324 QU\336?",
+ "MA NON VEDI CHE DRASCULA \324 QUI?",
// 270
- "ANDIAMO A UCCIDERLO",
- "SERVIMI UN DRINK..",
+ "ALLORA LA FINIAMO CON LUI UNA VOLTA PER TUTTE, NO?",
+ "SERVIMI UN DRINK",
"NIENTE. HO DIMENTICATO COSA VOLEVO DIRTI",
- "O\247MI\247SERVI\247UN\247DRINK\247O\247MI\247METTO\247A\247SUONARE\247IL\247PIANOFORTE",
- "QUANTO MANCA PER LA FINE DELLA PARTITA?",
+ "O MI SERVI UN DRINK O MI METTO A SUONARE IL PIANOFORTE FINO ALLA FINE DELLA PARTITA",
+ "QUANTO MANCA ALLA FINE DELLA PARTITA?",
// 275
"BUONA SERA",
- "COME VA IGOR? VAI CON LA GOBBA? -HI,HI,HI,CHE BUONO!",
- "CHE STAI FACENDO?",
- "NO",
+ "E COME TI SENTI, IGOR? UN PO' INGOBBITO? AH, AH, AH, CHE SPASSO!",
+ "COSA STAI FACENDO?",
+ "BEH, NO",
"ALLORA METTITI GLI OCCHIALI",
// 280
- "COSA \324 QUELLA DELLA ORGIA SOPRANNATURALE?",
- "VA BENE, NON COTINUARE, MI FACCIO IDEA",
- "NON POTREI DIRMI DOV'\324 DRASCULA?",
- "DAIII, PER FAVORE",
- "PER CHE NO?",
+ "COS'\324 QUESTA STORIA DELL'ORGIA SOPRANNATURALE?",
+ "OK, OK, NON CONTINUARE, ME NE SONO FATTO UN'IDEA",
+ "NON POTRESTI DIRMI DOV'\324 DRASCULA?",
+ "DAAAI, PER FAVORE...!",
+ "PERCH\220 NO?",
// 285
"AH, MA DORME DI NOTTE?",
- "BENE, ALLORA IN BOCCA IL LUPO CON I REDDITI",
- "DEVO PROPRIO PARLARE CON LUI",
- "EOOOO, SCHELETROOO!",
- "OH DIO! UN MORTO CHE PARLA!",
+ "BENE, ALLORA IN BOCCA AL LUPO CON I REDDITI",
+ "DEVO PARLARE CON LUI",
+ "EHI, SCHELETROOO!",
+ "SANTO CIELO! UN MORTO CHE PARLA!",
// 290
- "RACCONTAMI. COME MAI SEI VENUTO QU\336?",
- "E PER CHE DRASCULA VUOLE CREARE UN MOSTRO?",
+ "RACCONTAMI. COME SEI FINITO QUI?",
+ "E PERCH\220 DRASCULA VUOLE CREARE UN MOSTRO?",
"COME TI CHIAMI, AMICO SCHELETRO?",
- "SENTI, NON VUOI QUALCOSA DA MANGIARE?",
- "DEVI AVERE LO STOMACO VUOTO .- HI,HI,HI!",
+ "SENTI, NON VUOI CHE TI PORTI QUALCOSA DA MANGIARE?",
+ "DEVI AVERE LO STOMACO VUOTO. AH, AH, AH!",
// 295
- "LA VERIT\267 \324 CHE NON MI VA DI PARLARE ADESSO",
- "VANFFAN ( BIP ) FIGLIO DI .......( BIIP ).. VAI A FARE....( BIIIP )",
- "IO LA AMAVO DAVVERO. O.K., SONO D'ACCCORDO CHE NON ERA MOLTO INTELLIGENTE, MA NESSUNO \324 PERFETTO, NO?",
- "ANZI, AVEVA UN CORPO DA PAURA",
- "ORMAI NON SAR\343 PI\353 QUELLO DI PRIMA .MI RICHIUDER\343 IN UN MONASTERO, E LASCIER\343 LA MIA VITA PERDERE",
+ "ADESSO NON MI VA DI PARLARE",
+ "CHE FIGLIA DI ...(BIP). VADA A FARSI F...(BIP) QUELLA STR...(BIP)!",
+ "IO LA AMAVO DAVVERO. VA BENE, NON ERA PROPRIO UN'INTELLETTUALE, MA NESSUNO \324 PERFETTO, NO?",
+ "E POI, AVEVA UN CORPO MOZZAFIATO",
+ "NON SAR\343 MAI PI\353 QUELLO DI PRIMA. MI RINCHIUDER\343 IN UN MONASTERO E LASCER\343 SCORRERE VIA LA MIA VITA A POCO A POCO",
// 300
- "NIENTE POTR\267 FARMI USCIRE DI QUESTA MISERIA PERCHE...",
+ "NIENTE POTR\267 TIRARMI FUORI DA QUESTA MISERIA PERCH\220...",
"DI CHI? DI CHI?",
- "VOGLIO ESSERE PIRATA",
- "VOGLIO ESSERE PROGRAMMATORE",
+ "VOGLIO ESSERE UN PIRATA",
+ "VOGLIO ESSERE UN PROGRAMMATORE",
"RACCONTAMI QUALCOSA SU GARIBALDI",
// 305
- "CONTINUER\343 A GIOCARE E DIMENTICHER\343 CHE VI HO VISTI",
- "MA CHI AVR\267 PENSATO QUESTA SCIOCHEZZA!",
- "\324 UNA BORSA COME QUELLA DI MIA NONNA",
- "MA CHE FIGO SONO!",
- "PI\353 MI VEDO PI\353 MI PIACCIO",
+ "CONTINUER\343 A GIOCARE E DIMENTICHER\343 DI AVERVI VISTO",
+ "A CHI SAR\267 VENUTA IN MENTE QUESTA IDIOZIA?",
+ "\324 UNA BORSETTA COME QUELLA DI MIA NONNA",
+ "PER\343, CHE FIGO CHE SONO!",
+ "PI\353 MI VEDO, PI\353 MI PIACCIO",
// 310
"E POI COME MI CHIUDO?",
- "PRIMA DEVO APRIRMI, VERO?",
- "ST\343 BENE DOVE SONO",
- "MI HO GI\267 PRESSO",
- "CIAO IO",
+ "PRIMA DOVR\343 APRIRMI, NO?",
+ "STO BENE DOVE SONO",
+ "MI SONO GI\267 PRESO",
+ "CIAO ME!",
// 315
- "ME GLI INDOSSER\343 QUANDO SIA LA OCCASIONE OPORTUNA",
- "NON VEDO NIENTE DI SPECIALE",
- "\324 BENE DOV'\324",
- "E PER CHE?",
- "NON CE LA FACCIO",
+ "LI INDOSSER\343 QUANDO SAR\267 IL MOMENTO GIUSTO",
+ "NON CI VEDO NIENTE DI SPECIALE",
+ "STA BENE DOV'\324",
+ "E PERCH\220?",
+ "NON POSSO",
// 320
- "CIAO TU",
- "\324 IL SEPOLCRO DELLO ZIO PEPPINO",
- "EOOOO, ZIO PEPPINOOOO!",
- "NO.NON VOGLIO TAGLIARMI UN' ALTRA VOLTA",
- "-EHEM,EHEM..!",
+ "CIAO A TE",
+ "\324 IL SEPOLCRO DELLO ZIO DESIDERIO",
+ "EHI, ZIO DESIDERIOOOO!",
+ "NO. NON VOGLIO TAGLIARMI UN'ALTRA VOLTA",
+ "EHEM, EHM...!",
// 325
- "GNAMM, EMMM,!",
- "-SI, COF, COF!",
- "GUARDA, C'\324 UNA GOMMA QU\336 ATTACATA",
+ "GNAMM, AH!",
+ "S\326, COF, COF!",
+ "GUARDA, C'\324 UNA GOMMA ATTACCATA QUI",
"\324 IL TELEFONINO CHE MI HANNO REGALATO A NATALE",
- "COM'\324 ALTO",
+ "COM'\324 ALTO!",
// 330
- "ESCI AL BALCONE GIULIETTA!",
- "TU SEI LA LUCE CHE ILLUMINA LA MIA VITA!",
- "EH, PORTA, CHE C'\324?",
- "EOOOO, SPENDITRICE DI TABACCO DI TRANSILVANIAAA",
- "\324 UNA SPENDITRICE DI TABACCO",
+ "ESCI SUL BALCONE, GIULIETTA!",
+ "TU SEI LA LUCE CHE ILLUMINA LA MIA STRADA!",
+ "EHI, PORTA, DOVE PORTI?",
+ "EHI, DISTRIBUTORE DI SIGARETTE DI TRANSILVANIA!",
+ "\324 UN DISTRIBUTORE DI SIGARETTE",
// 335
"HO UN'ALTRA MONETA DENTRO",
- "NO. HO DECISSO SMETTERE DI FUMARE E DI BERE",
- "DA OGGI SAR\343 SOLTANTO PER LE DONNE",
- "QUESTO \324 UNA TRUFFA! NON \324 USCITO NULLA",
- "ALLA FINE!",
+ "NO. HO DECISO DI SMETTERE DI FUMARE E DI BERE",
+ "A PARTIRE DA ADESSO MI DEDICHER\343 SOLAMENTE ALLE DONNE",
+ "QUESTA \324 UNA TRUFFA! NON \324 USCITO NULLA!",
+ "FINALMENTE!",
// 340
- "CHE TI HO DETTO?, UN BAULE",
- "CIAO BAULE, TI CHIAMI COME MIO CUGINO CHE SI CHIAMA RAUL..E",
- "HO TROVATO LA BORSA DI B.J.",
- "MIO DIO, NON MI RIFLETTO, SONO UN VAMPIRO!",
- "...AH, NO, \324 UN DISEGNO",
+ "CHE TI HO DETTO? UN BAULE",
+ "CIAO BAULE, TI CHIAMI QUASI COME MIO CUGINO... RAULE.",
+ "HO TROVATO LA BORSA DI B.J.!",
+ "MIO DIO, NON HO UN RIFLESSO, SONO UN VAMPIRO!",
+ "...AH, NO. \324 UN DISEGNO!",
// 345
- "SPECCHIO DELLE MIE BRAME: CHI \220 ILPI\351 BELLO DEL REAME?",
+ "SPECCHIO, SPECCHIO DELLE MIE BRAME: CHI \324 IL PI\353 BELLO DEL REAME?",
"NON VUOLE APRIRMI",
- "MOLTO BENE. MI HO MESSO I TAPPI",
- "\324 UN DIPLOMA DI CACCIA-VAMPIRI OMOLOGATO DALLA UNVERSIT\267 DI CAMBRIDGE",
- "NO. MANCANO ANCORA GLI INGREDIENTI, NON MERITA LA PENA CHE SIA SVEGLIATO",
+ "MOLTO BENE. HO MESSO I TAPPI",
+ "\324 UN DIPLOMA DI CACCIA-VAMPIRI APPROVATO DALL'UNIVERSIT\267 DI CAMBRIDGE",
+ "NO, MANCANO ANCORA ALCUNI INGREDIENTI, NON VALE LA PENA SVEGLIARLO",
// 350
- "NON HO SOLDI",
- "\324 UNA LAMPADA BRITANICA",
+ "MA NON HO SOLDI",
+ "\324 UNA LAMPADA BRITANNICA",
"BARISTA! AIUTAMI!",
- "HA COMPARITO UN VAMPIRO ED HA PRESSO LA MIA FIDANZATA",
- "MA NON MI AIUTER\267",
+ "\324 COMPARSO UN VAMPIRO ED HA PRESO LA MIA FIDANZATA!!",
+ "MA NON MI AIUTERAI?!",
// 355
- "MORTA? CHE VUOLE DIRE?",
- "- EHEM!",
- "UN VAMPIRO HA SEQUESTRATO LA RAGAZZA DELLA 506!",
- "DEVI AIUTARMI!",
- "NON SAI SUONARE NESSUNA DI \"ELIO E LE STORIE TESSE\"",
+ "MORTA? COSA INTENDI DIRE?",
+ "EHEM!",
+ "UN VAMPIRO HA RAPITO LA RAGAZZA DELLA 506!",
+ "MA MI DEVI AIUTARE!",
+ "NE SAI SUONARE QUALCUNA DI ELIO E LE STORIE TESE?",
// 360
- "COME TI SOPPORTI, SUONANDO SEMPRE LO STESSO?",
- "ALLORA COME MI SENTI?",
- "PRESTAMI I TAPPI",
+ "COME FAI A RESISTERE SUONANDO SEMPRE LO STESSO PEZZO TUTTO IL GIORNO?",
+ "E ALLORA COME FAI A SENTIRMI?",
+ "PRESTAMI I TAPPI PER LE ORECCHIE",
"DAI, TE LI RESTITUISCO SUBITO",
"DAIIII...",
// 365
- "CIAO. DEVO UCCIDERE UN VAMPIRO",
+ "BEH, CIAO. HO UN VAMPIRO DA UCCIDERE",
"",
- "COSA DICI? IN TRANSILVANO?",
- "CHI \324 LO ZIO PEPPINO?",
- "MA CHE SUCCEDE CON DRASCULA?",
+ "MA COME PARLI? IN TRANSILVANO?",
+ "CHI \324 LO ZIO DESIDERIO?",
+ "MA COSA \324 SUCCESSO CON DRASCULA?",
// 370
- "CHI \324 VON BRAUN?",
- "E PER CHE NON LO FA?",
+ "CHI \324 QUESTO VON BRAUN?",
+ "E PERCH\220 NON LO FA?",
"E DOVE POSSO TROVARE VON BRAUN?",
- "GRAZIE E CIAO, SOGNI D'ORO",
- "SAR\267 MEGLIO BUSSARE PRIMA",
+ "GRAZIE E CIAO, DORMI BENE",
+ "SAR\267 MEGLIO SUONARE PRIMA",
// 375
- "\324 LEI IL PROFESSORE VON BRAUN?",
- "E MI POTREBBE DIRE DOVE POSSO ...?",
- "NON CREDO SIA IL NANNO GANIMEDI",
- "-PROFESSORE!",
- "AIUTAMI! LA VITA DEL MIO AMORE DIPENDE DI LEI!",
+ "\324 LEI IL PROFESSOR VON BRAUN?",
+ "E MI POTREBBE DIRE DOVE POSSO...?",
+ "NON CREDO SIA IL NANO GANIMEDE",
+ "PROFESSORE!",
+ "MI AIUTI, LA PREGO! LA VITA DELLA MIA AMATA DIPENDE DA LEI!",
// 380
- "VA BENE, NON HO BISOGNO DEL SUO AIUTO",
- "O.K. ME NE VADO",
- "NON AVERE PAURA. INSIEME VINCEREMO DRASCULA",
- "ALLORA PER CHE NON MI AIUTA?",
- "IO CE LE HO",
+ "E VA BENE, NON HO BISOGNO DEL SUO AIUTO",
+ "D'ACCORDO. ME NE VADO",
+ "NON ABBIA PAURA. INSIEME SCONFIGGEREMO DRASCULA",
+ "ALLORA PERCH\220 NON MI AIUTA?",
+ "IO LE HO",
// 385
- "SI CE LE HO",
+ "ECCOME SE LE HO!",
"D'ACCORDO",
- "...EHH...SI",
- "VENGO A RIENTRARE A QUESTA CABINA",
- "SONO PRONTO PER FARE LA PROVA",
+ "...EHH ...S\326",
+ "SONO VENUTO PER ENTRARE DI NUOVO IN QUELLA CABINA",
+ "SONO PRONTO PER AFFRONTARE LA PROVA",
// 390
- "VA BENE, VECCHIETO. SONO VENUTO PER IL MIO SOLDI",
- "NO, NIENTE. ME NE GI\267 ANDAVO",
+ "E VA BENE, VECCHIETTO. SONO VENUTO PER I MIEI SOLDI",
+ "NO, NIENTE. ME NE STAVO ANDANDO",
"SCUSA",
- "TI \324 INTERESANTE QUESTO LIBRO? HA PARTITURE DI TCIAKOWSKY",
+ "TI INTERESSA QUESTO LIBRO? HA LE PARTITURE DI TCHAIKOWSKY",
"COME POSSO UCCIDERE UN VAMPIRO?",
// 395
- "NON TI HANNO DETTO CHE NON \324 BUONO DORMIRE IN CATTIVA POSIZIONE?",
- "\324 QUELLO CHE SEMPRE DICE MIA MADRE",
- "PER CHE DRASCULA NON FU RIUSCITO A UCCIDERTI?",
- "E COSA FU?",
- "BENISSIMO! HA LEI LA POZIONE DI IMMUNIT\267...!",
+ "NON TI HANNO DETTO CHE DORMIRE IN UNA BRUTTA POSIZIONE NON \324 SALUTARE?",
+ "\324 QUELLO CHE MI DICEVA SEMPRE MIA MADRE",
+ "PERCH\220 DRASCULA NON RIUSC\326 AD UCCIDERTI?",
+ "E COSA NE FU?",
+ "FANTASTICO! LEI HA LA POZIONE DELL'IMMUNIT\267...!",
// 400
- "ALLORA",
+ "E ALLORA?",
"MOLTO BENE",
- "MI PUO RIPETERE COSA BISOGNO PER QUELLA POZIONE?",
- "VADO VIA VELOCE A TROVARLO",
- "SENTA, COSA \324 SUCCESO CON IL PIANISTA?",
+ "MI PU\343 RIPETERE DI COSA HO BISOGNO PER QUELLA POZIONE?",
+ "OK, CORRO A TROVARLO",
+ "SENTA, COSA \324 SUCCESSO CON IL PIANISTA?",
// 405
"HO GI\267 TUTTI GLI INGREDIENTI DI QUESTA POZIONE",
- "UNA DOMANDA: COSA \324 QUELLA DI ALUCSARD ETEREUM?",
- "DICA, DICA..",
+ "SOLO UNA DOMANDA: COS'\324 QUELLA SCRITTA ALUCSARD ETEREUM?",
+ "DICA, DICA... ",
"E DOV'\324 QUELLA GROTTA?",
- "CHE C'\324? NON AVETE TRIBUNALE?",
+ "CHE C'\324? NON AVEVATE UN TRIBUNALE?",
// 410
- "...MA ...E SE TROVO PI\353 VAMPIRI?",
+ "...MA ...E SE TROVO ALTRI VAMPIRI?",
"\324 UN VAMPIRO CHE NON MI FA PASSARE",
- "SI ASSOMIGLIA A YODA, MA PI\353 ALTO",
- "EH, YODA. SE MI FAI PASSARE TI DAR\343 CENTO LIRE",
- "BENE, O.K., NON POSSO DIRTI NULLA",
+ "ASSOMIGLIA A YODA, MA UN PO' PI\353 ALTO",
+ "EHI, YODA. SE MI FAI PASSARE TI DAR\343 UN PENNY",
+ "OK, CALMA, CERTO CHE CON TE NON SI PU\343 PROPRIO PARLARE",
// 415
+ "TI HANNO MAI DETTO CHE ASSOMIGLI A YODA?",
"CIAO VAMPIRO, BELLA NOTTE, VERO?",
- "TI HANNO DETTO QUALCHE VOLTA CHE TI ASSOMIGLII A YODA?",
- "SEI UN VAMPIRO O UN DIPINTO ALL'OLEO?",
- "MEGLIO NON DIRTI NIENTE, PERCHE POI TI ARRABBII",
- "\324 CHIUSA CON LA CHIAVE",
+ "SEI UN VAMPIRO O UN DIPINTO A OLIO?",
+ "MEGLIO NON DIRE NIENTE, ALTRIMENTI POI TI ARRABBI",
+ "\324 CHIUSA A CHIAVE",
// 420
- "SE PROVO, LA GAZZA MI POTREI CAVARE UN OCCHIO",
+ "SE CI PROVO LA GAZZA POTREBBE CAVARMI UN OCCHIO!",
"\324 CHIUSA! DIO MIO, CHE PAURA!",
- "LE CERNIERE SONO OSSIDATE",
- "LA DENTRO C'\324 SOLTANTO UN BARATOLO DI FARINA",
- "QUESTO HA TOLTO L'OSSIDO",
+ "I CARDINI SONO ARRUGGINITI",
+ "QUI DENTRO C'\324 SOLTANTO UN CESTO DI FARINA",
+ "QUESTO HA TOLTO LA RUGGINE",
// 425
- "HO TROVATO UNA TALEA DI LEGNO DI PINO",
- "PRENDER\343 QUESTO CH'\220 PI\353 GROSSO",
- "BENE, CREDO DI POTERE TOGLIERMI QUESTO STUPIDO COSTUME",
- "\"CORRIDOIO AI TORRIONI CHIUSO PER LAVORI IN CORSO. PER FAVORE, PER LA PORTA PRINCIPALE. SCUSATE PER IL DISTURBO\"",
- "..\324 PALLIDO, HA DENTI CANINI, HA CIUFFO E UTILIZA MANTELLO...- SICURO CH'\324 DRASCULA!",
+ "HO TROVATO UN PALETTO DI LEGNO DI PINO",
+ "PRENDER\343 QUESTO QUI PI\353 GROSSO",
+ "BENE, CREDO DI POTERMI TOGLIERE QUESTO STUPIDO COSTUME",
+ "\"CORRIDOIO AI TORRIONI CHIUSO PER LAVORI IN CORSO. USATE LA PORTA PRINCIPALE. SCUSATE IL DISTURBO\"",
+ "...\324 PALLIDO, HA I CANINI IN FUORI, PORTA IL TOUPET E INDOSSA IL MANTELLO... \324 SICURAMENTE DRASCULA!",
// 430
- "B.J., B.J., STAI BENE?",
- "SI, SO CH'\324 SCEMA MA MI SENTO SOLISSIMO",
- "NON AVRAI UNA CHIAVE PER CASO, VERO?",
- "- E SICURO CHE NON HAI UN GRIMALDELLO?",
- "DAMI UNA FONCINA. VADO A FARE COME MCGYVER",
+ "\324 B.J.! STAI BENE, B.J.?",
+ "S\326, LO SO CHE \324 TONTA, MA SONO COS\326 SOLO",
+ "NON \324 CHE HAI UNA CHIAVE, EH?",
+ "E SCOMMETTO CHE NON HAI NEANCHE UN GRIMALDELLO...",
+ "DAMMI UNA FORCINA. GIOCHER\343 A FARE MCGYVER!",
// 435
"NON MUOVERTI, TORNO SUBITO",
- "- MANAGIA!- SI \324 ROTTA!",
- "OLE, ANCHE MI HO FATTO LA BARBA!",
- "SI, CARO?",
- "NON ARRIVA",
+ "MANNAGGIA! SI \324 ROTTA!",
+ "OLEEEE! MI SONO FATTO PERSINO LA BARBA!",
+ "S\326, TESORO?",
+ "NON \324 ANCORA ARRIVATO",
// 440
- "IL PIANISTA NON C'\324",
+ "IL PIANISTA NON \324 QUI",
"UN DRINK TRANSILVANO",
- "ANCORA NON HO CAMERA",
- "SEMBRA CHE FU RISUCCHIATO NELLO SCARICO DELLA VASCA E HA DECISO APRIRE UN BAR",
- "\324 UBRIACO PERSO",
+ "NON HO ANCORA UNA CAMERA",
+ "SEMBRA CHE SIA RIMASTO INCASTRATO NELLA VASCA DA BAGNO E ABBIA DECISO DI APRIRE UN BAR",
+ "\324 UBRIACO FRADICIO",
// 445
- "QUESTI CAPELLI.... CREDO CHE MI FANNO RICORDARE A QUALCUNO",
+ "QUESTO CAPELLO... MI RICORDA QUALCUNO",
"\324 UNO SCHELETRO OSSUTO",
- "GUARDA! MIGUEL BOSE!",
- "\324 ADDORMENTATO. SAREBBE UN PECCATO SVEGLIARGLI",
- "\324 PI\353 BRUTTO CHE BEGNINI",
+ "GUARDA! C'\324 MIGUEL BOSE!",
+ "STA DORMENDO. SAREBBE UN PECCATO SVEGLIARLO",
+ "\324 PI\353 BRUTTO DI EMILIO FEDE",
// 450
- "UN FERETRO DI LEGNO DI PINO",
- "MI TAGLIER\267 A FETTINI, COME UN SALSICCIOTTO",
- "NON MI PIACCIONO I PENDOLI. PREFERISCO LE CARCIOFE",
- "LE MIE MANI SONO LEGATE. NON CE LA FAR\343",
- "\324 OVVIO CH'\324 UNA PORTA SEGRETA",
+ "UNA BARA IN LEGNO DI PINO",
+ "MI TAGLIER\267 A FETTINE, COME UN SALSICCIOTTO",
+ "NON MI PIACCIONO I PENDULI. PREFERISCO GLI ALCACHOFAS",
+ "HO LE MANI LEGATE. NON POSSO FARCELA",
+ "OVVIAMENTE \324 UNA PORTA SEGRETA",
// 455
"MI IGNORANO",
- "-DAIII!",
- "NEL PRIMO COPIONE SI MUOVEVA, MA IL VIDEO-GIOCO \220 USCITO DAL BUDGET E NON HANNO POTUTO PAGARMI UNA PALESTRA E NON SONO GONFFIATO",
- "SEMBRA CH'\324 UN P\343 ALLENTATA DAL MURO",
- "NON CREDO CHE MI SIA UTILE. \324 TROPPO UMIDA PER ACCENDERLA.",
+ "DAIII!",
+ "SECONDO IL COPIONE SI SAREBBE DOVUTO MUOVERE, MA IL BUDGET ERA RISICATO, NON MI HANNO PAGATO LA PALESTRA E COS\326 NON HO POTUTO FARMI I MUSCOLI. FINE DELLA STORIA",
+ "SEMBRA UN PO' STACCATA DALLA PARETE",
+ "NON PENSO CHE MI TORNER\267 UTILE. \324 TROPPO UMIDA PER ACCENDERSI",
// 460
- "AL LATO OVEST? -N\324 PAZZO, CHI SA CHE CI SAR\267 LI!",
- "HA DEI BELLI DISEGNI TRANSILVANI",
+ "ALL'ALA OVEST? \324 DA PAZZI! CHISS\267 COSA POTRESTI TROVARCI!",
+ "HA DELLE OTTIME MOTIVAZIONI TRANSILVANE",
"",
- "CHE PENA CHE NON CI SIA DENTRO UN AGNELLINO ARRROSTANDOSI",
- "LA ULTIMA VOLTA CHE APRII UN FORNO, LA CASA SALT\220 PER ARIA",
+ "PECCATO CHE NON CI SIA UN BELL'AGNELLO ARROSTO, L\326 DENTRO",
+ "L'ULTIMA VOLTA CHE HO APERTO UN FORNO HO FATTO SALTARE IN ARIA LA CASA",
// 465
- "LO SCUDO DELLA SCUADRA DI CALCIO DI TRANSILVANIA",
- "E PER CHE? PER INDOSARLA SULLA TESTA?",
- "NON CREDO CHE I CASSETI SIANO DI QUELLI CHE SI APPRONO",
- "NON VOGLIO SAPERE IL CIBO CHE CI SAR\267 LA DENTRO!",
- "HO L'IMPRESSIONE CH'\324 IMPRESSIONISTA",
+ "LO STEMMA DELLA SQUADRA DI CALCIO TRANSILVANA",
+ "E PERCH\220? PER METTERMELA SULLA TESTA?",
+ "NON CREDO CHE QUESTI CASSETTI SIANO DI QUELLI CHE SI APRONO",
+ "NON VOGLIO SAPERE CHE RAZZA DI CIBO CI SIA L\267 DENTRO",
+ "MI D\267 L'IMPRESSIONE DI ESSERE IMPRESSIONISTA",
// 470
- "LA NOTTE SI IMPADRONA DI TUTTI QUANTI... CHE PAURA?",
- "\324 OSTACOLATA",
- "\324 IL RE, NON LO AVEVI IMAGINATO?",
- "NO, NE UNO A CASA, ANZI GLI DO DA MANGIARE",
- "UNA SCAFFALATURA CON LIBRI ED ALTRE COSE",
+ "LA NOTTE CALA SU OGNUNO DI NOI... NON \324 TERRIFICANTE?",
+ "\324 INCASTRATA",
+ "\324 IL RE. LUI NON TE LO SEI IMMAGINATO, VERO?",
+ "NO, NE HO GI\267 UNO A CASA DA SFAMARE",
+ "UNO SCAFFALE CON LIBRI ED ALTRE COSE",
// 475
- "E A CHI CHIAMO A QUESTE ORE?",
- "\"COME FARE LA DECLARAZIONE DI REDDITI\"- CHE INTERESSANTE!",
- "NE HO UNO A CASA, CREDO CH'\324 UN BEST-SELLER MONDIALE",
- "UNA CHIAVE COMPLETAMENTE NORMALE",
- "MI SA QHE QUESTA NON \220 DI QU\336",
+ "MA CHI POTREBBE MAI CHIAMARE A QUEST'ORA?",
+ "\"COME COMPILARE LA DICHIARAZIONE DEI REDDITI\". MOLTO INTERESSANTE!",
+ "NE HO GI\267 UNO A CASA. CREDO SIA UN BEST SELLER MONDIALE",
+ "UNA CHIAVE ASSOLUTAMENTE NORMALE",
+ "NON CREDO CHE SIA DI QUESTA ZONA",
// 480
- "EH, SONO PATATINE FRITE A FORMA DI DENTI CANINI ! MI AFASCINA",
- "NON CREDO CHE SIA IL MOMENTO MIGLIORE PER METTERSI A MANGIARE DOLCI, L'ESSERE PI\353 CATTIVO DEL MONDO ha nelle sue mani la mia fidanzzata",
- "COME MI ST\343 DIVERTENDO UCCIDENDO VAMPIRI CON QUESTO!",
- "VEDIAMO SE APPARISCE UN ALTRO PRESTO",
- "NO, DEVE ESSERE CON UN VAMPIRO SPORCO E SCHIFFOSO COME QUELLO DI PRIMA",
+ "EHI, SONO PATATINE FRITTE A FORMA DI DENTI CANINI! LE ADORO!",
+ "NON CREDO SIA IL MOMENTO GIUSTO PER METTERMI A MANGIARE SCHIFEZZE, CONSIDERATO IL FATTO CHE LA MIA FIDANZATA \324 NELLE MANI DELL'UOMO PI\353 CATTIVO DELLA TERRA",
+ "ME LA STO DAVVERO SPASSANDO AD UCCIDERE VAMPIRI CON QUESTO!",
+ "VEDIAMO SE NE APPARE UN ALTRO",
+ "NO, DEV'ESSERE UN VAMPIRO SUDICIO E MALEODORANTE COME QUELLO CHE HO UCCISO PRIMA",
// 485
- "\324 L'AUTENTICA PARRUCA CHE UTILIZZ\343 ELVIS QUANDO DIVENT\343 PELATO",
- "\220 FARINA MA NON POSSO DIRE MARCHE",
- "FORSE IN UN ALTRO MOMENTO. OK?",
- "\220 UNA ASCIA BUONISSIMA, CHE PENA CHE NON CI SIA QU\336 VICINO NESSUNA TESTA DI VAMPIRO",
- "NO. NEL FONDO SONO UNA BRAVISSIMA PERSONA",
+ "\324 L'AUTENTICA PARRUCCA CHE UTILIZZ\343 ELVIS QUANDO DIVENT\343 PELATO",
+ "\324 FARINA, MA NON POSSO DIRE LA MARCA",
+ "FORSE UN'ALTRA VOLTA, VA BENE?",
+ "\324 UN'ASCIA MAGNIFICA, PECCATO CHE NON CI SIA NEMMENO UNA TESTA DI VAMPIRO QUI INTORNO",
+ "NO. IN FONDO SONO UNA BRAVISSIMA PERSONA",
// 490
- "\324 IL DEODORANTE DELLA TACHER -HI,HI,HI!",
- "\324 UN MANTELLO ABBASTANZA CARINO",
+ "\324 IL DEODORANTE DELLA TATCHER ... AH, AH, AH...!!",
+ "\324 UN MANTELLO MOLTO CARINO",
"",
- "COME TUTTI I RAMI DI TUTTI GLI ALBERI DEL MONDO, CIO\324 MICA SPEZIALE",
- "OH, INCREDIBILE!- UNA CORDA IN UNA AVVENTURA GRAFICA!",
+ "COME I RAMI DI TUTTI GLI ALBERI DEL MONDO. NON CI VEDO NIENTE DI SPECIALE",
+ "OH, INCREDIBILE! UNA CORDA IN UN'AVVENTURA GRAFICA!",
// 495
- "MI DOMANDO A CHE SERVE...",
- "UNA CORDA LEGATA A UNA BRANCA, O UNA BRANCA LEGATA A UNA CORDA, DIPENDE COME SI GUARDI",
- "SEMBRA CHE QUESTA GAZZA HA CATIVE INTENZIONI",
- "DAI.., NON LA DICO NULLA CHE POI SI ARRABBIA",
- "SEMBRA ESSERE MORTA, MA NON \220 VERO - EH?",
+ "MI DOMANDO A COSA POSSA SERVIRE...",
+ "UNA CORDA LEGATA AD UN RAMO O UN RAMO LEGATO AD UNA CORDA, DIPENDE DA COME SI GUARDA",
+ "PARE CHE QUESTA GAZZA ABBIA CATTIVE INTENZIONI",
+ "SCORDATELO, NON DIR\343 NULLA ALTRIMENTI SI ARRABBIA",
+ "MI SEMBRA MORTA, MA NON LO \324 VERAMENTE, VERO?",
// 500
- "NESSUN ANIMALE \220 STATO MALTRATO DURANTE LE RIPRESE DI QUESTO VIDEO-GIOCO",
+ "NESSUN ANIMALE HA SUBITO MALTRATTAMENTI DURANTE LA PRODUZIONE DI QUESTO VIDEOGIOCO",
},
};
@@ -4075,52 +4323,52 @@ const char *_textd[NUM_LANGS][NUM_TEXTD] = {
{
// 0
"",
- "COME VA, IGOR?",
- "-SEMPRE CHE C' UNA BUONA PARTITA SUCCEDE LO STESSO! BENE, ANDREMO A GUARDARLA AL BAR, COME SEMPRE",
- "ADESSO IGOR, ASCOLTA. ANDIAMO A REALIZZARE LA FASE 1 DEL MIO PROGETTO PER CONQUISTARE IL MONDO",
- "ATTRARREMO UN FULMINo DELLA TEMPESTA E LO DISMAGNETIZZAREMO CON L'INDIFIBULATORE. LA ELETTRICIT\265 ANDR\265 AL MIO MOSTRO E, GLI DAR\265 VITA!",
+ "COME STA ANDANDO, IGOR?",
+ "\324 SEMPRE LA STESSA STORIA, OGNI VOLTA CHE C'\324 UNA BELLA PARTITA SUL SATELLITE! COMUNQUE ANDREMO A VEDERLA AL BAR, COME AL SOLITO",
+ "ADESSO ASCOLTA BENE, IGOR, SIAMO ALLA FASE NUMERO UNO DEL MIO PIANO PER LA CONQUISTA DEL MONDO",
+ "ATTIREREMO UN FULMINE E LO DEMAGNETIZZEREMO CON L'INDIFIBULATORE. L'ELETTRICIT\267 VERR\267 TRASFERITA AL MOSTRO E GLI DAR\267 LA VITA!",
// 5
- "SE TUTTO VA BENE QUESTO SAR\265 SOLTANTO IL PRIMO DI UN'IMMENSO ESERCITO CHE CONQUISTAR\265 IL MONDO PER ME, HA,HA,HA",
- "I MOSTRI DISTRUGGERANNO TUTTE LE ARME DI TUTTI GLI ESERCITI DEL MONDO, MENTRE NOI CI RIFURGIAREMO nei miei terreni A GIBRALTAR",
- "POI, FAREMO UN GOLPE, E I GOVERNI DEL MONDO NON AVRANNO PER DIFENDERSI, E AVR\220 LE LORO NAZIONI SOTTO I MIEI PIEDI",
- "SAR\220 IL PRIMO CATTIVO DELLA STORIA CHE RIESCA!",
- "A TE NIENTE, SCIOCCO! ST\220 SPORRENDO LA TRAMA. BENE, TUTTO A POSTO?",
+ "SE TUTTO ANDR\267 PER IL VERSO GIUSTO, QUESTO SAR\267 L'INIZIO DI UN GRANDE ESERCITO CHE CONQUISTER\267 IL MONDO PER ME, AH, AH, AH",
+ "I MOSTRI DISTRUGGERANNO TUTTI GLI ESERCITI DEL MONDO, MENTRE NOI CI RIFUGEREMO IN UNO DEI TERRENI CHE HO COMPRATO A GIBILTERRA",
+ "POI FAREMO UN COLPO DI STATO, I GOVERNI DI TUTTO IL MONDO NON AVRANNO MODO DI DIFENDERSI E SI PROSTRERANNO AI MIEI PIEDI",
+ "SAR\343 IL PRIMO CATTIVO DELLA STORIA A RIUSCIRCI! AH, AH!",
+ "NON STO PARLANDO CON TE, IDIOTA! STO ESPONENDO LA TRAMA. BENE, \324 TUTTO PRONTO?",
// 10
- "-\220 IL MOMENTO! -PREMI L'INTERRUTTORE DELLE BATTERIE ALCALINE!",
- "- PORCA MISERIA! -CHE COSA NON \220 ANDATA BENE?",
- "SEI SICURO DI AVERLO CONTROLLATO BENE? E NO MANCABA NIENTE? ULTIMAMENTE PER I REDDITI NON VEDI UNA MADONNA",
- "IMBECILE!, NON HAI CONETTATO L'INDIFIBULATORE! LE VITI SARANO MAGNETIZZATE E ADESSO AVR\265 IL CERVELLO BRUCIATO",
- "SEI MORTO, SEI MORTO, COME TI PRENDA..",
+ "\324 IL MOMENTO! PREMI L'INTERRUTTORE DELLE BATTERIE ALCALINE!",
+ "PORCA MISERIA! COS'\324 ANDATO STORTO?",
+ "SEI SICURO DI AVERLO CONTROLLATO BENE E CHE NON MANCASSE NULLA? ULTIMAMENTE QUESTA STORIA DELLE TASSE TI STA MANDANDO DAVVERO FUORI DI TESTA",
+ "IDIOTA! HAI DIMENTICATO DI CONNETTERE L'INDIFIBULATORE. PROBABILMENTE LE VITI SI SARANNO MAGNETIZZATE E IL SUO CERVELLO SI SAR\267 ABBRUSTOLITO",
+ "SEI MORTO, SEI MORTO... ASPETTA CHE TI PRENDA!",
// 15
- "STAI ZITTO! DOMANI CERCHER\220 UN ALTRO CERVELLO E RIPETEREMO L'ESPERIMENTO",
- "NO. QUESTA VOLTA NE PORTER\220 UNO DI DONNA, COS\326 SAR\265 NUOVISSIMO, MAI UTILIZZATO. HA, HA HA, CHE BARZELLETA FALLITA",
- "E? SONO IL CATTIVO DELLA STORIA, E SONO MASCHILISTA SE VOGLIO, CAPITO? E NON LAMENTARTI UNA ALTRA VOLTA PERCHE MANGERAI LA TUA GOBBA",
- "HA,HA,HA. UN ALTRO PRESSO. ADESSO PAGHERAI MOLTO CARO QUESTA OFFESA, LA TUA INTENZIONE DI FINIRE CON ME. -IGOR, AL PENDOLO DELLA MORTE!",
- "DIMI, STUPIDO UMANO, COME MAI HAI PENSATO A DISTRUGGERMI?",
+ "STAI ZITTO! DOMANI CERCHER\343 UN ALTRO CERVELLO E RIPETEREMO L'ESPERIMENTO",
+ "NO. QUESTA VOLTA PRENDER\343 UN CERVELLO DI DONNA. PRATICAMENTE NUOVO, MAI UTILIZZATO. AH, AH,AH, BUONA QUESTA. ",
+ "E ALLORA? SONO IO IL CATTIVO DELLA STORIA, E POSSO ESSERE MASCHILISTA QUANTO VOGLIO, CAPITO? E SE DICI ANCORA QUALCOSA TI APPICCICO LA GOBBA IN FRONTE!",
+ "AH, AH, AH, CI SEI CASCATO ANCHE TU!! ADESSO LA PAGHERAI PER AVER OSATO SFIDARMI! IGOR, PORTALO AL PENDOLO DELLA MORTE!",
+ "DIMMI, STUPIDO UMANO, COME MAI VOLEVI DISTRUGGERMI?",
// 20
- "-CHE BELLO!, MI METTEREI A PIANGERE SE NON FOSSE PERCHE MI FA RIDERE",
- "HO BISOGNO DELLA TUA RAGAZZA, IL SUO CERVELLO MI AIUTER\265 A CONQUISTARE IL MONDO",
- "-SI, HA ! VADO A TOGLIARSILO PER METTEGLIELO AL MIO FRUSKYNSTEIN, E CON LUI DOMINER\220 IL MONDO, HA,HA,HA",
- "CHE?! - SEI MORTO, SEI MORTO! TI VADO A...MI HAI FATTO ARRABBIARE. SEI PRONTO PER MORIRE?",
- "HA,HA,HA. TU CREDI?",
+ "CHE BELLO! SE NON MI FACESSE RIDERE, MI METTEREI A PIANGERE",
+ "HO BISOGNO DELLA TUA RAGAZZA, IL SUO CERVELLO MI AIUTER\267 A CONQUISTARE IL MONDO",
+ "S\326, SICURO! LO PRENDER\343 DA LEI E LO DAR\343 AL MIO FRUSKYNSTEIN. IL MONDO SAR\267 NELLE MIE MANI, AH, AH, AH",
+ "COSA!? SEI UN UOMO MORTO! TI FAR\343... MI HAI FATTO VERAMENTE ARRABBIARE... PREPARATI A MORIRE!",
+ "AH, AH, AH. TI PIACEREBBE!",
// 25
- "SI, VERO? HA,HA,HA",
- "VA BENE, PUOI FUMARE LA ULTIMA SIGARETTA, MA SBRIGATI",
- "SONO STUFFO, BUTTA GI\265 LA SIGARETTA!",
- "E DIMI, QUELLA POZIONE HA L'EFFETTO INVERSO?",
- "QUELLO SI VEDR\265 ..",
+ "S\326, VERO? AH, AH AH",
+ "VA BENE, PUOI FUMARTI L'ULTIMA SIGARETTA. MA FAI PRESTO, OK?",
+ "MI HAI STUFATO, BUTTA VIA QUELLA SIGARETTA!",
+ "DIMMI UNA COSA, QUELLA POZIONE HA ANCHE L'EFFETTO OPPOSTO?",
+ "QUESTO LO VEDREMO...",
// 30
- "BENE, SAR\265 VERO?. IGOR, DAMI IL COMPACT DISC DI UNGHIE GRAFFIANDO UNA LAVAGNA",
- "NEANCHE SOGNARLO. LA RAGAZZA RIMANE CON ME, E TU RIMANI LI FINO CHE IL PENDOLO TI TAGLII IN FETTE. HA,HA,HA",
- "MA COME SONO CATTIVO, ANDIAMO IGOR, ANDIAMO A FARE LA POZIONE, ANDIAMO A CONQUISTARE IL MONDO",
+ "OK, ADESSO VEDREMO. IGOR DAMMI IL CD \"UNGHIE CHE GRAFFIANO LA LAVAGNA\"",
+ "NEANCHE PER SOGNO. LA RAGAZZA RIMANE QUI. E TU ASPETTERAI FINCH\220 IL PENDOLO NON TI AVR\267 FATTO A FETTINE. AH, AH, AH",
+ "CAVOLI, SONO DAVVERO CATTIVO... ANDIAMO, IGOR; PREPARIAMO LA POZIONE E CONQUISTIAMO IL MONDO",
"ADESSO CHE SUCCEDE?",
- "SI, CHE C'E?....LA PARTITA!",
+ "S\326, CHE C'\324?... OH DANNAZIONE, LA PARTITA!",
// 35
- "L'AVEVO DIMENTICATA. PRENDI LA RAGAZZA E ANDIAMO A GUARDARE IL CALCIO. CONQUISTER\220 IL MONDO DOPO",
+ "ME L'ERO DIMENTICATA. PRENDI LA RAGAZZA E ANDIAMO A GUARDARCELA. CONQUISTEREMO IL MONDO PI\353 TARDI",
"GRAZIE AMICO, AVEVO SETE",
- "-ARGH! -QUEL CROCIFISSO! -QUEL CROCIFISSO!...",
- "QUE BELLO \220 QUEL CROCIFISSO, NON MI ERO ACCORTO",
- "LASCIAMI, ST\220 GUARDANDO LA PARTITA",
+ "ARGH! QUEL CROCIFISSO! QUEL CROCIFISSO!...",
+ "CHE BELLO QUEL CROCIFISSO, NON L'AVEVO NOTATO",
+ "LASCIAMI IN PACE, STO GUARDANDO LA PARTITA",
// 40
"",
"",
@@ -4141,39 +4389,39 @@ const char *_textd[NUM_LANGS][NUM_TEXTD] = {
"",
// 55
"",
- "Ciao cieco. Come va?.",
- "Come sai che sono straniero.",
- "Sembri un cieco. Hai gli occhiali come il cieco di Sorrento, parli guardando all'infinito come Stevie Wonder..",
- "Bene, scusa. Non sapevo che non vedessi",
+ "CIAO CIECO. COME VA?",
+ "COME SAI CHE SONO UNO STRANIERO?",
+ "SEMBRI UN CIECO. HAI GLI OCCHIALI COME IL CIECO DI SORRENTO, PARLI GUARDANDO ALL'INFINITO COME STEVIE WONDER..",
+ "GUARDA, MI DISPIACE. NON SAPEVO CHE CI VEDESSI",
// 60
- "Ma non mi hai appena detto che non sei cieco?.",
- "- Ma se non vedi!.",
- "Beeeene. Scusa. Allora: Ciao : non vedente",
- "Sono John Hacker, st giocando al Drascula. Tu devi proprio essere il tipico personaggio che mi aiuter in cambio di un oggeto. Vero...?",
- "Ma... Scusa ciec..- non vedente! .Ma.. . che tipo di mestiere il tuo, di dare falci per soldi, mentre suoni la fisarmonica?.",
+ "MA NON MI HAI APPENA DETTO CHE NON SEI CIECO?",
+ "MA SE NON VEDI!",
+ "BEEEENE. SCUSA. ALLORA: \"CIAO NON VEDENTE\"",
+ "SONO JOHN HACKER, STO GIOCANDO A DRASCULA. TU DEVI PROPRIO ESSERE IL TIPICO PERSONAGGIO CHE MI AIUTER\267 IN CAMBIO DI UN OGGETTO. VERO? EH? VERO?",
+ "SCUSA SE TE LO DOMANDO, CIEC... NON VEDENTE! MA... CHE TIPO DI MESTIERE \324 IL TUO, DI DARE FALCI PER SOLDI, MENTRE SUONI LA FISARMONICA?",
// 65
- "Ah, si. \324 vero. Ciao non vedente....(cieco)",
- "Ecco la abbondante quantit di soldi che mi avevi chiesto.",
- "Mi raccomando",
- "Ciao straniero.",
- "E tu... Come sai che sono cieco?",
+ "AH, S\326. \324 VERO. CIAO NON VEDENTE...(CIECO)",
+ "ECCO LA COSPICUA SOMMA DI DENARO CHE MI HAI CHIESTO",
+ "LO SPERO PROPRIO",
+ "CIAO STRANIERO.",
+ "E TU... COME SAI CHE SONO CIECO?",
// 70
- "E tu parli come il figlio di Bill Cosby e non ti offendo.",
- "No, se non vedo.",
- "E non lo sono.",
- "-Oh, certo!. Come non vedo mi chiamano cieco, no?.",
- "-Ciao Straniero! e cosa fai in Transilvania?",
+ "E TU PARLI COME IL FIGLIO DI BILL COSBY E NON TI OFFENDO.",
+ "NO, NON CI VEDO.",
+ "E NON LO SONO.",
+ "OH, CERTO! SICCOME NON CI VEDO TU MI ACCUSI DI ESSERE CIECO.",
+ "CIAO STRANIERO! COSA CI FAI IN TRANSILVANIA?",
// 75
- "Corretto straniero. Per una abbondante quantit di soldi, ti dar in cambio una falce, per quando ne avrai bisogno.",
- "Shhhhhh. Sono trafficante di falci, devo proprio dissimulare.",
- "Perche mi lo hai detto prima, no?",
- "Grazie straniero. Ecco la tua falce. Un oggeto che ti sar molto utile pi avanti...... davvero.",
+ "CORRETTO, STRANIERO. PER UN'ABBONDANTE QUANTIT\267 DI DENARO TI DAR\343 UNA FALCE, PER QUANDO NE AVRAI BISOGNO.",
+ "SHHHHHH. SONO TRAFFICANTE DI FALCI, PER QUESTO DEVO FINGERE.",
+ "PERCH\220 ME LO HAI DETTO PRIMA, NO?",
+ "GRAZIE STRANIERO. ECCO LA TUA FALCE. UN OGGETTO CHE TI SAR\267 MOLTO UTILE PI\353 AVANTI...... DAVVERO.",
"",
// 80
"",
"",
- "No, nada",
- "bla, bla, bla."
+ "NO, NIENTE",
+ "BLA, BLA, BLA.",
},
};
@@ -4261,22 +4509,22 @@ const char *_textb[NUM_LANGS][NUM_TEXTB] = {
{
// 0
"",
- "QU\326, BEVENDO",
- "MORTI TUTTI. GRAZIE. BURRP",
- "SII, CERTO, SICURO..",
- "QUESTA PER IL ZIO PEPPINO",
+ "SONO QUI, STO BEVENDO",
+ "SONO TUTTI MORTI. GRAZIE. BURRP",
+ "S\326, CERTO, SICURO...",
+ "QUESTA \324 PER LO ZIO DESIDERIO",
// 5
- "E QUEST'ALTRA, PER IL CADAVERE DEL ZIO PEPPINO",
- "MIO ZIO. FU ANDATO AL CASTELLO, E NON MAI TORNATO",
- "EEEHH, TORN\220, MA PER POCO TEMPO. SE IL VON BRAUN NON AVESSE SBAGLIATO, MIO ZIO SAREBBE QU\326 BEVENDO",
- "NIENTE..",
- "EEH,SI! QUEL MALVAGIO CI HA INTIMORATI",
+ "E QUEST'ALTRA \324 PER IL CADAVERE DELLO ZIO DESIDERIO",
+ "MIO ZIO. \324 ANDATO AL CASTELLO E NON \324 PI\353 TORNATO",
+ "EH, TORN\343, MA NON TUTTO INTERO. SE VON BRAUN NON AVESSE SBAGLIATO, ADESSO MIO ZIO SAREBBE QUI A BERE CON NOI",
+ "NIENTE...",
+ "EH, S\326! QUEL MALVAGIO CI HA INTIMORITI TUTTI",
// 10
- "A VOLTE SCENDE AL PAESE E QUANDO SE NE VA SI PORTA QUALCUNO",
- "UN P\220 DOPO SOLTANTO TROVIAMO QUALQUE RESTO. CREDO CHE TRAFFICA ORGANI O QUALCOSA DEL GENERE",
- "L'UNICO DEL PAESE CHE SA COME FINIRE CON DRASCULA \220 UNO CHE HA STUDIATO",
- "DA CHE FU SCONFFIGIATO DA DRASCULA SI \220 ALLONTANATO A UNA CAPANNA FUORI DEL PAESE",
- "L'UNICO CHE POTREBBE AIUTARCI A VINCERE DRASCULA, E NON VUOLE SAPERE NIENTE DI NOI. COSA PENSI?",
+ "A VOLTE SCENDE IN PAESE E QUANDO SE NE VA SI PORTA VIA QUALCUNO",
+ "POCO DOPO TROVIAMO SOLTANTO QUALCHE RESTO. CREDO CHE SIA UN TRAFFICANTE DI ORGANI O QUALCOSA DEL GENERE",
+ "\324 L'UNICA PERSONA DEL VILLAGGIO CHE SAPPIA COME FARLA FINITA CON DRASCULA. \324 UNO CHE HA STUDIATO",
+ "DA QUANDO FU SCONFITTO DA DRASCULA VIVE IN UNA BARACCA FUORI DAL PAESE",
+ "LUI \324 L'UNICO CHE POTREBBE AIUTARCI A SCONFIGGERE DRASCULA, MA NON VUOLE SAPERNE. TU CHE NE PENSI?",
},
};
@@ -4432,39 +4680,39 @@ const char *_textbj[NUM_LANGS][NUM_TEXTBJ] = {
{
// 0
"",
- "ST\265 BENE? SENTA, PUO SENTIRMI? SI \220 MORTO?",
- "NO, IL MIO NOME BILLIE JEAN, MA PUOI CHIAMARMI B.J. PI \351 BREVE",
- "HI,HI!- CHE BUONO!",
- "NON SO JOHNY, ERO QU\326, STAVO PER ADDORMENTARMI, QUANDO HO SENTITO UN FORTE RUMORE NEL CORRIDOIO",
+ "TI SENTI BENE? ANDIAMO, SVEGLIATI! RIESCI A SENTIRMI? MA SEI MORTO?",
+ "NO, MI CHIAMO BILLIE JEAN, MA PUOI CHIAMARMI B.J., \324 PI\353 CORTO.",
+ "HI, HI! QUESTA ERA BUONA!",
+ "BEH, JHONNY. VEDI, ME NE STAVO QUA, GI\267 PRONTA PER ANDARE A LETTO, QUANDO HO SENTITO UN FORTE RUMORE IN CORRIDOIO",
// 5
- "PRIMA NON GLI HO DATTO IMPORTANZA, MA DUE ORE DOPO HO SCOPERTO CHE NON RIUSCIVO A ADDORMENTARMI E SONO uscita A FARE QUATTRO PASSI",
- "E FIGURATI LA SORPRESA QUANDO HO APERTO LA PORTA E TI HO TROVATO PER TERRA. TI GIURO, HO PENSATO CH'ERI MORTO..., MA COME SONO SCIOCCA",
- "VOLEVO FARTI IL BOCCA A BOCCA, MA NON C'ERA BISOGNO PERCHE SUBITO HAI COMINCIATO A PARLARE",
- "HAI DETTO NON SO CHE DI UN SPAVENTAPASSERI. CHE COLPO.....!, PERCHE QUANDO UN MORTO SI METTE A PARLARE FA UN COLPO GRANDISSIMO!",
- "VERO DI SI? NON SO COME SONO RIUSCITA, TI HO TRASPORTATO ALLA MIA CAMERA, TI HO MESSO SUL MIO LETTO E.... NIENTE PI\351 .",
+ "ALL'INIZIO NON CI HO FATTO CASO, MA DOPO CIRCA DUE ORE NON RIUSCIVO ANCORA A PRENDERE SONNO E ME NE SONO ANDATA A FARE DUE PASSI",
+ "E IMMAGINA LA MIA SORPRESA QUANDO HO APERTO LA PORTA E TI HO VISTO DISTESO A TERRA. TI GIURO, HO PENSATO CHE FOSSI MORTO... AH, AH, CHE SCIOCCA",
+ "VOLEVO FARTI LA RESPIRAZIONE BOCCA A BOCCA MA NON \324 SERVITO PERCH\220 HAI INIZIATO A PARLARE",
+ "HAI DETTO QUALCOSA A PROPOSITO DI UNO SPAVENTAPASSERI. MI HAI FATTO VENIRE UN COLPO. SAI, \324 ABBASTANZA SCIOCCANTE VEDERE UN MORTO CHE PARLA",
+ "VERO? NON SO COME, MA SONO RIUSCITA A PORTARTI IN CAMERA MIA, TI HO MESSO SUL LETTO E... QUESTO \324 TUTTO... AH, AH, AH.",
// 10
- "NO, NON \220 STATA LA BOTTA, HI, HI. \220 PERCHE ... HO PESTATO I TUOI OCCHIALI",
- "MAMMA MIA MA COM'\220 BELLO CON GLI OCCHIALI! SO CHE NON \220 FERNANDO LANCHA, MA HA QUALCOSA CHE MI PIACE MOLTISSIMO",
- "SI,SI, VOGLIO... ABBRACIAMI FORTE, BACIAMI MOLTO..",
- "OH JOHNY, CARO, MENO MALE CHE SEI VENUTO. QUEL MALVAGIO, DRASCULA, MI HA LEGATO AL LETTO E POI SE NE \220 ANDATO A GUARDARE LA PARTITA",
- "SI, \220 VERO, LIBERAMI",
+ "NO, NON \324 STATA LA BOTTA, HI, HI. \324 CHE PER SBAGLIO HO PESTATO I TUOI OCCHIALI",
+ "MAMMA MIA COM'\324 BELLO CON GLI OCCHIALI! SO CHE NON \324 ANTONIO BANDERAS, MA HA QUALCOSA CHE MI PIACE MOLTISSIMO",
+ "S\326, S\326, LO VOGLIO... ABBRACCIAMI FORTE, BACIAMI...",
+ "OH JOHNNY, CARO, MENO MALE CHE SEI QUI. DRASCULA, QUEL MALEDETTO, MI HA LEGATA AL LETTO E POI SE NE \324 ANDATO A GUARDARE LA PARTITA",
+ "S\326, \324 VERO, LIBERAMI",
// 15
- "NO, MI DISPIACE. HO UTILIZZATO TUTTE IN CARCERE PROBANDO LIBERARMI QUANDO TU MI AVEVI LASCIATA",
- "JOHNY, SEI TU? - BENISSIMO. LO SAPEVO ",
- "NON TI FIGURI QUANTO MI HA FATTO SOFFRIRE DRASCULA",
- "PRIMA MI HA PORTATO VOLANDO FINO QUA E POI MI HA RICHIUSA IN QUESTA CAMERACCIA CHE NON HA N\220 UNO SPECCHIO",
- "COME HAI SENTITO. E LO PEGLIORE: N\220 UNA VOLTA SI \220 SCUSATO",
+ "NO, MI DISPIACE. LE HO USATE TUTTE NELLA CELLA CERCANDO DI LIBERARMI QUANDO MI HAI ABBANDONATA",
+ "JOHNNY, SEI TU? OH, GRAZIE AL CIELO, SAPEVO CHE SARESTI VENUTO!",
+ "NON IMMAGINI NEMMENO QUANTO QUEL MALVAGIO DI DRASCULA MI ABBIA FATTO SOFFRIRE",
+ "PRIMA MI HA PORTATO FIN QUA VOLANDO E POI MI HA RINCHIUSA IN QUESTA CAMERACCIA CHE NON HA NEANCHE UNO SPECCHIO",
+ "\324 QUELLO CHE TI STO DICENDO! E IL PEGGIO \324 CHE NON SI \324 MAI SCUSATO, NEMMENO UNA VOLTA",
// 20
- "JOHNY, CARO. DOVE SEI?",
- "SONO PRONTA, FAMI USCIRE DA QU\326 ",
- "ASPETTA, VADO A GUARDARE... NO CARO, MI DISPIACE",
- "PRENDI..",
- "\"CARO JOHNY:",
+ "JOHNNY, CARO. DOVE SEI?",
+ "SONO PRONTA, FAMMI USCIRE DA QUI",
+ "ASPETTA CHE CONTROLLO... NO, CARO, MI DISPIACE",
+ "PRENDI...",
+ "\"CARO JOHNNY",
// 25
- "MAI POTR\220 DIMENTICARTI, MA NON SAREMO MAI FELICI INSIEME. SAR\220 SINCERA CON TE : C'\220 NE UN ALTRO; PI\351 ALTO, PI\351 FORTE..",
- "ANZI MI HA LIBERATO DA DRASCULA. MI HA CHIESTO LA MANO E HO DETTO DI SI",
- "ADIO JOHNY. NON CERCARE UNA SPIEGAZIONE, PERCHE L'AMORE \220 CIECO.",
- "SPERO NON MI ODII, E RICORDA CHE ANCORA TI VOGLIO BENE, SEBBENE SOLO COME UN AMICO\"",
+ "NON POTR\343 MAI DIMENTICARTI, MA NON SAREMO MAI FELICI INSIEME. SAR\343 SINCERA CON TE: C'\324 UN ALTRO; PI\353 ALTO, PI\353 FORTE...",
+ "MI HA LIBERATO DA DRASCULA. MI HA CHIESTO LA MANO E HO DETTO DI S\326",
+ "ADDIO JOHNNY. NON CERCARE UNA SPIEGAZIONE, PERCH\220 L'AMORE \324 CIECO.",
+ "SPERO CHE NON MI ODIERAI, E RICORDA CHE TI VOGLIO BENE, SEBBENE TU PER ME SIA SOLTANTO UN AMICO\"",
},
};
@@ -4597,33 +4845,33 @@ const char *_texte[NUM_LANGS][NUM_TEXTE] = {
{
// 0
"",
- "EO, LEI",
- "MA CHE DICI!",
- "SONO VIVO, MA HO SEMPRE MOLTA FAME, SA LEI?",
- "IO ERO IL BEONE DEL PAESE, DEGNO SUCCESSORE DI UNA FAMIGLIA DI ILLUSTRI BEONI, E UNA NOTTE DRASCULA MI SEQUESTR\220 PER RUBARMI GLI ORGANI",
+ "EHI, LEI!",
+ "NON RACCONTARMI CERTE CAVOLATE SU UN CADAVERE, OK?",
+ "SONO VIVO. STO SOLO MORENDO DI FAME",
+ "IO ERO L'UBRIACONE DEL PAESE, DEGNO SUCCESSORE DI UNA FAMIGLIA DI ILLUSTRI UBRIACONI, E UNA NOTTE DRASCULA MI RAP\326 PER RUBARMI GLI ORGANI",
// 5
- "mi utilizza COME UNO SCASSO, OGNI VOLTA CHE HA BISOGNO DI QUALCOSA PER IL MOSTRO CHE ST\265 CREANDO VIENE QUA E MI LO toglia",
- "AL INIZIO MI FACEVA MALE, MA ORA NON FA NIENTE",
- "NON SO, SAR\265 LA SUA TESINA DI FINE DI LAUREA",
- "IL MIO NOME PEPPINO, PER SERVIRGLI",
- "LA VERIT\265 CHE NON HO MOLTA VOGLIA, COMUNQUE GRAZIE MILE, SIGNORE",
+ "SICCOME L'ALCOL MI MANTIENE IN VITA, MI TIENE QUI COME UNA SCORTA. OGNI VOLTA CHE HA BISOGNO DI QUALCOSA PER IL MOSTRO CHE STA CREANDO, VIENE DA ME E SE LO PRENDE",
+ "ALL'INIZIO FACEVA MALE, MA ORA NON SENTO PI\353 NULLA",
+ "NON SO, MAGARI SAR\267 LA SUA TESI DI LAUREA",
+ "IL MIO NOME \324 DESIDERIO, PER SERVIRVI",
+ "LA VERIT\267 \324 CHE NON HO MOLTA VOGLIA, COMUNQUE GRAZIE MILLE, SIGNORE",
// 10
- "SI, PROPRIO TU",
- "PER CHE TUTTI I VIDEO-GIOCHI D' AVVENTURE FINISCONO CON UN'ALBEGGIARE O UN TRAMONTO?",
- "E TUTTI QUESTI NOMI SONO DI CHI HANNO FATTO IL GIOCO?",
- "E NON SI VERGOGNANO DI USCIRE ED ESSERE VISTI DA TUTTI QUANTI?",
- "UFFA, SOLTANTO ESCI \"EMILIO DE PAZ\"",
+ "PROPRIO TU!",
+ "PERCH\220 TUTTI I GIOCHI D'AVVENTURA FINISCONO SEMPRE CON UN'ALBA O UN TRAMONTO?",
+ "E TUTTI QUESTI NOMI SONO DI CHI HA FATTO IL GIOCO?",
+ "E NON SI VERGOGNANO A FARSI VEDERE DA TUTTI?",
+ "CAVOLI, QUELL'EMILIO DE PAZ \324 DAPPERTUTTO!!",
// 15
"DAVVERO?",
- "SI",
- "NON \220 PER METTERSI COS\326 ",
- "CERTO LUPO-MANNARO..",
- "... MA NON SEI CADUTO DA UNA FINESTRA E TI HAI FATTO MALE?",
+ "S\326",
+ "BEH, NON NE FARE UNA QUESTIONE",
+ "CERTO, LUPO MANNARO...",
+ "... MA NON TI SEI FATTO MALE CADENDO DA UNA FINESTRA?",
// 20
- "SE PER UNA VOLTA NON FOSSENO SEMPRE GLI STESSI",
- "QUELLO \220 GIA USCITO QUATRO VOLTE",
- "MI PIACEREBBE ESSERE TOP MODEL",
- "SI, E TU, COSA VAI A FARE?",
+ "SE PER UNA VOLTA NON FOSSERO SEMPRE GLI STESSI",
+ "QUELLO \324 GIA USCITO QUATTRO VOLTE",
+ "MI PIACEREBBE ESSERE UN MODELLO",
+ "S\326, E TU COSA FARAI?",
},
};
@@ -4800,44 +5048,44 @@ const char *_texti[NUM_LANGS][NUM_TEXTI] = {
{
// 0
"",
- "MAESTRO, CREDO CHE QUESTO NON VA",
- "SICURISSIMO, MAESTRO",
- "SCUSI, MAESTRO",
- "VA A PORTARE UN ALTRO SCIENTIFICO PAZZO? GLI AVVERTO CHE IL LABORATORIO PIENO E NE ABBIAMO TUTTI SCADUTI",
+ "PADRONE, CREDO NON STIA FUNZIONANDO",
+ "SICURISSIMO, PADRONE",
+ "MI DISPIACE, PADRONE",
+ "HAI INTENZIONE DI ATTIRARE ALTRI SCIENZIATI PAZZI? IL LABORATORIO \324 GI\267 PIENO, E TRA L'ALTRO SONO TUTTI SCADUTI.",
// 5
- "ZITTO, MAESTRO, FIGURASI SE LE SENTONO LE FEMMINISTE",
- "ACCIDENTI!",
- "-MAESTRO! NON LE ASPETTAVO COS\326 PRESTO!",
- "MALE MAESTRO, DEVONO CI ESSERE PROBLEMI CON IL SATELLITE E NON RIESCO A SINTONIZZARE L'IMMAGINE. ANZI LA TEMPESTA CAUSA INTERFERENZE",
- "CHE NE SO, MAESTRO",
+ "ZITTO, PADRONE, LE FEMMINISTE POTREBBERO SENTIRLA",
+ "DANNAZIONE!",
+ "PADRONE! NON LA ASPETTAVO COS\326 PRESTO!",
+ "MALE, PADRONE; DEV'ESSERCI UN PROBLEMA CON IL SATELLITE E NON RIESCO A SINTONIZZARE L'IMMAGINE. SEMBRA CHE LA TEMPESTA CAUSI INTERFERENZE",
+ "NON SAPREI, PADRONE",
// 10
- "SI, MAESTROl",
- "MAESTRO",
+ "S\326, MIO PADRONE",
+ "PADRONE",
"SA CHE ORE SONO?",
- "EH? -AH, CHE COLPO! TU SEI QUELLO DI \"PULIZIA NOTTURNA\" NO?",
- "IO SONO IGOR, IL MAGGIORDOMO. PUOI COMINCIARE NEL SALOTTO DI BALLO, IERI C'ERA ORGIA SOPRANATURALE ED \220 PIENO DI MERDA",
+ "COSA? AH, MI HAI SPAVENTATO! TU SEI IL \"RAGAZZO DELLE PULIZIE NOTTURNE\" GIUSTO?",
+ "SONO IGOR, IL MAGGIORDOMO. PUOI COMINCIARE DALLA SALA DA BALLO. IERI \324 STATA TEATRO DI UN'ORGIA SOPRANNATURALE ED OGGI \324 RIDOTTA AD UNA MERDA.",
// 15
"SE HAI BISOGNO DI QUALCOSA, COMPRALA",
- "LA DECLARAZIONE DI REDDITI, NON VEDI?",
- "NEANCH'IO, I NUMERI SONO PICCOLISSIMI E ANZI, IO NON VEDO BENE DA LONTANO",
- "NEANCHE PARLARNE, MI FANNO SEMBRARE BRUTTO",
- "\220 UNA FESTA CHE FA IL MAESTRO PER I SUOI AMICI OGNI VOLTA CHE ARRIVA QUALCHE IMBECILE CHE VUOLE FINIRE CON LUI",
+ "\324 LA DICHIARAZIONE DEI REDDITI, NON VEDI?",
+ "NEANCH'IO. I NUMERI SONO PICCOLISSIMI E NON CI VEDO MOLTO BENE DA LONTANO",
+ "NEANCHE PER SOGNO! MI FANNO SEMBRARE BRUTTO",
+ "\324 UNA FESTA CHE ORGANIZZA IL PADRONE CON I SUOI AMICI OGNI VOLTA CHE ARRIVA QUALCHE IMBECILLE CHE VUOL CERCARE DI UCCIDERLO",
// 20
- "PRIMA, GLI TOGLIANO GLI OCCHI; POI GLI VERSANO SUCCO DI LIMONE, DOPO IL BRUCIORE.......",
+ "PER PRIMA COSA GLI CAVANO GLI OCCHI. POI GLI VERSANO DEL SUCCO DI LIMONE IN MODO CHE BRUCI, POI...",
"NO",
- "COME CHE PER CHE NO? MA TU HAI VISTO CHE ORE SONO?",
- "IN INVERNO, SI",
+ "COME PERCH\220 NO? HAI VISTO CHE ORE SONO?",
+ "IN INVERNO, S\326",
"ARRIVEDERCI",
// 25
- "N\324 PENSARCI",
- "BENE, BASTA PER OGGI. VADO A CENARE",
- "E CHE SEMPRE DIMENTICO CHIUDERE CON LA CHIAVE",
+ "NON PENSARCI NEMMENO!",
+ "BENE, BASTA PER OGGI. VADO A CENA",
+ "DIMENTICO SEMPRE DI CHIUDERE A CHIAVE",
"ACCIDENTI!",
- "EH? -AH! CHE COLPO, MAESTRO, PENSAVO STAVA DURMENDO",
+ "COSA? PADRONE! MI HA SPAVENTATO! PENSAVO STESSE DORMENDO",
// 30
- "ORA MI RICORDO, PRENDA LE CHIAVI DEL SOGGIORNO, COS\326 DOMANI MATTINA NON MI DISTURBA SE VUOLE GUARDARE I CARTONI ANIMATI",
- "HA PRESSO FREDDO UN'ALTRA VOLTA, MAESTRO? SEMPRE GLI DICO CHE METTA IL RISCALDAMENTO",
- "PRENDA UNA ASPIRINA ED A SUDARE. BUONA NOTTE",
+ "OH, A PROPOSITO, HO PRESO LE CHIAVI DEL SOGGIORNO, COS\326 POTR\267 VEDERE I CARTONI ANIMATI DEL MATTINO SENZA SVEGLIARMI",
+ "HA DI NUOVO PRESO IL RAFFREDDORE, PADRONE? DANNAZIONE. \324 ANNI CHE LE DICO DI METTERE IL RISCALDAMENTO",
+ "BENE, PRENDA UN'ASPIRINA E VADA A LETTO A SUDARE. BUONA NOTTE",
},
};
@@ -5010,43 +5258,43 @@ const char *_textl[NUM_LANGS][NUM_TEXTL] = {
{
// 0
"",
- "UN ATTIMO. PERCHE SIAMO DI DIVERSE RAZZE E LA SOCIET\265 DICA CHE SIAMO NEMICI, ANDIAMO A LASCIARCI DOMINARE PER I PI\351 PRIMITIVI ISTINTI?",
- "MA NON SIAMO UNITI DALLA RAGIONE, DALLA ARMA PI\351 PODEROSA E ANCHE PER IL DONO PI\351 PREZIOSO CHE ABBIAMO?",
- "SE IL GIUDIZIO GUIDASSE I NOSTRI PASSI NELLA VITA SENZA LASCIARE POSTO AI SENTIMENTI, CHE MOSTRANO LE NOSTRE INCLINAZIONI PRE-EVOLUTIVI!",
- "NON CREDI CHE SAREMMO PI\351 BEATI SENZA QUESTO LEGAME EMOZIONALE? RISPONDE EFFIMERA CREATURA",
+ "UN ATTIMO. SOLO PERCH\220 APPARTENIAMO A RAZZE DIVERSE E LA SOCIET\267 DICE CHE SIAMO NEMICI, VOGLIAMO LASCIARE CHE SIANO I NOSTRI ISTINTI PI\353 PRIMITIVI A GUIDARCI?",
+ "NON SIAMO FORSE UNITI DALLA RAGIONE? CHE \324 SIA L'ARMA PI\353 PODEROSA SIA IL DONO PI\353 PREZIOSO CHE ABBIAMO?",
+ "AH, SE IL GIUDIZIO GUIDASSE I NOSTRI PASSI NELLA VITA SENZA LASCIARE IL POSTO AI SENTIMENTI CHE MOSTRANO LE NOSTRE INCLINAZIONI PRE-EVOLUTIVE!",
+ "RISPONDI, EFFIMERA CREATURA. NON CREDI CHE SAREMMO PI\353 FELICI SENZA QUESTO LEGAME EMOZIONALE?",
// 5
- "NON PASSI",
- "VEDI? QUESTO UN CHIARO ESEMPIO: TU VUOI PASSARE E PROSEGUIRE LA TUA AVVENTURA ED IO NON POSSO PERMETTERLO",
- "MA DEVE ESSERE CAUSA DI CONFRONTO QUANDO ANCORA NON CI CONOSCIAMO?",
- "CHE TI HO DETTO?",
- "BOH, DIPENDE DI CHE CAPIAMO COME RELAZIONE. CI SONO AUTORI CHE DIFENDONO...",
+ "NON PASSERAI",
+ "VEDI? QUESTO \324 UN CHIARO ESEMPIO: TU VUOI PASSARE E PROSEGUIRE LA TUA AVVENTURA ED IO NON POSSO PERMETTERLO",
+ "DEVE ESSERE DUNQUE MOTIVO DI CONFRONTO TRA NOI, CHE NON CI CONOSCIAMO PER NULLA?",
+ "BENE QUINDI",
+ "BEH, DIPENDE DA COSA INTENDIAMO PER RELAZIONE. ALCUNI AUTORI DIFENDONO...",
// 10
- "LA CACCIA COME FORMA DI SUSSISTENZA \220 UNA ATTIVIT\265 ARCAICA, INCOMPATIBILE CON UNA NATURA SUPERIORE COM'\220 LA MIA: ADESSO SONO VEGETARIANO",
- "TEMPO FA, STAVO MANGIANDO UN TIZIO QUANDO MI SONO MESSO A RIFLETTERE. FU QUANDO LA CONCLUSIONE DI PRIMA ARRIV\220 ",
- "FU DIFFICILE LASCIARE LE MIE VECCHIE ABITUDINI, MA LA MIA ANIMA IRASCIBILE HA VINTO LA CONCUPISCIBILE E NON MANGIO PI\351 DELLA CARNE",
- "NEPPURE IL PIACERE CHE FA UN OSSO, COL SUCCO DELLA PELLE E QUEL SAPORE CHE TI PORTA A POSTI LONTANI E PARADISIACI...",
- "NEMMENO MI TOCCA DA VICINO, DAVVERO",
+ "LA CACCIA COME FORMA DI SUSSISTENZA \324 UNA ATTIVIT\267 ARCAICA, INCOMPATIBILE CON LA MIA ATTUALE NATURA SUPERIORE: SONO DIVENTATO VEGETARIANO",
+ "SONO ARRIVATO A QUESTA CONCLUSIONE TEMPO FA. STAVO MANGIANDO UN TIZIO QUANDO MI SONO MESSO A RIFLETTERE.",
+ "FU DIFFICILE LASCIARE LE MIE VECCHIE ABITUDINI, MA LA MIA ANIMA IRASCIBILE HA AVUTO LA MEGLIO SU QUELLA CONCUPISCENTE E DA ALLORA NON MANGIO PI\353 CARNE",
+ "NEPPURE IL PIACERE DI SUCCHIARE UN OSSO, SENTIRE IL GUSTO DELLA PELLE E IL SAPORE DOLCE DEL MIDOLLO CHE TI PORTA IN POSTI LONTANI E PARADISIACI...",
+ "NEPPURE QUESTO MI TOCCA, DAVVERO",
// 15
"CHE COSA?",
- "NON SO SU CHE MI PARLI, EFFIMERA CREATURA",
- "NON MI INTERESA",
- "GLI ALTRI VIDEO-GIOCHI, NON SO, MA QUESTO \220 PER APPROFITTARE QUESTO BELLO SCHERMO",
+ "NON CAPISCO DI CHE PARLI, EFFIMERA CREATURA",
+ "NON MI INTERESSA",
+ "GLI ALTRI VIDEOGIOCHI, NON SAPREI, MA QUESTO \324 PER SFRUTTARE AL MEGLIO QUESTO BELLO SCHERMO",
"",
// 20
- "IO SI ME VERGOGNAREI",
- "NO, SONO IL NONNO, IL PADRE, IL FIGLIO, E UN AMICO CHE SI CHIAMA COS\326 ",
- "NO, MA SE NON \220 COS\326, SEMBRAR\265 CHE HANNO FATTO IL VIDEO-GIOCO IN CINQUE",
- "BRAVI RAGAZZI",
- "-QUELLO \220 BUONO, QUELLO \220 BUONO!",
+ "IO ME LA PRENDEREI",
+ "NO, SONO IL NONNO, IL PADRE, IL FIGLIO, E UN AMICO CHE SI CHIAMA COS\326",
+ "NO, MA SE NON \324 COS\326, SEMBRER\267 CHE IL VIDEOGIOCO L'ABBIANO FATTO IN CINQUE",
+ "SONO RAGAZZI PROMETTENTI",
+ "\324 BRAVO, \324 BRAVO!",
// 25
"CHIAMAMI COSTANTINO",
- "NON ERO IO, DAI,. ERA IL MIO CONTROFIGURA, IL COYOTE",
- "INSOMMA, MOLTI TITOLI DI CODA",
- "IO NON SO GI\265 QUANTI",
- "ALLORA PEPPINO, CHE VAI FARE ADESSO?",
+ "NON ERO IO, DAI. ERA IL MIO GEMELLO, IL COYOTE",
+ "ALLA FACCIA, CHE TITOLI DI CODA LUNGHI",
+ "HO PERSO IL CONTO",
+ "ALLORA DESIDERIO, CHE FARAI ORA?",
// 30
"MA DOVRESTI DIMAGRIRE",
- "MI APPARTER\220 AL TIBET A RIFLETTERE SUL SENSO DELLA VITA",
+ "MI RITIRER\343 IN TIBET A RIFLETTERE SUL SENSO DELLA VITA",
},
};
@@ -5159,27 +5407,27 @@ const char *_textp[NUM_LANGS][NUM_TEXTP] = {
// 0
"",
"CIAO",
- "BELLA, MOLTO BELLA",
- "NO, CHE NON LO FA",
+ "SISSIGNORE, MOLTO BELLA",
+ "NO CHE NON LO FA",
"VA BENE",
// 5
- "-SI?",
+ "S\326?",
"E?",
- "MI DISPIACE. IL SINDACATODI PIANISTI NON MI DA PERMESSO PER LIBERARE RAGAZZE DALLE MANI DI VAMPIRI",
- "SE LA AVESSE SEQUESTRATA IL LUPO-MANNARO...",
- "SOLTANTO POSSO SUONARE QUESTA CANZONE",
+ "MI DISPIACE. IL SINDACATO DEI PIANISTI NON MI PERMETTE DI SALVARE RAGAZZE DALLE GRINFIE DEI VAMPIRI",
+ "SE FOSSE STATA RAPITA DAL LUPO MANNARO...",
+ "NON POSSO SUONARE ALTRO CHE QUESTA CANZONE",
// 10
- "\324 PERCHE SONO PIANISTA DI CONSERVATORIO E IL TABERNERO NON COMPRA PI\353 PARTITURE",
- "PECCATO.....MI PIACE MOLTISSIMO LA MUSICA CLASSICA!",
- "PERCHE MI HO MESSO TAPPI NEGLI ORECCHII",
- "PERCHE SO LEGGERE LE LABRA",
+ "\324 PERCH\220 SONO PIANISTA DI CONSERVATORIO E IL BARISTA NON COMPRA PI\353 SPARTITI",
+ "E DIRE CHE MI PIACE MOLTISSIMO LA MUSICA CLASSICA!",
+ "PERCH\220 HO I TAPPI NELLE ORECCHIE",
+ "PERCH\220 SO LEGGERE LE LABBRA",
"NOOO",
// 15
- "NO!, NON MI SOPPOROTO!",
+ "NO! NON POSSO ANDARE AVANTI COS\326!",
"HO DETTO DI NOOO!",
- "COSA? SI, SI MI INTERESA, COME NO",
- "ADESSSO POTR\343 SUONARE UN'ALTRA CANZONE, GRAZIE!!",
- "CREDO CHE I MIEI TAPPI ADESSO SONO TUOI",
+ "COSA? CERTO CHE MI INTERESSA",
+ "DEO GRATIAS! ADESSO POTR\343 SUONARE UN'ALTRA CANZONE!",
+ "SUPPONGO CHE ORA POSSA DARTI I MIEI TAPPI",
},
};
@@ -5316,34 +5564,34 @@ const char *_textt[NUM_LANGS][NUM_TEXTT] = {
{
// 0
"",
- "CHE SUCCEDE, CHE SUCCEDE?",
+ "CHE C'\324, CHE C'\324?",
"D'ACCORDO. CAMERA 512. DEVE SALIRE LE SCALE. LA CHIAVE \324 NELLA PORTA",
- "IL CONDE DRASCULA?",
- "NO, NIENTE. QUEL TIZIO HA MALA REPUTAZIONE QU\336",
+ "IL CONTE DRASCULA?!",
+ "NO, NIENTE. \324 SOLO CHE QUEL TIPO HA UNA CATTIVA REPUTAZIONE QUI",
// 5
- "SE DICONO MOLTE COSE SU LUI. COME CH'\324 UN VAMPIRO E SEQUESTRA GENTE PER BERE LA SUA SANGUE",
- "ALTRI DICONO CHE SOLO \324 UN TRAFFICANTE DI ORGANI, PER QUELLO TROVIAMO GENTE SQUARTATA FUORI LE MURA",
- "SONO SOLTANTO CHIACCHIERE. FORSE SIA LE DUE COSE. MA, PERCHE VUOLE TROVARE QUEL TIZIO?",
- "NO, HO MOLTO DA FARE..",
- "VA BENE, MA PERCHE VOGLIO IO, NON PERCHE L'ABBIA DETTO TU",
+ "BEH, CORRONO MOLTE VOCI SUL SUO CONTO. ALCUNI DICONO CHE \324 UN VAMPIRO E RAPISCE LE PERSONE PER SUCCHIAR LORO IL SANGUE",
+ "COMUNQUE, ALTRI DICONO CHE \324 SOLO UN TRAFFICANTE DI ORGANI, ED \324 PER QUESTO CHE SI TROVANO CORPI SQUARTATI NELLE VICINANZE",
+ "CHIARAMENTE SONO SOLTANTO VOCI. \324 PI\353 PROBABILE CHE SIA ENTRAMBE LE COSE. A PROPOSITO, PERCH\220 VUOLE INCONTRARE QUEL TIPO?",
+ "NO, LASCIA PERDERE. HO MOLTO DA FARE...",
+ "VA BENE, OK. MA PERCH\220 LO VOGLIO IO, NON PERCH\220 L'HAI DETTO TU",
// 10
- "ADESSO VINCONO",
- "LASCIAMI IN PACE, O.K.?",
+ "STANNO VINCENDO",
+ "LASCIAMI IN PACE, OK?",
"CERTO, NON SONO CIECO",
- "C'\324 LA TRADIZIONE NEL PAESE DI DIMENTICARE I RANCORI QUANDO C'\324 PARTITA DI CALCIO; PER ANIMARE LA SELEZIONE",
- "TI HO DETTO DI STARE ZITTO, NON RIESCO A SENTIRE",
+ "IN PAESE C'\324 L'USANZA DI DIMENTICARE I RANCORI QUANDO C'\324 UNA PARTITA, PER SOSTENERE LA SQUADRA LOCALE",
+ "E STAI ZITTO UNA BUONA VOLTA. NON RIESCO A SENTIRE",
// 15
- "LASCIAMI IN PACE E NON MI DISTURBARE",
- "\324 APPENA COMINCIATO, ZITTO!",
- "AH, BENE. HO PENSATO CHE SUCCEDEVA QUALCOSA",
- "NO, NON FA NIENTE. ADESSO SICURO CH'\324 GI\267 MORTA",
- "SI \324 MESSO A SUONARE MUSICA CLASSICA ED IO LA ODIO",
+ "INSOMMA, LASCIAMI IN PACE E NON MI DISTURBARE PI\353",
+ "\324 APPENA INIZIATA! STAI ZITTO!",
+ "AH, OK. CREDEVO CHE FOSSE SUCCESSO QUALCOSA",
+ "NO, \324 INUTILE. PROBABILMENTE A QUEST'ORA SAR\267 GI\267 MORTA",
+ "\324 CHE SI \324 MESSO A SUONARE MUSICA CLASSICA. E IO NON LA SOPPORTO",
// 20
- "\324 COME FACCIO PER SENTIRE QUELLO CHE VOGLIO SE L'HO LICENZIATO",
- "E ORA SI METTE BULLO...-E SEMBRAVA PROPRIO SCEMO!",
- "...SENTA! FACCIA ATTENZIONE. IL PAVIMENTO \324 APPENA INCERATO",
- "ZITTO! - STIAMO GUARDANDO LA PARTITA!",
- "DAI! PRENDI",
+ "E SICCOME LO PAGO PERCH\220 SUONI QUELLO CHE VOGLIO IO, L'HO LICENZIATO",
+ "E POI SI \324 MESSO A FARE IL BULLO... SEMBRAVA COS\326 INNOCUO PRIMA, CHE IPOCRITA!",
+ "...A PROPOSITO, FACCIA ATTENZIONE. HO APPENA PASSATO LA CERA",
+ "SILENZIO! STIAMO GUARDANDO LA PARTITA!",
+ "DAI, FORZA! PRENDI.",
},
};
@@ -5664,80 +5912,80 @@ const char *_textvb[NUM_LANGS][NUM_TEXTVB] = {
{
// 0
"",
- "MA CHI BUSSA A QUESTE ORE?",
- "EH...NO,NO. IO SONO IL NANNO GANIMEDI....IL PROFESSORE VON BRAUN NON ABITA QU\336 PI\353",
+ "CHI DIAVOLO \324 A QUEST'ORA?",
+ "OH... NO, NO. IO SONO IL NANO GANIMEDE... IL PROFESSOR VON BRAUN NON VIVE PI\353 QUI",
"NO, NON SO DOV'\324!",
- "HO DETTO VIA!",
+ "VATTENE!",
// 5
- "IMBECILE. ORMAI TROPPO TARDE, SEMRE TARDE",
- "SONO COMPLETAMENTE D'ACCORDO",
+ "IMBECILLE! ORMAI \324 TROPPO TARDI, LO \324 SEMPRE",
+ "SONO TOTALMENTE D'ACCORDO",
"IO, PAURA?",
- "ASCOLTA BENE RAGAZZO: STAI PARLANDO CON L'UNICA PERSONA CHE CONOSCE IL SEGRETO PER VINCERE AI VAMPIRI",
- "NON TUTTI QUANTI POSSONO LOTTARE CON UN VAMPIRO. SI DEVONO AVERE DELLE CARATTERISTICHE SPEZIALI",
+ "ASCOLTA BENE, RAGAZZO: STAI PARLANDO CON L'UNICA PERSONA CHE CONOSCE IL SEGRETO PER AFFRONTARE I VAMPIRI",
+ "NON TUTTI POSSONO COMBATTERE CONTRO UN VAMPIRO. BISOGNA AVERE DELLE QUALIT\267 SPECIALI",
// 10
- "NO CE LE HAI",
- "SICURO CHE NON SCOMMETI TUTTO IL TUO SOLDI!",
- "VA BENE . AVANTI",
- "SE DAVVERO SEI PRONTO PER LOTTARE CONTRO DRASCULA, DEVI POTERE SOPPORTARE TUTTI I RUMORI STRIDENTI E VAMPIRICI",
- "TUTTO CHIARO?",
+ "E TU NON LE POSSIEDI",
+ "SCOMMETTERESTI TUTTI I TUOI SOLDI?",
+ "VA BENE. ENTRA",
+ "SE DAVVERO INTENDI AFFRONTARE DRASCULA, DEVI ESSERE IN GRADO DI SOPPORTARE TUTTI I RUMORI PI\353 STRIDENTI E VAMPIRICI",
+ "\324 CHIARO?",
// 15
- "D'ACCORDO. ASPETTA UN ATTIMO",
- "PER FAVORE, METTETI NEL CENTRO DELLA CAMERA",
- "DOV'\324 HO MESSO IL COMPACT DISC DI \"UNGHIE GRAFFIANDO UNA LAVAGNA\"",
- "MOLTO BENE, ANDIAMO",
- "VEDI? SEI UN INUTILE, COME TUTTI GLI ALTRI",
+ "D'ACCORDO. ASPETTA UN MOMENTO",
+ "PER FAVORE, METTITI AL CENTRO DELLA STANZA",
+ "DOV'\324 CHE HO MESSO IL CD DI \"UNGHIE CHE GRAFFIANO LA LAVAGNA\"?",
+ "MOLTO BENE. SI COMINCIA",
+ "VEDI? SEI UN INCAPACE, COME TUTTI GLI ALTRI",
// 20
- "ORA DAMI IL SOLDI CHE HAI PERSO, E VIA",
- "E NON TORNARE FINO CHE NON SIA COMPLETAMENTE PRONTO",
- "E COSA VUOI TU ADESSO?",
- "DEVO AMMETTERLO... HAI LA STOFFA DI LOTTATORE PER VINCERE DRASCULA",
- "EH..! PRENDI IL TUO SOLDI. SO QUANDO HO SBAGLIATO",
+ "ORA DAMMI I SOLDI CHE HAI PERSO E VATTENE",
+ "E NON TORNARE FINCH\220 NON SARAI COMPLETAMENTE PRONTO",
+ "CHE COSA VUOI ADESSO?",
+ "DEVO RICONOSCERLO... HAI LA STOFFA PER COMBATTERE I VAMPIRI",
+ "A PROPOSITO, PRENDI I TUOI SOLDI. SO RICONOSCERE I MIEI ERRORI",
// 25
- "ADESSO VATENE, VOGLIO DORMIRE UN P\343",
- "QUANDO SIA DISPOSTO A UCCIDERE QUALCHE VAMPIRO, TORNA E TI AIUTER\343 ",
- "QUELLO \324 FACILE. LA LUCE DEL SOLE O UN CROCIFISSO, E L'HAI SCHISCCIATO",
- "CON CHI DEVI FARE MOLTA ATTENZIONE \324 CON DRASCULA. I SUOI POTERI FRISISHNOSTICI GLI FANNO IL PI\353 FORTE DEI VAMPIRI",
- "NON POTREI FARE NULLA SE NON FOSSE PER LA .....",
+ "ADESSO VATTENE, VOGLIO DORMIRE UN PO'",
+ "QUANDO SARAI PRONTO AD AFFRONTARE UN VAMPIRO, TORNA E TI AIUTER\343 COME POSSO",
+ "OH, \324 FACILE. BASTA LA LUCE DEL SOLE O UN CROCIFISSO PER INCENERIRLO",
+ "DEVI INVECE STARE MOLTO ATTENTO A DRASCULA. I SUOI POTERI FRISISNOTICI LO RENDONO IL PI\353 POTENTE DEI VAMPIRI",
+ "SARESTI SPACCIATO, SE NON FOSSE PER LA...",
// 30
"...POZIONE!",
- "CERTO. HAI RAGIONE, SE CONTINUO DORMENDO COS\336 FORSE AVR\343 PROBLEMI DI SCHIENA QUANDO SIA VECCHIO",
- "BENE, \324 VERO CHE FU MEGLIO LOTTATORE DI ME, MA IL MIO STUDIO SU TECNICHE ANTI-VAMPIRI GLI AIUT\343 MOLTISSIMO",
- "HO SCOPERTO UNA POZIONE DI IMMUNUT\267 . TI FA INVULNERABILE AI MORSI DI VAMPIRI, O AI SUOI POTERI FRISISHNOTICI",
- "NO, SCUSA, CE L'EBBI MOLTO TEMPO FA, MA UNA POZIONE COM'ERA LA MIA \324 PERICOLOSA. FIGURATI SE LA AVESSE UN VAMPIRO",
+ "OH, CERTO, HAI RAGIONE! SE CONTINUO A DORMIRE COS\326, FORSE AVR\343 PROBLEMI ALLA SCHIENA QUANDO SAR\343 VECCHIO",
+ "BEH, AMMETTO CHE SI \324 RIVELATO PI\353 FORTE DI ME, MA LA MIA PRINCIPALE SCOPERTA SULLE TECNICHE ANTI-VAMPIRO MI HA COPERTO LE SPALLE",
+ "HO SCOPERTO UNA POZIONE DI IMMUNIT\267 CHE TI RENDE INVULNERABILE A QUALUNQUE MORSO DI VAMPIRO, O AI SUOI POTERI FRISISNOTICI",
+ "NO, MI DISPIACE. CE L'AVEVO UNA VOLTA, MA UNA POZIONE CON QUELLE CARATTERISTICHE \324 PERICOLOSA. IMMAGINA SE CADESSE NELLE MANI DI UN VAMPIRO",
// 35
- "GLI FAREBBE IMMUNE AGLI AGLII, ALLA LUCE DEL SOLE.... PER QUELLO L'HO SCARICATA NEL CESO",
- "TRANQUILLO, MI RICORDO BENISSIMO DI COME RIFARLA",
- "BISOGNO AGLII, CHE NE HO QU\326, DOVRAI PORTARMI UN P\220 DI CERA, NICOTINA, UNA GOMMA, E UNA CARTINA O UN TOVAGLIOLO, O QUALCOSA DEL GENERE",
- "-AH! E COME NO, L'INGREDIENTE PRINCIPALE: DELLE FOGLIE DI UNA STRANA PIANTA CHIAMATA FERDINAN",
- "\324 UNA PIANTA CONVOLVOLO, LE SUE FOGLIE PROPORZIONANO POTERI MAGICI SE SONO TAGLIATE DA UNA FALCE D'ORO",
+ "LO RENDEREBBE IMMUNE ALL'AGLIO E ALLA LUCE DEL SOLE... COS\326 MI SONO LIBERATO DI QUELLA CHE NON HO USATO CON UN METODO ALTAMENTE SCIENTIFICO: GETTANDOLA NELLA TAZZA DEL WATER",
+ "TRANQUILLO, MI RICORDO PERFETTAMENTE COME PREPARARE QUELLA POZIONE",
+ "HO BISOGNO DI AGLIO, CHE HO GI\267 QUI. PER\343 DOVRAI PORTARMI UN PO' DI CERA, DELLA NICOTINA, UNA GOMMA E UNA CARTINA DI SIGARETTA, O UN TOVAGLIOLO O QUALCOSA DEL GENERE",
+ "AH! E, OVVIAMENTE, L'INGREDIENTE PRINCIPALE: LE FOGLIE DI UNA STRANA PIANTA CHIAMATA FERNAN",
+ "SI TRATTA DI UNA PIANTA RAMPICANTE LE CUI FOGLIE ACQUISTANO POTERI MAGICI SE VENGONO TAGLIATE CON UNA FALCE D'ORO",
// 40
- "ALLORA, PORTAMI QUESTE CINQUE COSE E FAR\343 PER TE LA POZIONE",
- "DOPO SAREI PRONTO PER UCCIDERE DRASCULA",
- "RICORDA: CERA, NICOTINA, UNA GOMMA, UNA CARTINA E FOGLIE DI FERDINAN, LA PIANTA, TAGLIATE DA UNA FALCE D'ORO",
- "TI L'HO GI\267 DETTO! FU TUTTO GRAZIE ALLA POZIONE",
- "AH, MOLTO BENE. DUNQUE VADO A FARE LA CAN......LA POZIONE. SAR\267 UN ATTIMINO",
+ "ALLORA, QUANDO AVRAI QUESTE CINQUE COSE, PORTAMELE E TI PREPARER\343 LA POZIONE",
+ "DOPO SARAI PRONTO PER AFFRONTARE DRASCULA",
+ "RICORDA: CERA, NICOTINA, UNA GOMMA, UNA CARTINA E DELLE FOGLIE DI FERNAN, LA PIANTA, TAGLIATE CON UNA FALCE D'ORO",
+ "TE L'HO GI\267 DETTO! FU MERITO DELLA POZIONE",
+ "AH, MOLTO BENE. ALLORA VADO A FARMI LA CAN... LA POZIONE. DAMMI UN MINUTO, OK?",
// 45
- "\324 SOLTANTO UN SORTILEGIO DI PROTEZIONE CONTRO VAMPIRI",
- "L'HO MESSO PER DISSIMULARE CHE IL DISEGNATORE HA DIMENTICATO METTERE LA FINESTRA CHE SI VEDE DA FUORI",
- "BENE, PRIMA DEVI SAPERE COME ARRIVARE AL CASTELLO DRASCULA",
- "C'\324 UNAGROTTA CHE VA AL CASTELLO E CHE UTILIZZA QUEL MATTO FAN DI ELVIS, IGOR, PER SCENDERE AL PAESE TUTTE LA MATTINE",
- "MA FA ATTENZIONE, SEMPRE \220 PROTETTA DA UN VAMPIRO. DOVRAI LIBERARTI DI LUI",
+ "\324 UN INCANTESIMO DI PROTEZIONE CONTRO I VAMPIRI",
+ "L'HO MESSA L\326 PER NASCONDERE IL FATTO CHE IL DISEGNATORE HA DIMENTICATO DI METTERE LA FINESTRA CHE SI VEDE DA FUORI",
+ "BENE, LA PRIMA COSA CHE DEVI SAPERE \324 COME ARRIVARE AL CASTELLO DI DRASCULA",
+ "C'\324 UNA GROTTA CHE PORTA DIRETTAMENTE AL CASTELLO. QUEL MATTO FAN DI ELVIS, IGOR, LA USA PER SCENDERE AL PAESE TUTTE LA MATTINE",
+ "MA FA' ATTENZIONE, \324 SEMPRE PROTETTA DA UN VAMPIRO. DOVRAI LIBERARTI DI LUI",
// 50
- "C'\220 UN VECCHIO POZZO ACCANTO ALLA CAPELLA DEL CIMITERO",
- "SI UTILIZZAVA MOLTO TEMPO FA PER GIUDICARE CASI DI STREGONERIA",
- "SI BUTTAVANO DENTRO ALLE STREGE. SE SI AFFONDAVANO ERANO STREGHE. SE NO, NO",
- "UNA VOLTA BUTTAMMO UNA E GALLEGGI\220, DUNQUE NON SAREBBE UNA STREGA",
- "ORA BEVE LA POZIONE. PECCATO CI SIA SOLTANTO PER UNO",
+ "C'\324 UN VECCHIO POZZO ACCANTO ALLA CAPPELLA DEL CIMITERO",
+ "SI USAVA ANTICAMENTE PER GIUDICARE I CASI DI STREGONERIA",
+ "SI BUTTAVANO LE STREGHE NEL POZZO. SE AFFONDAVANO ERANO STREGHE. SE NO, NO",
+ "UNA VOLTA NE BUTTAMMO GI\353 UNA E NON AFFOND\343. SUPPONGO NON FOSSE UNA STREGA.",
+ "AD OGNI MODO. PRENDI LA POZIONE. BASTA PER UNA VOLTA SOLA",
// 55
- "SAR\265 MEGLIO FUMARLO PROPRIO PRIMA DELLA LOTTA CONTRO DRASCULA",
- "CORRI1",
- "SCUSE!",
- "JOHN HACKER? SONO IL DOTTORE VON BRAUN",
- "SENTA, \220 MOLTO IMPORTANTE, \220 SULLA POZIONE",
+ "\324 MEGLIO CHE LA FUMI APPENA PRIMA DI AFFRONTARE DRASCULA",
+ "CORRI!",
+ "SCUSI!",
+ "JOHN HACKER? SONO IL DOTTOR VON BRAUN",
+ "ASCOLTA, \324 MOLTO IMPORTANTE. RIGUARDA LA POZIONE",
// 60
- "HO TROVATO UN LIBRO SU POZIONI E DICE CHE NON SI DEVE BERE ALCOL DOPO AVERE FUMATO LA POZIONE",
- "L'ALCOL BEVUTO FA REAZIONE CON LE SOSTANZE DELLA POZIONE E ANNULLA I SUOI EFFETTI IN DECIME DI SECONDO",
- "DEVO RIATTACARE. LA POLIZIA MI CERCA. DICONO CHE TRAFFICO DROGHE -IGNORANTI! BENE, ALLORA ADIO E IN BOCA IL LUPO",
+ "STAI ZITTO E LASCIAMI PARLARE. HO TROVATO UN LIBRO SULLE POZIONI E DICE CHE NON SI DEVE BERE ALCOL DOPO AVERE FUMATO LA POZIONE",
+ "L'ALCOL INGERITO REAGISCE CON LE SOSTANZE DELLA POZIONE E ANNULLA I SUOI EFFETTI IN POCHI SECONDI",
+ "MI DISPIACE, MA DEVO RIATTACCARE. LA POLIZIA MI CERCA. DICONO CHE SONO UNO SPACCIATORE. IGNORANTI! BEH, ADDIO E BUONA FORTUNA NEL SALVARE IL MONDO",
},
};
@@ -5768,10 +6016,10 @@ const char *_textsys[NUM_LANGS][NUM_TEXTSYS] = {
"VOIX ET TEXT",
},
{
- "PREMI DI NUOVO SUPR PER COMINZIARE",
- "PRMI DI NUOVO ESC PER USCIRE",
- "SOLO SUONI",
- "SUONI E TESTO",
+ "PREMI DI NUOVO CANC PER RICOMINCIARE",
+ "PREMI DI NUOVO ESC PER USCIRE",
+ "SOLO VOCI",
+ "VOCI E TESTO",
},
};
@@ -5807,10 +6055,10 @@ const char *_texthis[NUM_LANGS][NUM_TEXTHIS] = {
},
{
"",
- "",
- "",
- "",
- ""
+ "RACCONTANO CHE, MOLTI ANNI FA, DRASCULA UCCISE LA MOGLIE DI VON BRAUN. DA ALLORA, CON L'INTENZIONE DI AFFRONTARE IL CONTE, VON BRAUN COMINCI\343 A STUDIARE TUTTO QUELLO CHE TROVAVA SUI VAMPIRI.",
+ "QUANDO PENS\343 DI ESSERE PRONTO, AND\343 AL CASTELLO ED EBBE UN VIOLENTO SCONTRO CON DRASCULA.",
+ "NESSUNO SA COSA ACCADDE LASS\353. MA SEBBENE VON BRAUN FU SCONFITTO, DRASCULA NON RIUSC\326 A UCCIDERLO.",
+ "UMILIATO DALLA SCONFITTA, VON BRAUN SCAPP\343 DAL CASTELLO E DA ALLORA NON HA MAI PI\353 OSATO AFFRONTARE DRASCULA.",
},
};
@@ -5934,7 +6182,7 @@ const char *_textverbs[NUM_LANGS][NUM_TEXTVERBS] = {
"poussez",
},
{
- "esamina",
+ "guarda",
"prendi",
"apri",
"chiudi",
@@ -5966,9 +6214,9 @@ const char *_textmisc[NUM_LANGS][NUM_TEXTMISC] = {
"GOOOOOOOAAAAAAAL!",
},
{
- "HUNCHBACKED",
- "Transilvania, 1993 d.c.",
- "GOOOOOOOAAAAAAAL!",
+ "GOBBO",
+ "Transilvania, 1993 d.c. (dopo cena)",
+ "GOOOOOOOOOOOOOOOL!",
},
};
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index 78de2b6bce..c69c38199a 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -31,7 +31,7 @@
#include "md5.h"
enum {
- kKyraDatVersion = 31,
+ kKyraDatVersion = 32,
kIndexSize = 12
};
diff --git a/tools/create_kyradat/hof_floppy.h b/tools/create_kyradat/hof_floppy.h
index e2709eb3fd..e61f43fb2c 100644
--- a/tools/create_kyradat/hof_floppy.h
+++ b/tools/create_kyradat/hof_floppy.h
@@ -28,6 +28,16 @@ const ExtractEntry kyra2File1G[] = {
{ -1, 0, 0 }
};
+const ExtractEntry kyra2File1I[] = {
+ { k2SeqplayPakFiles, 0x00021189, 0x000211B7 },
+ { k2SeqplayStrings, 0x00022C62, 0x0002352A },
+ { k2SeqplaySfxFiles, 0x0002352A, 0x0002369D },
+ { k2SeqplayIntroTracks, 0x000236AA, 0x000236AA },
+ { k2SeqplayFinaleTracks, 0x000236C7, 0x000236D9 },
+ { k2SeqplaySeqData, 0x00022250, 0x00022944 },
+ { -1, 0, 0 }
+};
+
const ExtractEntry kyra2File2E[] = {
{ k2IngamePakFiles, 0x0035E4E, 0x00362ED },
{ k2IngameSfxFiles, 0x00034700, 0x00034DF1 },
@@ -58,12 +68,24 @@ const ExtractEntry kyra2File2G[] = {
{ -1, 0, 0 }
};
+const ExtractEntry kyra2File2I[] = {
+ { k2IngamePakFiles, 0x00036816, 0x00036CB5 },
+ { k2IngameSfxFiles, 0x000350C6, 0x000357B7 },
+ { k2IngameSfxIndex, 0x0002AB80, 0x0002AED8 },
+ { k2IngameTracks, 0x0003BE78, 0x0003BEF6 },
+ { k2IngameTalkObjIndex, 0x00034872, 0x000348EA },
+ { k2IngameItemAnimData, 0x0003C4E2, 0x0003C82A },
+ { -1, 0, 0 }
+};
+
const Game kyra2FloppyGames[] = {
{ kKyra2, EN_ANY, k2FloppyFile1, "9b0f5e57b5a2ed88b5b989cbb402b6c7", kyra2File1E},
{ kKyra2, FR_FRA, k2FloppyFile1, "df31cc9e37e1cf68df2fdc75ddf2d87b", kyra2File1F},
{ kKyra2, DE_DEU, k2FloppyFile1, "0ca4f9a1438264a4c63c3218e064ed3b", kyra2File1G},
+ { kKyra2, IT_ITA, k2FloppyFile1, "178d3ab913f61bfba21d2fb196405e8c", kyra2File1I},
{ kKyra2, EN_ANY, k2FloppyFile2, "7c3eadbe5122722cf2e5e1611e19dfb9", kyra2File2E},
{ kKyra2, FR_FRA, k2FloppyFile2, "fc2c6782778e6c6d5a553d1cb73c98ad", kyra2File2F},
{ kKyra2, DE_DEU, k2FloppyFile2, "0d9b0eb7b0ad889ec942d74d80dde1bf", kyra2File2G},
+ { kKyra2, IT_ITA, k2FloppyFile2, "3a61ed6b7c00ddae383a0361799e2ba6", kyra2File2I},
GAME_DUMMY_ENTRY
};
diff --git a/tools/create_kyradat/pak.h b/tools/create_kyradat/pak.h
index a90b930fcc..1e0fd2c72f 100644
--- a/tools/create_kyradat/pak.h
+++ b/tools/create_kyradat/pak.h
@@ -35,7 +35,7 @@ public:
bool saveFile(const char *file);
void clearFile() { delete _fileList; _fileList = 0; }
- const uint32 getFileSize() const { return _fileList->getTableSize()+5+4+_fileList->getFileSize(); }
+ uint32 getFileSize() const { return _fileList->getTableSize()+5+4+_fileList->getFileSize(); }
void drawFileList();
diff --git a/tools/credits.pl b/tools/credits.pl
index d1a73ab9fb..45351146c2 100755
--- a/tools/credits.pl
+++ b/tools/credits.pl
@@ -660,9 +660,10 @@ begin_credits("Credits");
end_section();
begin_section("Miscellaneous");
- add_person("David Corrales-Lopez", "david_corrales", "Filesystem access improvements");
+ add_person("David Corrales-Lopez", "david_corrales", "Filesystem access improvements (GSoC 2007 task)");
add_person("Jerome Fisher", "KingGuppy", "MT-32 emulator");
add_person("Jochen Hoenicke", "hoenicke", "Speaker &amp; PCjr sound support, Adlib work");
+ add_person("Chris Page", "cp88", "Return to launcher, savestate improvements, leak fixes, ... (GSoC 2008 task)");
add_person("Robin Watts", "robinwatts", "ARM assembly routines for nice speedups on several ports; improvements to the sound mixer");
end_section();
end_section();
diff --git a/tools/md5table.c b/tools/md5table.c
index 3f85ac338b..c8f7eb9e09 100644
--- a/tools/md5table.c
+++ b/tools/md5table.c
@@ -85,6 +85,7 @@ static const StringMap platformMap[] = {
{ "PC-Engine", "kPlatformPCEngine" },
{ "SEGA", "kPlatformSegaCD" },
{ "Windows", "kPlatformWindows" },
+ { "Wii", "kPlatformWii" },
{ "All?", "kPlatformUnknown" },
{ "All", "kPlatformUnknown" },
diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt
index 4da978914d..0ce6ded8a3 100644
--- a/tools/scumm-md5.txt
+++ b/tools/scumm-md5.txt
@@ -402,6 +402,7 @@ brstorm Bear Stormin'
thinker1 Big Thinkers First Grade
5c21fc49aee8f46e58fef21579e614a1 -1 us All - - - Kirben
+ 632d2fddb8ba97723fa15334763ae857 33270 en Windows - - - George Kormendi
0f5935bd5e88ba6f09e558d64459746d 30919 us Windows - Demo - khalek
@@ -436,8 +437,11 @@ readtime Blue's Reading Time Activities
95818b178d473c989ac753574e8892aa -1 en All - Demo - Kirben
fbear Fatty Bear's Birthday Surprise
+ 13d2a86a7290813a1c386490447d72db -1 en 3DO HE 61 - - George Kormendi
5b08000a9c47b2887df6506ac767ca68 -1 en 3DO HE 61 - - sev
+ 6bca7a1a96d16e52b8f3c42b50dbdca3 -1 jp 3DO HE 61 - - George Kormendi
3824e60cdf639d22f6df92a03dc4b131 7732 en DOS HE 61 - - khalek
+ 4f1d6f8b38343dba405472538b5037ed 7717 en DOS HE 61 - - George Kormendi
ef74d9071d4e564b037cb44bd6774de7 -1 hb DOS HE 61 - - sev
3df6ead57930488bc61e6e41901d0e97 -1 en Mac HE 61 - - khalek
179879b6e35c1ead0d93aab26db0951b 13381 en Windows HE 70 - - khalek
@@ -465,6 +469,7 @@ freddi Freddi Fish 1: The Case of the Missing Kelp Seeds
e44ea295a3f8fe4f41983080dab1e9ce -1 fr Mac HE 90 Updated - ThierryFR
746e88c172a5b7a1ae89ac0ee3ee681a -1 ru Windows HE 90 Updated - sev
a197a87ae77f3b3333f09a7a2c448fe2 -1 en Windows HE 99 Updated - Jonathan
+ 57a5cfec9ef231a007043cc1917e8988 -1 en Wii HE 100 - - sanguinehearts
084ed0fa98a6d1e9368d67fe9cfbd417 -1 en Windows HE 71 Demo - khalek
c8aac5e3e701874e2fa4117896f9e1b1 -1 en Mac HE 73 Demo - khalek, sev
@@ -516,6 +521,7 @@ freddi4 Freddi Fish 4: The Case of the Hogfish Rustlers of Briny Gulch
7c2e76087027eeee9c8f8985f93a1cc5 13584 en All - Demo - khalek
c25755b08a8d0d47695e05f1e2111bfc -1 us All - Demo - sev
+ fa84cb1018103a4ee4e5fa8041c1d0d1 13609 de Windows - Demo - George Kormendi
ebd324dcf06a4c49e1ba5c231eee1060 -1 us All HE 99 Demo - sev
688328c5bdc4c8ec4145688dfa077bf2 -1 de All HE 99 Demo - Joachim Eberhard
03d3b18ee3fd68114e2a687c871e38d5 -1 us Windows HE 99 Mini Game - eriktorbjorn
@@ -553,6 +559,7 @@ FreddisFunShop Freddi Fish's One-Stop Fun Shop
catalog Humongous Interactive Catalog
11e6e244078ff09b0f3832e35420e0a7 -1 en Windows - Demo - khalek, sev
037385a953789190298494d92b89b3d0 -1 en Windows HE 72 Demo - khalek, sev
+ 74da3494fbe1a7d20213b0afe0954755 10841544 fr All HE CUP Preview - George Kormendi
4c4820518e16e1a0e3616a3b021a04f3 10927456 de All HE CUP Preview - Kirben
airport Let's Explore the Airport with Buzzy
@@ -566,7 +573,9 @@ airport Let's Explore the Airport with Buzzy
farm Let's Explore the Farm with Buzzy
fbbbb38a81fc9d6a61d509278390a290 -1 en Mac - - - khalek
+ a5c5388da9bf0e6662fdca8813a79d13 86962 en Windows - - - George Kormendi
a85856675429fe88051744f755b72f93 -1 en Windows - - - Kirben
+ a2386da005672cbd5136f4f27a626c5f 87061 nl Windows - - - George Kormendi
39fd6db10d0222d817025c4d3346e3b4 -1 en Mac - Demo - Joachim Eberhard
bf8b52fdd9a69c67f34e8e9fec72661c -1 en Windows HE 71 Demo - khalek, sev
@@ -586,10 +595,12 @@ pajama Pajama Sam 1: No Need to Hide When It's Dark Outside
37aed3f91c1ef959e0bd265f9b13781f -1 us All HE 100 Updated - Kirben
782393c5934ecd0b536eaf5fd541bd26 -1 en Windows HE 100 Updated - Jonathan
4aa93cb30e485b728504ba3a693f12bf -1 ru Windows HE 100 - - sev
+ c225bec1b6c0798a2b8c89ac226dc793 -1 en Wii HE 100 - - sanguinehearts
f237bf8a5ef9af78b2a6a4f3901da341 18354 en All - Demo - khalek, sev
7f945525abcd48015adf1632637a44a1 -1 fr All - Demo - Kirben
0305e850382b812fec6e5998ef88a966 -1 nl Windows - Demo - adutchguy
+ 87df3e0074624040407764b7c5e710b9 18354 nl Windows - Demo - George Kormendi
d7ab7cd6105546016e6a0d46fb36b964 -1 en All HE 100 Demo - khalek
pajama2 Pajama Sam 2: Thunder and Lightning Aren't so Frightening
@@ -621,6 +632,7 @@ pajama3 Pajama Sam 3: You Are What You Eat From Your Head to Your Feet
4fe6a2e8df3c4536b278fdd2fbcb181e -1 en Windows - Mini Game - Trekky
679855cf61932f9bf995c8f3677380ed -1 fr Windows - Demo - Mevi
c8c5baadcbfc8d0372ed4335abace8a7 -1 fr Windows - Demo - Mevi
+ 784b499c98d07260a30952685758636b 13911 de Windows - Demo - George Kormendi
3e48298920fab9b7aec5a971e1bd1fab -1 gb Windows - Demo - eriktorbjorn
cf90b4db5486ef798db78fe6fbf897e5 -1 us Windows - Demo - khalek
@@ -658,12 +670,14 @@ puttrace Putt-Putt Enters the Race
aaa587701cde7e74692c68c1024b85eb -1 nl All HE 99 Demo - joostp
0bf1a3eb198ca1bd2ebe104825cec770 -1 fr Windows HE 99 Demo - Mevi
c8575e0b973ff1723aba6cd92c642db2 -1 fr Windows HE 99 Demo - Mevi
+ 3769b56c9a22f5521d74525ee459f88d 13108 de Windows HE 99 Demo - George Kormendi
7c8100e360e8ef05f88069d4cfa0afd1 13108 gb Windows HE 99 Demo - eriktorbjorn
6b27dbcd8d5697d5c918eeca0f68ef6a 3901484 All All HE CUP Preview - sev
puttmoon Putt-Putt Goes to the Moon
a9543ef0d79bcb47cd76ec197ad0a967 -1 en 3DO - - - sev
780e4a0ae2ff17dc296f4a79543b44f8 -1 All DOS - - - khalek
+ b9bb68c5d2c9b6e2d9c513a29a754a57 7828 en DOS - - - George Kormendi
697c9b7c55a05d8199c48b48e379d2c8 -1 hb DOS - - - sev
9dc02577bf50d4cfaf3de3fbac06fbe2 -1 en Mac - - - khalek
9c92eeaf517a31b7221ec2546ab669fd -1 en Windows HE 70 - - khalek
@@ -685,9 +699,11 @@ puttcircus Putt-Putt Joins the Circus
3af61c5edf8e15b43dbafd285b2e9777 -1 hb Windows - Demo - Ori Avtalion
puttputt Putt-Putt Joins the Parade
+ 7766c9487f9d53a8cb0edabda5119c3d 8022 en DOS HE 60 - - George Kormendi
0b3222aaa7efcf283eb621e0cefd26cc -1 ru DOS HE 60 - - sev
7e151c17adf624f1966c8fc5827c95e9 -1 en 3DO HE 61 - - khalek
be2abe172f58db170de3a037daa1dd27 -1 jp 3DO HE 61 - - clone2727
+ ee41f6afbc5b26fa475754b56fe92048 8032 jp 3DO HE 61 - - George Kormendi
9708cf716ed8bcc9ff3fcfc69413b746 -1 en DOS HE 61 - - khalek
e361a7058ed8e8ebb462663c0a3ae8d6 -1 hb DOS HE 61 - - sev
684732efb5799c0f78804c99d8de9aba -1 en Mac HE 61 - - khalek
@@ -703,6 +719,7 @@ puttzoo Putt-Putt Saves the Zoo
1005456bfe351c1b679e1ff2dc2849e9 -1 All Windows - - - khalek
c3b22fa4654bb580b20325ebf4174841 -1 nl Windows - - - joostp
9781422e4288dbc090720e4563168ba7 -1 fr Windows - - - gist974
+ 0f9d3317910ac7a9f449243118884ada 42070 de Windows - - - George Kormendi
92e7727e67f5cd979d8a1070e4eb8cb3 -1 en All HE 98.5 Updated - cyx
3a3e592b074f595489f7f11e150c398d -1 us Windows HE 99 Updated - Adrian
@@ -734,13 +751,16 @@ PuttTime Putt-Putt Travels Through Time
balloon Putt-Putt and Pep's Balloon-O-Rama
08cc5c3eedaf72ebe12734eee94f7fa2 -1 en All HE 80 - - Kirben
+ bab0fb81dcb12b8930c5d850b8f2a7de 12800 de Windows HE 80 - - George Kormendi
145bd3373574feb668cc2eea2ec6cf86 -1 ru Windows HE 80 - - sev
2232b0b9411575b1f9961713ebc9de61 -1 es Windows HE 80 - - exiltd
d7b247c26bf1f01f8f7daf142be84de3 -1 en Windows HE 99 Updated - iziku
8e3241ddd6c8dadf64305e8740d45e13 -1 en All HE 100 Updated - Kirben
dog Putt-Putt and Pep's Dog on a Stick
+ bd5fd7835335dfce03064d5f77b7f0ae 19681 nl Windows - - - George Kormendi
eae95b2b3546d8ba86ae1d397c383253 -1 en All - - - Kirben
+ 839a658f7d22de00787ebc945348cdb6 19681 de Windows - - - George Kormendi
d4b8ee426b1afd3e53bc0cf020418cf6 -1 en Windows HE 99 - - sev
activity Putt-Putt & Fatty Bear's Activity Pack
@@ -769,6 +789,7 @@ spyfox SPY Fox 1: Dry Cereal
72ac6bc980d5101c2142189d746bd62f -1 ru Windows HE 99 - - sev
3de99ef0523f8ca7958faa3afccd035a -1 us All HE 100 Updated - Kirben
23394c8d29cc63c61313959431a12476 -1 en Windows HE 100 Updated - Jonathan
+ 50b831f11b8c4b83784cf81f4dcc69ea -1 en Wii HE 100 - - sanguinehearts
53e94115b55dd51d4b8ff0871aa1df1e 20103 en All - Demo - khalek, sev
fbdd947d21e8f5bac6d6f7a316af1c5a 15693 en All - Demo - sev
@@ -789,6 +810,8 @@ spyfox2 SPY Fox 2: Some Assembly Required
7222f260253f325c21fcfa68b5bfab67 -1 us All - Demo - Kirben
732845548b1d6c2da572cb6a1bf81b07 -1 de All - Demo - Joachim Eberhard
e62056ba675ad65d8854ab3c5ad4b3c0 -1 en Windows - Mini Game - Trekky
+ 22de86b2f7ec6e5db745ed1123310b44 15832 fr Windows - Demo - George Kormendi
+ 204453e33456c4faa26e276229fe5b76 14689 de Windows - Demo - George Kormendi
19bf6938a94698296bcb0c99c31c91a7 -1 gb Windows - Demo - eriktorbjorn
49a1739981a89066b1121fac04b710f4 5756234 All All HE CUP Preview - sev